I'm trying to rename fields and update values on already inserted rows in cakephp migrations.
Workflow:
In before method i fetch all already added rows in my db so i will be able to update them in after method.
Then migration happens, which create columns value_from and value_to and also drops columns price_from and price_to
Then i try in my after method fetch all "new" rows, where i wan't to update values from old ones, but error happens, because find('all') method throws errors
My code:
class ShippingTypeCostCalculationM1483610977ProjectPluginLogistics extends CakeMigration {
/**
* Data which will be inserted in modified table shipping costs
* @var
*/
private $data;
/**
* Migration description
*
* @var string
* @access public
*/
public $description = '';
/**
* Actions to be performed
*
* @var array $migration
* @access public
*/
public $migration = array(
'up' => array(
'create_field' => array(
'shipping_costs' => array(
'shipping_type' => array('type' => 'string', 'null' => false, 'default' => 'order_sum', 'length' => 20, 'collate' => 'utf8_unicode_ci', 'charset' => 'utf8', 'after' => 'customer_type'),
'value_from' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4', 'after' => 'shipping_type'),
'value_to' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4', 'after' => 'value_from'),
),
),
'drop_field' => array(
'shipping_costs' => array('price_from', 'price_to',),
)
),
'down' => array(
'drop_field' => array(
'shipping_costs' => array('shipping_type', 'value_from', 'value_to',),
),
),
'create_field' => array(
'shipping_costs' => array(
'price_from' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4'),
'price_to' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4'),
),
)
);
/**
* Before migration callback
*
* @param string $direction, up or down direction of migration process
* @return boolean Should process continue
* @access public
*/
public function before($direction) {
$shippingCost = ClassRegistry::init('Logistics.ShippingCost');
$this->data = $shippingCost->find('all');
return true;
}
/**
* After migration callback
*
* @param string $direction, up or down direction of migration process
* @return boolean Should process continue
* @access public
*/
public function after($direction) {
$shippingCost = ClassRegistry::init('Logistics.ShippingCost');
// This is where error happens
$shippingCosts = $shippingCost->find('all');
foreach ($this->data as $item) {
$shippingCost = $shippingCosts->get($item['shipping_costs']['id']);
$shippingCost->value_from = $item['shipping_costs']['price_from'];
$shippingCost->value_to = $item['shipping_costs']['price_to'];
$shippingCosts->save($shippingCost);
}
return true;
}
}
PROBLEM: In after method, cake php is still trying to fetch values like price_from or price_to which are already deleted.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ShippingCost.price_from' in 'field list'
How can i overcome my problem? If you need any additional informations, please let me know and i will provide. Thank you in advance!
You run the callbacks in any case, the code is always executed.
public function after($direction) {...}
See the argument? This can be up
and down
. You need to wrap your code that you want to run before or after applying the migration accordingly in a check like if ($direction === 'down') { ... }
.
Also I don't think your approach is well done. If you have a lot of data you can run out of memory.
Create a migration that will add the new fields. Then another migration file that will just do the data transformation and process the data in chunks. And a third one that will delete the no longer needed fields after that. The simple reason is: Separate data from schema changes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.