In CakePHP, come puoi determinare se un campo è stato cambiato in un'azione di modifica?
Domanda
Sto usando il cacheCounter
in CakePHP
, che incrementa un contatore per i campi correlati.
Esempio, ho una tabella Person una tabella Source. Person.source_id esegue il mapping a una riga nella tabella di origine. Ogni persona ha una Sorgente e ogni Sorgente ha nessuna o più righe Persona.
cacheCounter
funziona alla grande quando cambio il valore di una fonte su una persona. Incrementa Source.Person_Count
. Cool.
Ma quando aumenta, lo aggiunge alla fonte di destinazione per una persona, ma non lo rimuove dal vecchio valore. Ho provato updateCacheControl ()
in afterSave
, ma non ha fatto nulla.
Quindi ho scritto un codice nel mio modello per afterSave
che avrebbe sottratto l'origine source_id, ma lo ha sempre fatto anche quando non stavo nemmeno cambiando source_id
. (Quindi il conteggio è diventato negativo).
La mia domanda: esiste un modo per sapere se un campo è stato modificato nel modello in CakePHP
?
Soluzione
Per monitorare le modifiche in un campo, è possibile utilizzare questa logica nel modello senza apportare modifiche altrove:
function beforeSave() {
$this->recursive = -1;
$this->old = $this->find(array($this->primaryKey => $this->id));
if ($this->old){
$changed_fields = array();
foreach ($this->data[$this->alias] as $key =>$value) {
if ($this->old[$this->alias][$key] != $value) {
$changed_fields[] = $key;
}
}
}
// $changed_fields is an array of fields that changed
return true;
}
Altri suggerimenti
Con riferimento a Alexander Morland Rispondi.
Che ne dici di questo invece di scorrere in loop prima del filtro.
$result = array_diff_assoc($this->old[$this->alias],$this->data[$this->alias]);
Riceverai chiave oltre che valore.
Nella vista di modifica, includi un altro campo nascosto per il campo che desideri monitorare ma aggiungi il nome del campo con qualcosa come " _prev " e imposta il valore sul valore corrente del campo che desideri monitorare. Quindi, nell'azione di modifica del controller, fai qualcosa se i due campi non sono uguali. per es.
echo $form->input('field_to_monitor');
echo $form->hidden('field_to_monitor_prev', array('value'=>$form->value('field_to_monitor')));
Le modifiche avvengono raramente, quindi un'altra selezione prima di eseguire l'aggiornamento non è un grosso problema, quindi, recupera il record prima di salvare, salvalo, confronta i dati inviati nel modulo di modifica con i dati che hai recuperato dal db prima di te salvato, se è diverso, fare qualcosa.
Verifica se " salva " utilizza una sorta di chiamata DBAL che restituisce "righe interessate", in genere questo è il modo in cui è possibile giudicare se l'ultima query ha modificato i dati o in caso contrario. Perché se così non fosse, le righe interessate dopo un'istruzione UPDATE sono 0.
Puoi chiamare getAffectedRows () su qualsiasi classe di modello.
Dal modello di classe:
/**
* Returns the number of rows affected by the last query
*
* @return int Number of rows
* @access public
*/
function getAffectedRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastAffected();
}