本文翻译改编自Laravel的十八条最佳实践本文并非Laravel改编的SOLID原则、模式等。只是为了让你注意到现实生活中Laravel项目中你最常忽视的东西。单一职责原则一个类和一个方法应该只有一个职责。错误的方法:publicfunctiongetFullNameAttribute(){if(auth()->user()&&auth()->user()->hasRole('client')&&auth()->user()->isVerified()){返回'先生。'。$this->名字。''。$this->middle_name。''$this->姓氏;}else{返回$this->first_name[0]。'.'。$这个->姓氏;}}推荐做法:publicfunctiongetFullNameAttribute(){return$this->isVerifiedClient()?$this->getFullNameLong():$this->getFullNameShort();}publicfunctionisVerfiedClient(){returnauth()->user()&&auth()->user()->hasRole('client')&&auth()->user()->isVerified();}publicfunctiongetFullNameLong(){return'先生。'。$this->名字。''。$this->middle_name。''。$this->last_name;}publicfunctiongetFullNameShort(){返回$this->first_name[0]。'.'。$this->last_name;}强大的模型和简单的控制器如果您使用查询构建器或原始SQL进行查询,请将所有与数据库相关的逻辑放入Eloquent模型或存储库类中的错误:publicfunctionindex(){$clients=Client::verified()->with(['orders'=>function($q){$q->where('created_at','>',Carbon::today()->subWeek());}])->get();returnview('index',['clients'=>$clients]);}好:publicfunctionindex(){returnview('index',['clients'=>$this->client->getWithNewOrders()]);}ClassClientextendsModel{publicfunctiongetWithNewOrders(){return$this->verified()->with(['orders'=>function($q){$q->where('created_at','>',Carbon::today()->subWeek());}])->获取();}}验证将验证从控制器移至请求类。非常常见但不推荐的做法:publicfunctionstore(Request$request){$request->validate(['title'=>'required|unique:posts|max:255','body'=>'required','publish_at'=>'可为空|日期',]);....}最好这样:publicfunctionstore(PostRequest$request){....}classPostRequestextendsRequest{publicfunctionrules(){return['title'=>'required|unique:posts|max:255','body'=>'required','publish_at'=>'nullable|date',];}}业务逻辑应该在服务类中控制器必须只有一个职责,所以业务逻辑应该从控制器移动到服务类中。错误:publicfunctionstore(Request$request){if($request->hasFile('image')){$request->file('image')->move(public_path('images').'temp');}....}好:publicfunctionstore(Request$request){$this->articleService->handleUploadedImage($request->file('image'));....}classArticleService{publicfunctionhandleUploadedImage($image){if(!is_null($image)){$image->move(public_path('images').'temp');}}}不要重复自己(DRY)尽可能重用代码。SRP(单一职责原则)正在帮助您避免重复。当然,这还包括Blade模板、Eloquent的范围等等。错误:publicfunctiongetActive(){return$this->where('verified',1)->whereNotNull('deleted_at')->get();}publicfunctiongetArticles(){return$this->whereHas('user',function($q){$q->where('verified',1)->whereNotNull('deleted_at');})->get();}好:publicfunctionscopeActive($q){return$q->where('verified',1)->whereNotNull('deleted_at');}publicfunctiongetActive(){return$this->active()->get();}publicfunctiongetArticles(){return$this->whereHas('user',function($q){$q->active();})->get();}与QueryBuilder和原生SQL查询相比,更倾向于Eloquent。为了更喜欢集合而不是数组,Eloquent可以编写可读和可维护的代码。此外,Eloquent有很棒的内置工具,如软删除、事件、范围等。例如,你写:SELECT*FROM`articles`WHEREEXISTS(SELECT*FROM`users`WHERE`articles`.`user_id`=`users`.`id`ANDEXISTS(SELECT*FROM`profiles`WHERE`profiles`.`user_id`=`users`.`id`)AND`users`.`deleted_at`ISNULL)AND`verified`='1'AND`active`='1'ORDERBY`created_at`DESC也可能是写成这样:Article::has('user.profile')->verified()->latest()->get();批量赋值比如你这样写:$article=newArticle;$article->title=$request->title;$article->content=$request->content;$article->verified=$request->verified;//添加文章类别$article->category_id=$category->id;$文章->保存();这样写是不是更好:$category->article()->create($request->all());不要在Blade模板中执行查询而使用关联加载(N+1问题)不好的地方即对于100个用户,相当于执行101个DB查询:[@foreach](https://laravel-china.org/users/5651)(User::all()as$user){{$user->profile->name}}下面@endforeach的方法,对于100个用户,只执行2次DB查询:$users=User::with('profile')->get();...[[@foreach](https://laravel-china.org/users/5651)](https://laravel-china.org/users/5651)($usersas$user){{$user->profile->name}}@endforeachwith努力评论您的代码比为方法或变量编写描述性名称更糟糕:if(count((array)$builder->getQuery()->joins)>0)good://okisthereanyconnectionif(count((array)$builder->getQuery()->joins)>0)更好:if($this->hasJoins())不要把JS和CSS放在Blade模板里,也不要把任何HTML将其放入PHP类中错误:letarticle=`{{json_encode($article)}}`;好:或者{{$article->name}}