现在有两张表#
wikis
id | title | content |
---|---|---|
标题 | 内容 |
tags
id | tag | wiki_id |
---|---|---|
标签 | 外键 |
一个wiki拥有多个标签,因此在model类里面建立如下关系
wiki类
public function aliases(){
return $this->hasMany('Tag');
}
Tag类
public function wiki(){
return $this->belongsTo('Wiki');
}
如何在创建wiki的时候同时保存好tags呢?
用save()的方式#
//先保存wiki
$wiki = Wiki::create(Input::only('title','content'));
//再逐个保存tags
if( !empty( Input::get('tags'))){
foreach (Input::get('tags') as $tag) {
$tg = new Tag(compact('tag'));
$wiki->tags()->save($tg);
}
}
用saveMany的方式#
//先保存wiki
$wiki = Wiki::create(Input::only('title','content'));
//再创建tag的对象集合
if( !empty( Input::get('tags'))){
foreach (Input::get('tags') as $tag){
$tags[] = new Tag(compact('tag'));
}
$wiki->tags()->saveMany($tags);
}
//一次性保存tags,猜测会比直接foreach要节省资源
从tag的角度保存#
//先保存wiki
$wiki = Wiki::create(Input::only('title','content'));
//逐个保存
if( !empty( Input::get('tags'))){
foreach (Input::get('tags') as $tag) {
$tg = new Tag(compact('tag'));
$tg->wiki()->associate($wiki);//把$tg关联到父对象$wiki
$tg->save();
}
}
但是这种方式的问题是,必须先保存wiki后再保存tag,但如果希望wiki和tag同时保存,如果tag不成功那么整个操作就回滚掉应该怎么办呢?难道不能使用InnoDB的事务处理机制吗?
尝试了一下push()
:#
从tag的角度2 用push#
$tag = new Tag();
$tag->tag = 'a tag';
$tag->wiki = new Wiki();
$tag->wiki->title = 'a title';
$tag->wiki->content = 'a content';
$tag->push();
//结果报错
// SQLSTATE[42S22]:
// Column not found: Unknown column 'wiki' in 'field list' (SQL:
// insert into `tags` (`tag`, `wiki`, `updated_at`, `created_at`)
// values (a tag,{"title":"a title","content":"a content"},
// 2014-11-05 04:20:30, 2014-11-05 04:20:30))
可以看出laravel 是打算直接把对象转化成字符串,存在表里面。
从wiki的角度用push#
$wiki = new Wiki();
$wiki->title = 'a name';
$wiki->content = 'a content';
$aliases = [
new Tag(['tag' => 'A new tag.']),
new Tag(['tag' => 'Another tag.']),
new Tag(['tag' => 'latest tag.']),
];
$wiki->aliases = $aliases;
$wiki->push();
//结果报错
//Parameter mismatch,
//pattern is a string while replacement is an array
没法用数组;
最后一招,用事务处理#
如果要使用方法很简单,将要执行的内容放到 DB::transaction(function(){})
中
DB::transaction(function(){
$wiki = Wiki::create(Input::only('title','content'));
if( !empty( Input::get('tags'))){
foreach (Input::get('tags') as $tag){
$al[] = new Alias(compact('tag'));
}
$wiki->aliases()->saveMany($al);
}
});
return 'ok';
如果要更优雅的话,可以运用仓库模式创建一个WikiRepository
提供save()
方法,将这些复杂的数据操作放进去。控制里面直接使用 WikiRepository::save()
即可;
一些高级的事务工具:#
//开启事务
DB::beginTransaction();
//回滚
DB::rollback();
//提交事务
DB::commit();
具体的可以参考:老外的文章
//开启事务
DB::beginTransaction();
try{
$wiki = Wiki::create(Input::only('title','content'));
}catch (ValidationException $e)
{
//如果验证失败,回滚
DB::rollback();
return Redirect::to('/form')
->withErrors( $e->getErrors() )
->withInput();
} catch(\Exception $e)
{
//如果异常,回滚
DB::rollback();
throw $e;
}
try{
foreach( Input::get('tags') as $tag ){
$t = Tag::create([
'tag'=>$tag,
'wiki_id' =>$wiki->id,//这里引用了wiki的di
]);
}
}catch (ValidationException $e)
{
DB::rollback();
return Redirect::to('/form')
->withErrors( $e->getErrors() )
->withInput();
} catch(\Exception $e)
{
DB::rollback();
throw $e;
}
//提交事务
DB::commit();
return $wiki;
问题#
- push() 的用法资料太少,有哪个大神可以清楚的讲讲用法?