2013-03-25 12 views
6

Durante il processo di creazione dei file di migrazione della mia app, ho notato che Laravel non supporta i trigger di database! Sono venuto a patti con il fatto che ho bisogno di eseguire un'istruzione di query per ottenere questo risultato, ma che è anche dando mi turba .. Ecco un frammento di codice dalla mia app:Istruzione di database Laravel 4 creare trigger

Schema::create('users', function ($table) { 
    $table->increments('id'); 
    $table->string('uuid', 36); 
    $table->string('email', 255); 
    $table->string('password', 255); 
}); 
DB::statement('CREATE TRIGGER users_trigger_uuid BEFORE INSERT ON users FOR EACH ROW SET NEW.uuid = UUID()'); 

quando corro artigianale migrazione mi dà il seguente errore:

[Exception]
SQLSTATE[HY000]: General error: 2030 This command is not supported in the prepared statement protocol yet (SQL: CREATE TRIGGER users_trigger_uuid BEFORE INSERT ON users FOR EACH ROW SET NEW.uuid = UUID()) (Bindings: array ( ))

Esistono soluzioni Oltre a creare il mio proprio oggetto PDO e l'esecuzione della query al di fuori di laravel? Questa è un'eccezione MySQL o un'eccezione di Laravel?

EDIT

A giudicare dalla deroga, è chiaro che le dichiarazioni preparate non supportano la creazione di trigger .. non so perché, ma mi piacerebbe una certa comprensione. Per aggirare questo ho appena eseguito la mia query PDO.

$default_driver = Config::get('database.default'); 
$connection_info = Config::get('database.connections.' . $default_driver); 
$conn = new PDO('mysql:host=' . $connection_info['host'] . ';dbname=' . $connection_info['database'], $connection_info['username'], $connection_info['password']); 
$conn->query('CREATE TRIGGER users_trigger_uuid BEFORE INSERT ON ' . $connection_info['prefix'] . 'users FOR EACH ROW SET NEW.uuid = UUID()'); 
+0

mentre la risposta che hai selezionato è semplice ed 'eloquente' non affronta un serio problema di integrità del database. Dovresti provare a racchiudere il codice del database in una transazione in modo che se qualcosa non va a buon fine, fallisce tutto. –

+0

Hai avuto fortuna con questo? – laviku

risposta

8

Utilizzare DB :: unprepared(), funziona come un fascino.

2

La soluzione visualizzata nella modifica non è corretta. È necessario utilizzare DB::unprepared() o, se è necessario utilizzare PDO, non farlo in questo modo. Invece, ottenere un oggetto PDO dalla connessione e l'uso che:

$pdo = DB::connection()->getPdo();

4

Il modo "pulito" per farlo è quello di utilizzare eventi del database. Quando crei una nuova istanza utente, Laravel4 lancia un evento created.

Eloquent models fire several events, allowing you to hook into various points in the model's lifecycle using the following methods: creating, created, updating, updated, saving, saved, deleting, deleted.

Whenever a new item is saved for the first time, the creating and created events will fire. If an item is not new and the save method is called, the updating/updated events will fire. In both cases, the saving/saved events will fire.

Quindi, all'interno della vostra classe User, aggiungere un listener per l'evento creating:

class User extends Eloquent ... { 

    // ... 

    public static function boot() 
    { 
     parent::boot(); 
     static::creating(function($user) 
     { 
      $user->uuid = uuid(); 
     }); 
    } 

Per come generare un UUID in PHP, vedere this answer.

+0

deve essere molto attento all'utilizzo di questa soluzione. Non sembra che il codice di modifica del database sia incluso in una transazione. Il tuo database potrebbe finire in uno stato terribile se non stai attento. –

+0

La creazione dovrebbe essere atomica; qui stiamo modificando una * tupla * prima che sia effettivamente 'INSERT'ed. È tuttavia possibile eseguire le istruzioni modificando o sovrascrivendo il metodo "vendor/laravel/framework/src/Illuminate/Database/Connection.php'' run()'. – LSerni