当前位置: 首页 > 后端技术 > PHP

[组织]Laravel中EloquentORM关系的操作

时间:2023-03-29 16:41:43 PHP

Laravel中EloquentORM关系的操作Association数据定义关系一对一hasOne('App\Phone');//外键应该在父级上有匹配的id(或自定义的$primaryKey)//return$this->hasOne('App\Phone','foreign_key');//使用用户的local_key匹配手机的foreign_key//return$this->hasOne('App\Phone','foreign_key','local_key');}}$phone=User::find(1)->phone;//获取用户手机型号的相对关联belongsTo('App\User');//返回$this->belongsTo('App\User','foreign_key');//返回$this->belongsTo('App\User','foreign_key')','other_key');}}$user=Phone::find(1)->user;//查询手机id=1对应的用户$user=Phone::where('number','188**')->first()->user;//查询电话号码为188的用户一对多类UserextendsModel{//获取文章publicfunctionarticle(){return$this->hasMany('App\Comment');//返回$this->hasMany('App\Comment','foreign_key');//返回$this->hasMany('App\Comment','foreign_key','local_key');}}$articles=User::find(1)->article;//返回用户ID为1的所有文章$article=User::find(1)->article()->where('title','aa')->first();//返回某篇文章一对多(反向)classArticleextendsModel{publicfunctionuser(){return$this->belongsTo('App\User');//返回$this->belongsTo('App\Post','foreign_key');//返回$this->belongsTo('App\Post','foreign_key','other_key');}}$user=Article::find($id)->user;//返回文章作者需要三张数据表:users、roles和role_user,role_user表是关系表,默认按照关联模型名的字母顺序命名,包含两列user_id和role_idclassUserextendsModel{/***用户角色*/publicfunctionroles(){//默认去role_user找关系//return$this->belongsToMany('App\Role');返回$this->belongsToMany('App\Role',"role_users");//定义键值//return$this->belongsToMany('App\Role','user_roles','user_id','role_id');}}$roles=User::find(1)->roles;//返回[{"id":1,"name":"SuperManager","pivot":{"user_id":1,"role_id":1}},{"id"":2,"name":"Manager","pivot":{"user_id":1,"role_id":2}}]$roles=User::find(1)->roles()->orderBy('name')->get();//条件约束注意,我们得到的每一个Role模型都会自动分配一个pivot属性,这个属性包含一个表示中间表的模型,可以像雄辩的模型。如果您的数据透视表包含其他属性,则必须在定义关系时指定它:return$this->belongsToMany('App\Role')->withPivot('column1','column2');如果你想让你的数据透视表自动包含created_at和updated_at时间戳,定义关系时使用withTimestamps方法:return$this->belongsToMany('App\Role')->withTimestamps();通过中间表字段过滤关系return$this->belongsToMany('App\Role')->wherePivot('approved',1);返回$this->belongsToMany('App\Role')->wherePivotIn('priority',[1,2]);associationqueryExistingassociatedquery//获取至少有一条评论的所有帖子...$posts=App\Post::has('comments')->get();您还可以指定运算符和数字来自定义查询://获取至少包含三个评论的所有文章...$posts=Post::has('comments','>=',3)->get();您也可以使用“.”构造一个嵌套的has语句,例如,你想获得所有至少有一条评论的帖子并投票://获取所有至少有一条评论的帖子并投票...$posts=Post::has('comments.投票')->get();如果需要更强大的功能,可以使用whereHas和orWhereHas方法将where条件放在has查询上。这些方法允许您向关系条件约束添加自定义条件约束,例如检查评论的内容://GetallatleastThereisapostwithacommentcontainingthewordfoo$posts=Post::whereHas('comments',function($query){$query->where('content','like','foo%');})->get();无关结果查询//获取所有无注释博文$posts=App\Post::doesntHave('comments')->get();//查看评论内容:$posts=Post::whereDoesntHave('comments',function($query){$query->where('content','like','foo%');})->get();统计关联模型如果想在不加载关联关系的情况下统计关联结果的个数,可以使用withCount方法,该方法会在结果模型中放入一个{relation}_count字段$posts=App\Post::withCount('comments')->get();foreach($postsas$post){echo$post->comments_count;}//向查询添加约束以添加多个关系的“计数”:$posts=Post::withCount(['votes','comments'=>function($query){$query->where('content','like','foo%');}])->get();echo$posts[0]->votes_count;echo$posts[0]->comments_count;//为关系计数结果设置别名以允许对关系进行多维计数:$posts=Post::withCount(['comments','commentsASpending_comments'=>function($query){$query->where('approved',false);}])->get();echo$posts[0]->comments_count;echo$posts[0]->pending_comments_count;Eagerloading按属性访问数据库关系时,关系数据是“Lazyloaded”,即直到第一次访问才加载关系数据$books=App\Book::all();foreach($booksas$book){echo$book->author->name;}//这个循环需要执行26次查询:1是获取图书本身,其余的接下来的25个查询是针对每本书来获取其作者。$books=App\Book::with('author')->get();foreach($booksas$book){echo$book->author->name;}//在这个操作中,只有两个就一个query://select*frombooks//select*fromauthorswhereidin(1,2,3,4,5,...)渴望加载多个关系$books=App\Book::with('author','出版商')->get();嵌套预加载//加载所有图书作者及其个人联系信息:$books=App\Book::with('author.contacts')->get();带有条件约束的预加载//加载标题包含第一个$users=App\User::with(['posts'=>function($query){$query->where('title','like','%first%');}])->get();//以created_at的相反顺序加载文章$users=App\User::with(['posts'=>function($query){$query->orderBy('created_at','desc');}])->get();lazyeagerloading$books=App\Book::all();if($someCondition){$books->load('author','publisher');}//设置更多查询条件到eagerloading查询,你可以将闭包传递给加载方法:$books->load(['author'=>function($query){$query->orderBy('published_date','asc');}]);插入和更新关联模型保存方法$comment=newApp\Comment(['message'=>'一条新评论。']);$post=App\Post::find(1);$post->comments()->save($comment);//save方法会自动将post_id值添加到newComment模型保存多个关联模型,可以使用saveMany方法:$post=App\Post::find(1);$post->comments()->saveMany([newApp\Comment(['message'=>'一条新评论。']),newApp\Comment(['message'=>'另一条评论。']),]);create方法该方法接收一个属性数组,创建一个模型,然后将其插入到数据库中。save和create之间的区别在于save接受整个Eloquent模型实例,而create接受原始PHP数组:确保在使用create方法之前浏览属性批量分配文档。$post=App\Post::find(1);$comment=$post->comments()->create(['message'=>'一条新评论。',]);附属关系更新belongsTo关联,使用associate方法,在子模型上设置外键:$account=App\Account::find(10);$user->account()->associate($account);$用户->保存();删除belongsTo关联时,使用dissociate方法。该方法会将关联关系的外键设置为null:$user->account()->dissociate();$user->save();多对多关联的attachment/detachment假设一个用户可能有多个角色,同时一个角色属于多个用户。要通过在连接模型的中间表中插入记录来将角色附加到用户,可以使用附加方法:$user=App\User::find(1);$user->roles()->attach($roleId);//将额外插入的数据以数组的形式传递给中间表:$user->roles()->attach($roleId,['expires'=>$expires]);removeone对于多对多的关联记录,使用detach方法。detach方法会从中间表中移除相应的记录;然而,这两个模型在数据库中保持不变://Removearolefromagivenuser...$user->roles()->detach($roleId);//Removeallrolesfromthespecifieduser...$用户->角色()->分离();接收ID数组作为输入:$user=App\User::find(1);$user->roles()->detach([1,2,3]);$user->roles()->attach([1=>['expires'=>$expires],2,3]);同步关联sync方法以数组的形式接收ID并放入中间表//任何不在数组中的ID对应的记录都会从中间表中移除$user->roles()->sync([1,2,3]);//额外的中间表值也可以和ID一起传递:$user->roles()->sync([1=>['expires'=>真],2,3]);//如果不想脱离已有的ID,可以使用syncWithoutDetaching方法:$user->roles()->syncWithoutDetaching([1,2,3]);Switchassociation//Ifnotcurrentlyattached,attach:ifgivenTheIDiscurrentlyattached,sounattach$user->roles()->toggle([1,2,3]);Saveadditionaldataontheintermediatetable//接收一个额外的中间表属性数组作为第二个参数:App\User::find(1)->roles()->save($role,['expires'=>$过期]);updateintermediatetablerecordsupdateExistingPivot//更新中间表中已有的行,接收中间记录外键和属性数组更新$user=App\User::find(1);$user->roles()->updateExistingPivot($角色ID,$属性);当一个模型属于另一个模型时触发父时间戳,当子模型更新时父模型的时间戳也被更新将是有用的情况例如,当Comment模型更新时,你可能想“触发”更新它所属的Post模型的updated_at时间戳。Eloquent使这变得简单,只需添加一个包含关系名称的touches属性到子模型:classCommentextendsModel{//Alltr??iggeredrelationshipsprotected$touches=['post'];//关系publicfunctionpost(){return$this->belongsTo('App\Post');}}更新Comment,模型Post也将更新它的updated_at值$comment=App\Comment::find(1);$comment->text='Edittothiscomment!';$comment->save();