2013-03-25 17 views
6

Podczas procesu tworzenia plików migracji mojej aplikacji zauważyłem, że Laravel nie obsługuje wyzwalaczy bazy danych! I pogodzić się z faktem, że muszę wykonać instrukcję zapytania do osiągnięcia tego celu, ale również daje mi kłopoty .. Oto fragment kodu z mojej aplikacji:Instrukcja Laravel 4 Utwórz wyzwalacz

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()'); 

Kiedy biegnę rzemieślnik migrują to daje mi następujący błąd:

[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 ( ))

Czy są jakieś rozwiązania oprócz tworzenia własnego obiektu PDO i wykonywania zapytania poza Laravel? Czy jest to wyjątek MySQL lub wyjątek Laravel?

EDIT

Sądząc po wyjątku, to jasne, że przygotowane oświadczenia nie wspierać tworzenie wyzwalaczy .. nie wiem, dlaczego, ale chcielibyśmy pewien wgląd. Aby obejść to, po prostu uruchomiłem własne zapytanie 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

, podczas gdy wybrana odpowiedź jest prosta i "elokwentna", nie rozwiązuje problemu poważnej integralności bazy danych. Powinieneś spróbować owinąć kod bazy danych w transakcję, aby wszystko zawieść, jeśli coś się nie powiedzie. –

+0

Czy miałeś szczęście? – laviku

Odpowiedz

2

Rozwiązanie wyświetlane podczas edycji jest nieprawidłowe. Powinieneś użyć DB::unprepared() lub, jeśli musisz użyć PDO, , nie rób tego w ten sposób. Zamiast uzyskać obiekt PDO z połączenia i używać:

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

4

„czystym” sposobem, aby to zrobić jest użycie wydarzenia bazy. Podczas tworzenia nowej instancji użytkownika program Laravel4 uruchamia zdarzenie 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.

Więc wewnątrz klasy User dodać detektor dla zdarzenia creating:

class User extends Eloquent ... { 

    // ... 

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

Na jak wygenerować UUID w PHP, zobacz this answer.

+0

należy bardzo ostrożnie używać tego rozwiązania. Nie wygląda na to, że kod modyfikujący bazę danych jest zawarty w transakcji. Twoja baza danych może skończyć się okropnym stanem, jeśli nie będziesz ostrożny. –

+0

Kreacja powinna być atomowa; tutaj modyfikujemy * krotkę *, zanim faktycznie jest 'INSERT'ed. Możliwe jest jednak wykonywanie instrukcji przez modyfikowanie lub nadpisywanie metody 'vendor/laravel/framework/src/Illuminate/Database/Connection.php'' run() '. – LSerni