从 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();
如果系统无法到达最后一行,则不会向数据库提交任何内容。
我尝试在外部使用交易 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();
如果系统无法到达最后一行,则不会向数据库提交任何内容。