All models use dynamic update, but periodically error message appears
Same problem was in previous versions.
According to doc http://docs.phalconphp.com/en/1.3.0/reference/models-cache.html#overriding-find-findfirst you may override find and findFirst method. As I understand problem appears when save failed and refresh is performed, which also uses those methods.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
I have the same issue.
Same here.
Could anyone of you post a test to reproduce the issue?
I get the same error. I use a custom behavior to maintain timestamps and revisions.
My Behavior: http://pastebin.com/znfmLdQT
Phalcon version: 1.3.1
PHP: 5.5.10
Ubuntu
I initialize my model with:
public function initialize(){
$this->addBehavior(new KitCloud\Model\DefaultBehavior());
$this->keepSnapshots(true);
}
I have also added a function to get the previous value of the field in the Behavior class:
public function _getSnapshotField($field) {
return (isset($this->_snapshot[$field]) ? $this->_snapshot[$field] : false);
}
Exception:
Phalcon\Mvc\Model\Exception Object
(
[message:protected] => The record doesn't have a valid data snapshot
[string:Exception:private] =>
[code:protected] => 0
[file:protected] => mypath\Model\DefaultBehavior.php
[line:protected] => 27
[trace:Exception:private] => Array
(
[0] => Array
(
[file] => mypath\Model\DefaultBehavior.php
[line] => 27
[function] => getChangedFields
[class] => Phalcon\Mvc\Model
[type] => ->
[args] => Array
(
)
)
)
Reproduction of the error in Phalcon 1.3.1
@phalcon https://gist.github.com/SquareOfPi/a7f1910377cf2501599f
Is there any update on this?
Bump. I am experiencing this problem also.
I did a test right now. I am working with serialized data from a session, and got this error when I unserialized a session and executed "$user-update()". When I loaded a new Model I did not get the error:
$user = unserialize($this->session->get('user'));
$user = User::findFirst("id=".$user->id);
$user->testfield = 1;
$user->update();
+1 get same error when using behavior and trying to catch beforeSave event
+1 same here. Does anybody know of some workaround or dirty quick fix?
In my case it turned out that I had the
$this->keepSnapshots(true);
in the parent class and when I overrode initialize() in the child class I forgot to call parent::initialize(); first. :)
Unfortunately this is not my case.
This bug only occurs if the entity has been created before during the same script execution.
_Phalcon version 1.3.4_
This is my User dummy model
<?php
class User extends \Phalcon\Mvc\Model {
public function initialize() {
$this->keepSnapshots(true);
}
}
$user = new \User();
// also tried $this->getDI()->get('modelsManager')->keepSnapshots($user, true);
echo $user->getModelsManager()->isKeepingSnapshots($user) . '<br>';
$user->create([
'firstName' => 'foo',
'lastName' => 'bar',
'password' => 'test'
]);
// also tried $user->refresh();
$user->firstName = 'test';
$user->save();
echo $user->getModelsManager()->isKeepingSnapshots($user) . '<br>';
var_dump($user->getSnapshotData());
1
NULL
$user = \User::findFirst(1);
$user->firstName = 'test';
$user->save();
var_dump($user->getSnapshotData());
array(4) {
["userID"]=>
string(2) "1"
["firstName"]=>
string(3) "test"
["lastName"]=>
string(4) "bar"
["password"]=>
string(4) "test"
}
Or am I missing something?
100% reproducible, just call getChangedFields() for object not yet saved or loaded from db (newly created).
I've tried getChangedFields() with Create and Update steps posted by Dusan but it just returns 'The record doesn't have a valid data snapshot'.
To fix the 'The record doesn't have a valid data snapshot' you need to do one of the two things:
The bug is that setSnapshotData() is called internally only when you fetch data from database, and is NOT called when you save data or simply assign fields. If it's not a bug, it needs to be at least documented.
@msty thanks for fix, maybe in version 2 will correct
I'm having the same issue when fetching multiple records in a loop using findFirst and then later updating them again in another loop based on some conditions. @msty the fix works but can you give me some more insight on why it works ?
create, update does NOT work.
is there a better solution than mine? ty
public function beforeCreate() {
$this->setSnapshotData($this->toArray());
}
public function afterSave() {
if ($this->hasChanged('field')) {
//do stuff..
}
}
Are you using Phalcon >= 2.0.7?
Yes the bleeding edge ;)
+1 same here. Currently use jturbide's solution
+ 1 same here on 2.0.7.
+1 same here on 2.1.x beta
Seeing this issue also on 2.0.8. Any workarounds in the meantime?
When writing the unit test I discovered an issue that my model wasn't properly loaded. The unit test below works for me now.
<?php
class Issue1867Robots extends Phalcon\Mvc\Model
{
public $name_changed=false;
public function initialize()
{
$this->useDynamicUpdate(true);
$this->keepSnapshots(true);
}
public function getSource()
{
return 'robots';
}
public function afterSave()
{
if ($this->hasChanged("name")){
$this->name_changed = true;
}
}
}
<?php
/*
+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2015 Phalcon Team (http://www.phalconphp.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
| |
| If you did not receive a copy of the license and are unable to |
| obtain it through the world-wide-web, please send an email |
| to [email protected] so we can send you a copy immediately. |
+------------------------------------------------------------------------+
| Authors: Andres Gutierrez <[email protected]> |
| Eduar Carvajal <[email protected]> |
| Vladimir Kolesnikov <[email protected]> |
+------------------------------------------------------------------------+
*/
/**
* This test has to be in a separate file and cannot be combined with ModelsTest
*/
class Issue1801 extends PHPUnit_Framework_TestCase
{
public function __construct()
{
spl_autoload_register(array($this, 'modelsAutoloader'));
}
public function __destruct()
{
spl_autoload_unregister(array($this, 'modelsAutoloader'));
}
public function modelsAutoloader($className)
{
if (file_exists('unit-tests/models/'.$className.'.php')) {
require 'unit-tests/models/'.$className.'.php';
}
}
protected function _getDI($dbService)
{
Phalcon\DI::reset();
$di = new Phalcon\DI\FactoryDefault();
$di->set('db', $dbService, true);
return $di;
}
public function test1867Mysql()
{
require 'unit-tests/config.db.php';
if (empty($configMysql)) {
$this->markTestSkipped("Skipped");
return;
}
$di = $this->_getDI(function(){
require 'unit-tests/config.db.php';
$db = new Phalcon\Db\Adapter\Pdo\Mysql($configMysql);
return $db;
});
$this->issue1867($di);
}
protected function issue1867($di)
{
$robot = Issue1867Robots::findFirst(1);
$robot->name = time();
$robot->save();
$this->assertTrue($robot->name_changed);
}
}
+1 same here on 2.09 on centOS
In my code, getSnapshotData() & hasChanged('startDate') are invoked in the afterUpdate() in the model.
When I first create[$object->create()] this model object, then update this object. The issue emerge.
But after the creation. If getting the object again [$object = Model::findFIrst($object->ID]. then update the object. There was no such issue.
BTW. Only $object->refresh() could not fix the issue.
In my case it works fine on update, it just fails while creating new records.
I'd like to be able to get the initial data entered in the model via getChangedFields() and save it in an audit log.
The 1.3.x version is no longer supported.
It's happening in 2.0.8.
Should getChangedFields work on newly created records as well?
Create separated issue please. Provide script to reproduce
@ignaciovazquez when saving, are you saving a single model or a model and its related records?
@tegaphilip It was a single model. I solved this some time ago, but I don't remember exactly what the fix was. It had to do with saving the object twice in the same script.
@ignaciovazquez you are right. i solved mine just now. was saving the object twice. first on its own , then saving it with its related model. separated the saves and it was fixed. thanks.
I'm glad I could help.
I still think it's a bug. Saving it twice shouldn't be causing this issue.
I have the same problem in 2.01r
+1 2.0.8
The issue is still present in 2.0.10. DusanBrejka posted a detailed explanation for the issue with code example. There shouldn't be any problem to reproduce it.
@hakimio Could you please open new issue with script to reproduce?
2.0.13
1) Create with transaction
2) Later update in same transaction
3) With hasChanged('fieldName') in beforeValidationOnUpdate hook, it will throw Internal Error: The record doesn't have a valid data snapshot