"Eloquent ORM非常好,但我想知道是否有一种简便的方法来使用innoDB设置MySQL事务,就像PDO那样,或者我是否需要扩展ORM以使其成为可能?"
DB::transaction(function() {
//
});
闭包内的所有内容都在一个事务中执行。如果发生异常,它将自动回滚。
如果您不喜欢匿名函数:
try {
DB::connection()->pdo->beginTransaction();
// database queries here
DB::connection()->pdo->commit();
} catch (\PDOException $e) {
// Woopsy
DB::connection()->pdo->rollBack();
}
更新: 对于 Laravel 4,pdo
对象不再是公共的,因此:
try {
DB::beginTransaction();
// database queries here
DB::commit();
} catch (\PDOException $e) {
// Woopsy
DB::rollBack();
}
DB::beginTransaction()
、DB::commit()
和DB::rollback()
。这会使代码更加简洁。 - FloriDB::connection()->getPdo()->beginTransaction();
- insteadDB::transaction
更加简洁,但缺点是如果您需要为不同的异常指定不同的处理程序,则必须返回到 try/catch 技术。 - OzzyTheGiant如果要避免闭包,而又乐于使用门面(facades),以下方法可以保持代码整洁明了:
try {
\DB::beginTransaction();
$user = \Auth::user();
$user->fill($request->all());
$user->push();
\DB::commit();
} catch (Throwable $e) {
\DB::rollback();
}
如果任何语句失败,提交将永远无法执行,事务也不会处理。如果您想使用Eloquent,您也可以使用此代码。
这只是我的项目中的示例代码。
/*
* Saving Question
*/
$question = new Question;
$questionCategory = new QuestionCategory;
/*
* Insert new record for question
*/
$question->title = $title;
$question->user_id = Auth::user()->user_id;
$question->description = $description;
$question->time_post = date('Y-m-d H:i:s');
if(Input::has('expiredtime'))
$question->expired_time = Input::get('expiredtime');
$questionCategory->category_id = $category;
$questionCategory->time_added = date('Y-m-d H:i:s');
DB::transaction(function() use ($question, $questionCategory) {
$question->save();
/*
* insert new record for question category
*/
$questionCategory->question_id = $question->id;
$questionCategory->save();
});
question->id
表达式返回零。 - Christos PapoulasMail::to()
吗?或者只能放置与数据库相关的事务? - Blues Clues我确定你不是在寻找一个结束方案,尝试这个更紧凑的解决方案。
try{
DB::beginTransaction();
/*
* Your DB code
* */
DB::commit();
}catch(\Exception $e){
DB::rollback();
}
出于某种原因,在任何地方都很难找到这些信息,所以我决定在这里发布它,因为我的问题与Eloquent事务有关,而正好是更改以下内容。
阅读此stackoverflow答案后,我意识到我的数据库表使用的是MyISAM而不是InnoDB。
对于Laravel(或任何其他地方)要使事务工作,需要将表设置为使用InnoDB
为什么?
引用MySQLTransactions and Atomic Operations文档 (此处):
MySQL Server (version 3.23-max and all versions 4.0 and above)支持使用InnoDB和BDB事务存储引擎的事务。InnoDB提供完整的ACID合规性。请参见第14章 存储引擎。有关InnoDB在处理事务错误方面与标准SQL不同之处的信息,请参见第14.2.11节 “InnoDB错误处理”。
MySQL服务器中的其他非事务性存储引擎(例如MyISAM)遵循称为“原子操作”的数据完整性不同范例。从事务角度看,MyISAM表实际上始终在autocommit = 1模式下运行。原子操作通常提供可比较的完整性和更高的性能。
由于MySQL服务器支持这两种范例,因此您可以决定使用原子操作的速度还是使用事务特性。这个选择可以基于每个表进行。
try{
DB::beginTransaction();
/*
* SQL operation one
* SQL operation two
..................
..................
* SQL operation n */
DB::commit();
/* Transaction successful. */
}catch(\Exception $e){
DB::rollback();
/* Transaction failed. */
}
最好和清晰的方式:
DB::beginTransaction();
try {
DB::insert(...);
DB::insert(...);
DB::insert(...);
DB::commit();
// all good
} catch (\Exception $e) {
DB::rollback();
// something went wrong
}