2016-01-08 14 views
10

Ho trovato this answer sull'argomento, ma non funziona per me.Modifiche di Laravel create_at all'aggiornamento

Quindi, faccio una voce nel database:

// Write lead to database 
$lead = Lead::create($lead_data); 

E i timestamp simile a questa, che è buono:

| 2016-01-08 10:34:15 | 2016-01-08 10:34:15 | 

Ma poi faccio una richiesta a un server esterno, e ho bisogno di aggiornare la riga:

$lead->user_id = $response['user_id']; 
$lead->broker_id = $response['broker_id']; 
$lead->save(); 

e il campo created_at viene cambiato:

| 2016-01-08 04:34:17 | 2016-01-08 10:34:17 | 

Come posso risolvere questo problema?

EDIT

Ho bisogno di una soluzione che sarebbe solo modificare il comportamento senza eliminazione di colonne o ripristino migrazioni. La correzione deve essere eseguita su un database live senza toccare i dati. Come suggerito di seguito, ho provato la seguente migrazione:

$table->datetime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'))->change(); 

ma non succede nulla. Il campo created_at viene ancora modificato durante l'aggiornamento.

+0

Come si carica la variabile $ lead prima di eseguire l'aggiornamento? –

+0

La variabile '$ lead' viene riempita con il metodo' create', ma in ogni caso, ho provato anche con '$ lead = Lead :: find ($ lead-> id);' dopo la scrittura, il problema persiste. – Skatch

risposta

21

Se si utilizza Laravel 5.2 e si utilizza MySQL, è stato introdotto un po 'di "bug" con i timestamp. Puoi leggere tutto sul problema su github here. Ha a che fare con i valori predefiniti di timestamp e MySQL assegna automaticamente gli attributi DEFAULT CURRENT_TIMESTAMP o ON UPDATE CURRENT_TIMESTAMP in determinate condizioni.

Fondamentalmente, hai tre opzioni.

  1. Aggiornamento MySQL variabile:

Se si imposta la variabile explicit_defaults_for_timestamp-TRUE, nessuna colonna timestamp verrà assegnato il CURRENT_TIMESTAMP predefinito o ON UPDATE CURRENT_TIMESTAMP attribuisce automaticamente. Puoi leggere di più sulla variabile here.

  1. Usa i timestamp nullable:

Change $table->timestamps()-$table->nullableTimestamps(). Per impostazione predefinita, il comando crea campi data/ora che non sono annullabili. Utilizzando $table->nullableTimestamps(), i campi data/ora saranno annullabili e MySQL non assegnerà automaticamente il primo DEFAULT CURRENT_TIMESTAMP o ON UPDATE CURRENT_TIMESTAMP attributi.

  1. Definire i timestamp da soli:

Invece di usare $table->timestamps, utilizzare $table->timestamp('updated_at'); $table->timestamp('created_at'); te stesso. Assicurati che il tuo campo 'updated_at' sia il primo timestamp nella tabella, in modo che sarà quello che assegna automaticamente gli attributi DEFAULT CURRENT_TIMESTAMP o ON UPDATE CURRENT_TIMESTAMP.

+0

Ho bisogno di una soluzione che possa essere implementata su un database live. Reimpostare le migrazioni e rilasciare colonne non è un'opzione. – Skatch

3

Skatch - Penso che la tua soluzione di cui sopra non è del tutto giusta, ma è probaby bene in questo caso.

Il problema è che si sta ricevendo la data di PHP, non la data/ora di riferimento MYSQL predefinita per l'impostazione predefinita. Quando si esegue tale migrazione si finisce con una dichiarazione come questa:

alter table alter column created_at default '2016:02:01 12:00:00'; 

Si noti la stringa per la data. Quando si esegue la migrazione, quella data verrà sempre utilizzata per il tuo created_at, non la data corrente in cui un record viene aggiunto giorni dopo.

Invece di eseguire "data ('Y: m: d H: i: s')", è possibile eseguire DB :: raw ('current_timestamp') per risolvere questo problema.

(SRY, non poteva solo aggiungere un commento sopra - la mia reputazione non è abbastanza alta ancora ...)

+0

Hai ragione, non ci ho pensato. Comunque, ho provato di tutto, incluso il tuo suggerimento '$ table-> datetime ('created_at') -> default (DB :: raw ('CURRENT_TIMESTAMP')) -> change();', ma questo era l'unico modo in cui funzionava ... La prossima volta proverò meglio a farlo con SQL. – Skatch

+1

Hai bisogno di farlo tramite una migrazione? Il comando nativo SQL è diretto: "alter table mytable modifica colonna mycolumn timestamp default current_timestamp NOT NULL su update current_timestamp;" Esegui direttamente sul DB e tutto dovrebbe essere risolto. (prova prima!). Se DEVI farlo tramite una migrazione, puoi farlo con DB :: unprepared ($ MyRawSQL) ;. Qualcosa come la funzione pubblica up() {Schema :: create (....); DB :: impreparato ($ MySQL); } – sgrover

+0

- Evita anche il bug che @patricus ha menzionato. – sgrover

1

questo distacco come una risposta di alto livello, che riassume il nostro commento alla discussione.

Innanzitutto, è stata introdotta una data bug in Laravel, come indicato da @patricus. Le soluzioni suggerite nella discussione dei bug sono l'uso di nullableTimestamps() invece di solo timestamp(), o per creare direttamente i campi created_at e updated_at - $table->timestamp('updated_at')->change().

Questo può anche essere risolto con SQL raw. Un'istruzione ALTER simile a questo

alter table loader_rawvalues MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 

che possono essere applicati direttamente sulle vostre tavole DB esistenti (test per primo, o corso!). OPPURE è possibile utilizzare DB :: unprepared() per applicarlo dalla migrazione, ad esempio:

class CreateMyTable extends Migration 
{ 
    public function up() 
    { 
     Schema::create('mytable', function (Blueprint $table) { 
      $table->bigIncrements('id'); 
      // ... 
      $table->timestamps(); 
     }); 

     DB::unprepared('alter table mytable MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'); 
    } 
} 
+0

Penso che sia necessario modificare il campo created_at senza un'istruzione 'ON UPDATE', updated_at funziona bene.:) – Skatch

+0

Per confermare, se è necessario eseguire una migrazione per risolvere il problema updated_at, in base alla soluzione di sgrover è possibile aggiungere quanto segue alla migrazione per tutte le tabelle che richiedono il fissaggio senza interruzioni: 'DB :: non preparato (' alterano faq tavolo modificare colonna created_at timestamp predefinito CURRENT_TIMESTAMP NOT NULL '); ' insieme ' DB :: impreparati (' alter domande frequenti tavolo modificare colonna updated_at CURRENT_TIMESTAMP timestamp predefinita NOT NULL '); ' questo imposterà il tIMESTAMP per impostare l'impostazione predefinita sul TIMESTAMP CORRENTE e rimuovere la regola aggiuntiva ON UPDATE. –