I have a relatively simple entries model with just five fields:
So, nothing fancy. Now a single form can have multiple entries (both already existing ones and new ones just created), the form is extended via ajax calls.
When I submit the form $this->data
looks like this:
Array
(
[Entry] => Array
(
[date] => 2011-01-07
[0] => Array
(
[id] => 1
[type] => Eat
[amount] => 1 Steak, one baked potatoe
[unit] => lunch
[time] => Array
(
[hour] => 13
[min] => 31
)
)
[1] => Array
(
[type] => weight
[amount] => 78.5
[unit] => KG
[time] => Array
(
[hour] => 22
[min] => 22
)
)
)
)
The first entry in $this->data['Entry']['date']
is the date that shall be used by ALL the entries. And since also the user_id is missing I created a "beforeSave" function in the entry-model. It looks like this:
function beforeSave() {
App::import('Component','Session');
$this->Session = new SessionComponent();
if (isset($this->data) && isset($this->data['Entry'])) {
$date = $this->data['Entry']['date'];
unset($this->data['Entry']['date']);
foreach ($this->data['Entry'] as $n => $entry) {
if (is_array($entry)) {
$this->data['Entry'][$n]['date'] = $date . ' ' . $entry['time']['hour'] . ':' . $entry['time']['min'] . ':00';
$this->data['Entry'][$n]['user_id'] = $this->Session->read('Auth.User.id');
}
}
debug($this->data);
}
return true;
}
I remove the date, add it together with the time entry of the user, thus creating a mysql datetime entry and add the user_id of the logged in user. Straightforward, really. The resulting array (as output by that last debug()
) looks like the following:
Array
(
[Entry] => Array
(
[0] => Array
(
[id] => 1
[type] => Eat
[amount] => 1 Steak, 1 baked potatoe
[unit] => lunch
[time] => Array
(
[hour] => 09
[min] => 31
)
[date] => 2011-01-07 09:31:00
[user_id] => 2
)
[1] => Array
(
[type] => Weight
[amount] => 78.5
[unit] => KG
[time] => Array
(
[hour] => 22
[min] => 22
)
[date] => 2011-01-07 22:22:00
[user_id] => 2
)
)
)
So it look exactly like I want it to look and it should be easily saved. But when I use $this->Entry->saveAll($this->data['Entry']
) to save all the entries, not only does it not work, but when I debug $this->data
directly after the saveAll, it looks exactly like before the saveAll function - the date is back in the array, the entries do not have a date or user_id entry.
I can see that beforeSave is called, I can see that it changes $this->data
, but somewhere between the end of beforeSave and the usage of "saveAll" all my changes get lost and $this->data
is reverted to it's original state. Therefore no saving takes place.
I had similar problem trying to implement some sanitization with hasMany through. As it turns out the problem lies in how saveAll() works. The $this->data in controller isn't the same as $this->data in Model::beforeSave() callback and the two are not synchronized. When You call Model::saveAll() passing $this->data from the controller You explicitly give the model "the old version" of data array. And when You look into saveAll definition in cake/libs/model/model.php it just does:
if (empty($data)) {
$data = $this->data
}
and nothing more to sync up the modified $data array in model and passed by parameter $data form the controller. The solution is to not pass the data to saveAll() but instead set the data on model first using Model::set() and then call Model::saveAll() (without the $data parameter).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With