hasChange does not detect all changes - Cache problem?

19 views
Skip to first unread message

Marcello Fontolan

unread,
May 3, 2015, 8:53:41 PM5/3/15
to redbe...@googlegroups.com
  Hi,

  My project requires a changelog off almost all database changes for auditing.
  My first "TimeMachine" version was using the RedBean logger but the result is too verbose and big.
  I decided use the Model instead but I detect a issue.

  Load a bean with the property 'cliente_id = 580'.
  Change to 'cliente_id = 1' and store are detected at 'hasChanged'.
  Change to 'cliente_id = 290' and store are detected at 'hasChanged'.
  Change to 'cliente_id = 580' and store are NOT detected at 'hasChanged'.
  
  This is a spectated behavior or a cache problem?

  Regards,

  Marcello Fontolan


<?php

require_once 'rb.php';

class TimeMachineItem {

public $name;
public $old;
public $new;

public function __construct($name, $old, $new) {
$this->name = $name;
$this->old = $old;
$this->new = $new;
}

}

class TimeMachine {

public $tabela;

/** @var TimeMachineItem[] */
protected $itemList = [];

public function __construct($tabela) {
$this->tabela = $tabela;
}

public function add_item($item) {
$this->itemList[] = $item;
}

public function count_item() {
return count($this->itemList);
}

}

class Model_Base extends RedBean_SimpleModel {

public function after_update() {
$timeMachine = new TimeMachine(get_class($this));
foreach ($this->bean as $k => $v) {
if ($this->bean->hasChanged($k)) {
$timeMachine->add_item(new TimeMachineItem($k, $this->bean->old($k), $this->bean[$k]));
}
}
if (!empty($timeMachine->count_item())) {
echo '<p>changed</p>';
echo print_r($timeMachine, true);
}
}

}

class Model_Cliente extends Model_Base {
}

class Model_Participante extends Model_Base {
}

class Model_Boleto extends Model_Base {
}

define('DBHOST', '127.0.0.1');
define('DBNAME', '');
define('DBUSER', '');
define('DBPASS', '');
R::setup('mysql:host=' . DBHOST . '; dbname=' . DBNAME, DBUSER, DBPASS);
R::freeze();
R::setAutoResolve(true);

echo '<pre>';

// original cliente_id = 580
$p = R::load('participante', 1);
$p->cliente = R::load('cliente', 1);
/* ok, detect change at cliente_id to 1 */
R::store($p);

/* ok, detect change at cliente_id to 290 */
$p->cliente = R::load('cliente', 290);
R::store($p);

/* NOT ok, does not detect change at cliente_id to 580 */
$p->cliente = R::load('cliente', 580);
R::store($p);


gabor

unread,
May 9, 2015, 7:04:54 AM5/9/15
to redbe...@googlegroups.com, marf...@gmail.com


Hi,

I cannot possibly tell what's going on here.
Please do not send entire slices of applications to me, just a couple of lines of code clearly demonstrating the issue.


cheers
Gabor

Marcello Fontolan

unread,
May 9, 2015, 9:13:47 AM5/9/15
to redbe...@googlegroups.com
Sorry Gabor, noted!

In my tests 'hasChanged' and 'old' was unable to detect the changes in a bean if it is already stored before.
I dispense a bean and change a property name.
At this moment I have a new 'id', the new value of 'name' and old('id') = 0 and old('name') empty.
I store this bean.
Now I change the value of 'name'.
The hasChanged('id') still tell me that 'id' has changed and old('id') still = 0 but, at this moment there is no more changes in the 'id' property.
The old('name') still empty but new 'name' has the new value.
Same thing happens if a execute $bean->fresh() or if R::useWriterCache(FALSE).
But, if between R::store and the changes I reload the bean with R::load the hasChanged and 'old' works as expected.
Please let me know if my explanation is enough.

regards

Marcello Fontolan
 

--
You received this message because you are subscribed to a topic in the Google Groups "redbeanphp" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/redbeanorm/X5NY56wpWO0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to redbeanorm+...@googlegroups.com.
To post to this group, send email to redbe...@googlegroups.com.
Visit this group at http://groups.google.com/group/redbeanorm.
For more options, visit https://groups.google.com/d/optout.

gabor

unread,
May 9, 2015, 9:48:47 AM5/9/15
to redbe...@googlegroups.com, marf...@gmail.com

Okay,

Have you tried to clear the history?
Storing a bean does not clear the history automatically. This is because RedBeanPHP just keeps tracking the 'entire' history of a bean and it does not know
at which point 'you want a clean sheet'. It seems natural to erase the history after a store operation, but sometimes this is not what you want so I decided to
keep it manual:


$book = R::dispense('book');
$book
->title = 'my book';
var_dump
($book->hasChanged('title'));
R
::store($book);
var_dump
($book->hasChanged('title'));
$book
->clearHistory();
var_dump
($book->hasChanged('title'));
$book
->title = 'new';
var_dump
($book->hasChanged('title'));




Hope this helps
Cheers
Gabor



Marcello Fontolan

unread,
May 9, 2015, 10:08:30 AM5/9/15
to redbe...@googlegroups.com
Yes, this works but like you say, seems natural erase the history after a store.
There is a way to set this as default instead execute a "clearHistory" after every store?

regards

Marcello

gabor

unread,
May 9, 2015, 10:13:50 AM5/9/15
to redbe...@googlegroups.com, marf...@gmail.com


Not right now, unfortunately.
I could add this as a feature I guess.

Reply all
Reply to author
Forward
0 new messages