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

LaravelEloquent的20个必备实用技巧

时间:2023-03-29 16:33:20 PHP

EloquentORM可能看起来是一个简单的机制,但在幕后,有很多半隐藏的功能和鲜为人知的方法来实现更多的功能。在本文中,我将演示一些技巧。1、自增自减实现代替:$article=Article::find($article_id);$article->read_count++;$article->save();可以这样做:$article=Article::find($article_id);$article->increment('read_count');下面的方法也可以实现:Article::find($article_id)->increment('read_count');Article::find($article_id)->increment('read_count',10);//+10Product::find($produce_id)->decrement('stock');//-1*2。先执行方法X,如果方法X失败,再执行方法YEloquent有相当多的功能可以把这两个方法结合在一起,比如“请先执行X方法,如果X方法执行失败,再执行Y方法”。示例1--findOrFail():替换以下代码的实现:$user=User::find($id);如果(!$user){中止(404);你可以这样写:$user=User::findOrFail($id);示例2--firstOrCreate():替换以下代码的实现:$user=User::where('email',$email)->first();if(!$user){User::create(['email'=>$email]);}可以这样写:$user=User::firstOrCreate(['email'=>$email]);*3。模型boot()方法在Eloquent模型中,有一个神奇的地方叫做boot(),你可以在这里覆盖默认行为:classUserextendsModel{publicstaticfunctionboot(){parent::boot();static::Updating(function($model){//写一些日志什么的//覆盖一些属性,像这样$model->something=transform($something);});}}在创建模型对象值时设置一些字段,可能是最流行的示例之一。我们来看看在创建模型对象的时候如果想生成一个UUID字段怎么办。publicstaticfunctionboot(){parent::boot();self::creating(function($model){$model->uuid=(string)Uuid::generate();});}*4。withcondition用排序关联定义关联的一般方法:publicfunctionusers(){return$this->hasMany('App\User');}你知道吗?还可以加上where或者orderBy?\比如你想关联某些类型的用户,用email字段排序,可以这样做:publicfunctionapprovedUsers(){return$this->hasMany('App\User')->where('approved',1)->orderBy('email');}*5.模型特点:Eloquent模型的一些参数,比如time,append等,使用类的属性形式。最常用的是:classUserextendsModel{protected$table='users';protected$fillable=['电子邮件','密码'];//可以批量赋值的字段,比如添加User::create()时,可用字段protected$dates=['created_at','deleted_at'];//Carbon需要维护的字段名protected$appends=['field1','field2'];//json返回时的附加字段}不仅是这些,还有:protected$primaryKey='uuid';//替换主键public$incrementing=false;//设置不自增长protected$perPage=25;//定义每页显示的页数(默认15)constCREATED_AT='created_at';constUPDATED_AT='updated_at';//重写时间字段名public$timestamps=false;//时间字段不用维护还有很多,我只列举了一些比较有意思的特性,具体参考DocsabstractModelclass了解所有特性。*6.通过ID查询多条记录find()方法大家都知道吧?$user=User::find(1);我很惊讶很少有人知道这个方法可以接受多个ID的数组作为参数:$users=User::find([1,2,3]);*7.WhereX有一个优雅的方式来转换这段代码:$users=User::where('approved',1)->get();进入这个:$users=User::whereApproved(1)->get();是的,你没有看错,用字段名作为后缀添加到where中,就可以通过魔术方法跑起来了。此外,Eloquent中还有一些预定义的与时间相关的方法:User::whereDate('created_at',date('Y-m-d'));User::whereDay('created_at',date('d'));User::whereMonth('created_at',date('m'));User::whereYear('created_at',date('Y'));*8。通过排序关系的更复杂的“技巧”。你想按最近的帖子对论坛主题进行排序吗?在论坛中将最近更新的主题放在最前面是一种常见的要求,对吗?首先,为主题的最新帖子定义一个单独的关系:publicfunctionlatestPost(){return$this->hasOne(\App\Post::class)->latest();}然后,在控制器中,我们可以实现这个“魔法”:$users=Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');*9。Eloquent::when()--不再使用if-else很多人喜欢用“if-else”来写查询条件,像这样:if(request('filter_by')=='likes'){$query->where('likes','>',request('likes_amount',0));}if(request('filter_by')=='date'){$query->orderBy('created_at',request('ordering_rule','desc'));}还有一个更好的方法——使用when()$query=Author::query();$query->when(request('filter_by')=='likes',function($q){return$q->where('likes','>',request('likes_amount',0));});$query->when(request('filter_by')=='date',function($q){return$q->orderBy('created_at',request('ordering_rule','desc'));});它可能看起来不是很优雅,但它强大的功能是传递参数:$query=User::query();$query->when(request('role',false),function($q,$role){return$q->where('role_id',$role);});$authors=$query->get();*10。一对多返回默认模型对象假设现在有一种情况是显示文章的作者,那么模板代码为:{{$post->author->name}}但是如果作者的信息被删除或由于某种原因未设置,代码将返回错误,例如“非对象的属性”。当然你可以这样做:{{$post->author->name??''}}你可以通过Eloquent关系来做到这一点:如果文本没有作者信息,则为作者模型对象。此外,我们还可以为默认模型对象中的属性分配默认值。publicfunctionauthor(){return$this->belongsTo('App\Author')->withDefault(['name'=>'GuestAuthor']);}*11.按赋值函数排序假设您有这样的代码:functiongetFullNameAttribute(){return$this->attributes['first_name']。''。$this->attributes['last_name'];}现在,你想按“full_name”排序吗?无效果:$clients=Client::orderBy('full_name')->get();//没有效果解决方法很简单。我们需要在得到结果后对结果进行排序。$clients=Client::get()->sortBy('full_name');//成功!请注意,方法名称不同——它不是orderBy,而是sortBy*12。如果您希望User::all()始终按名称字段排序,则在全局范围内进行默认排序?您可以为其分配一个全局范围。让我们回到上面提到的boot()方法:protectedstaticfunctionboot(){parent::boot();//按名称正序排序static::addGlobalScope('order',function(Builder$builder){$builder->orderBy('name','asc');});}扩展阅读Queryscope。*13。原生查询方式有时,我们需要在Eloquent语句中添加原生查询。幸运的是,有这样的方法。//whereRaw$orders=DB::table('orders')->whereRaw('price>IF(state="TX",?,100)',[200])->get();//havingRawProduct::groupBy('category_id')->havingRaw('COUNT(*)>1')->get();//orderByRawUser::where('created_at','>','2016-01-01')->orderByRaw('(updated_at-created_at)desc')->get();*14.复制:复制一行很简单。描述的不是很深入,这里是复制一个数据库实体(一条数据)的最佳方式:$task=Tasks::find(1);$newTask=$task->replicate();$newTask->save();*15.大块数据的Chunk()方法与Eloquent并不完全相关,更多的是关于Collection(集合)的,但是对于处理大数据集合还是很有用的。您可以使用chunk()将此数据拆分成小块修改前:$users=User::all();foreach($usersas$user){//...你可以这样做:User::chunk(100,function($users){foreach($usersas$user){//...}});*16。创建模型时创建额外的东西我们都知道Artisan命令:phpartisanmake:modelCompany但是,您知道有三个有用的标志可以为模型生成关联文件吗?phpartisanmake:model公司-mcr-m会创建迁移文件-c会创建控制器-r表示控制器应该是资源控制器*17。调用save方法的时候,指定updated_at你知道吗->save()方法可以接受参数吗?我们可以通过传入参数来防止其默认行为:将updated_at更新为当前时间戳。$product=Product::find($id);$product->updated_at='2019-01-0110:00:00';$product->save(['timestamps'=>false]);这样,我们就成功的在保存的时候指定了updated_at的值。*18。update()的结果是什么?你想知道这段代码实际返回了什么吗?$result=$products->whereNull('category_id')->update(['category_id'=>2]);我的意思是,更新操作是在数据库中执行的,但是$result包含什么?答案是受影响的行。所以如果你想检查有多少行受到影响,你不需要调用任何其他东西——update()方法会返回这个数字。*19。将括号转换为Eloquent查询如果你有一个混合了and和or的SQL查询,像这样:...WHERE(gender='Male'andage>=18)or(gender='Female'andage>=65)How用Eloquent翻译它?以下是错误的方式:$q->where('gender','Male');$q->orWhere('age','>=',18);$q->where('gender','女');$q->orWhere('年龄','>=',65);顺序错了。正确的打开方式稍微复杂一点,使用闭包作为子查询:$q->where(function($query){$query->where('gender','Male')->where('age','>=',18);})->orWhere(function($query){$query->where('gender','Female')->where('age','>=',65);})*20。带复数参数的orWhere最后,您可以将数组参数传递给orWhere()。通常的方式:$q->where('a',1);$q->orWhere('b',2);$q->orWhere('c',3);你可以这样做:$q->where('a',1);$q->orWhere(['b'=>2,'c'=>3]);*我很确定还有更多隐藏的秘密,但我希望至少上面的一些内容对您来说可能是新的。如需更多现代PHP知识,请访问Laravel/PHP知识社区