从 class 实例化 Eloquant 时事务不起作用

Transaction doesn't work when instantiating eloquant from a class

我尝试在外部使用交易 laravel。当我按原样在索引文件中包含 db 实例化时,它会起作用:

use Illuminate\Database\Capsule\Manager as Db;



$db = new Db;

$db->addConnection( [
    'driver'    => Settings::DATABASE_DRIVER,
    'host'      => Settings::DATABASE_HOST,
    'database'  => Settings::DATABASE_NAME,
    'username'  => Settings::DATABASE_USERNAME,
    'password'  => Settings::DATABASE_PASSWORD,
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => ''
] );

# Make this Capsule instance available globally via static methods... (optional)
$db->setAsGlobal();

然后我可以在其他地方使用这样的代码:

Db::connection()->beginTransaction();

# Create blog post in the database and return its id
$blogPostRecordId = ( new BlogDbModel() )->create( $_POST );
Db::connection()-> rollBack();

它将正确工作和回滚:没有在数据库中创建行。

但是,如果我从 class 获取数据库的实例,它将不起作用:

class DbSql
{

    /**
     * Use the eloquent query builder and orm. Bypass PDO interface.
     * @return Capsule
     */
    public function db()
    {
        $capsule = new Capsule;

        $capsule->addConnection( [
            'driver'    => Settings::DATABASE_DRIVER,
            'host'      => Settings::DATABASE_HOST,
            'database'  => Settings::DATABASE_NAME,
            'username'  => Settings::DATABASE_USERNAME,
            'password'  => Settings::DATABASE_PASSWORD,
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => ''
        ] );

        # Make this Capsule instance available globally via static methods... (optional)
        $capsule->setAsGlobal();

        // Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
        //$capsule->bootEloquent();


        return $capsule;
    }
}

然后使用

( new DbSql() )->db()->getConnection()->beginTransaction();

# Create blog post in the database and return its id
$blogPostRecordId = ( new BlogDbModel() )->create( $_POST );
( new DbSql() )->db()->getConnection()->rollBack();

它根本行不通,交易将被忽略。为什么从 class 实例化中获取数据库实例会使进程失败?我更愿意根据需要使用实例。

解决方案:数据库实例必须在所有需要事务的地方完全相同:

$dbInstance = ( new DbSql() )->db();

然后在要执行事务的任何地方使用 $dbInstance:

$dbInstance->connection()->beginTransaction();

以及任何 db eloquent 操作。因此根据需要传递 $dbInstance。好处是它可以在您代码中的任何位置:在您的模型、控制器中....

然后完成:

 $dbInstance->connection()->commit();

如果系统无法到达最后一行,则不会向数据库提交任何内容。