【问题标题】:Laravel 4 database statement create triggerLaravel 4 数据库语句创建触发器
【发布时间】:2013-03-15 13:53:05
【问题描述】:

在创建应用迁移文件的过程中,我注意到 Laravel 不支持数据库触发器!我已经接受了这样一个事实,即我需要执行一个查询语句来完成此操作,但这也给我带来了麻烦。这是我的应用程序中的代码 sn-p:

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

当我运行 artisan migrate 时,它​​给了我以下错误:

[例外]
SQLSTATE [HY000]:一般错误:2030 准备好的语句协议尚不支持此命令(SQL:CREATE TRIGGER users_trigger_uuid BEFORE INSERT ON users FOR EACH ROW SET NEW.uuid = UUID())(绑定:数组( ))

除了创建我自己的 PDO 对象并在 Laravel 之外执行查询之外,还有其他解决方案吗?这是 MySQL 异常还是 Laravel 异常?

编辑

从例外情况来看,很明显准备好的语句不支持触发器的创建。不知道为什么,但会喜欢一些见解。为了解决这个问题,我只运行了自己的 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()');

【问题讨论】:

  • 虽然您选择的答案很简单而且“雄辩”,但它并没有解决严重的数据库完整性问题。您应该尝试将数据库代码包装在事务中,这样如果有任何失败,一切都会失败。
  • 你运气好吗?

标签: mysql database triggers pdo laravel


【解决方案1】:

使用 DB::unprepared(),就像一个魅力。

【讨论】:

    【解决方案2】:

    “干净”的方法是使用数据库事件。当你创建一个新的 User 实例时,Laravel4 会触发一个 created 事件。

    Eloquent 模型会触发多个事件,让您可以连接到各种 使用以下方法在模型的生命周期中点:创建, 创建、更新、更新、保存、保存、删除、删除。

    每当第一次保存新项目时,创建和 创建的事件将触发。如果一个项目不是新的并且保存方法是 调用,更新/更新事件将触发。在这两种情况下, 保存/保存的事件将触发。

    因此,在您的 User 类中,为 creating 事件添加一个侦听器:

    class User extends Eloquent ... {
    
        // ...
    
        public static function boot()
        {
            parent::boot();
            static::creating(function($user)
            {
                $user->uuid = uuid();
            });
        }
    

    有关如何在 PHP 中生成 UUID,请参阅this answer

    【讨论】:

    • 需要非常小心地使用此解决方案。看起来数据库修改代码并没有包装在事务中。如果您不小心,您的数据库最终可能会处于糟糕的状态。
    • 创造应该是原子的;在这里,我们正在修改一个 tuple,然后它实际上是 INSERTed。但是,可以通过修改或覆盖 "vendor/laravel/framework/src/Illuminate/Database/Connection.php run() 方法来处理语句。
    【解决方案3】:

    您在编辑中显示的解决方案不正确。您应该使用DB::unprepared(),或者,如果您必须使用 PDO,不要那样做。相反,从连接中获取一个 PDO 对象并使用它:

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

    【讨论】:

      猜你喜欢
      • 2016-02-25
      • 1970-01-01
      • 2013-08-24
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多