Laravel 代码开发最佳实践(持续更新)

2018-03-01 11:10:35来源:网络收集作者:IRLAN人点击

分享


我们这里要讨论的并不是 Laravel 版的 SOLID 原则(想要了解更多 SOLID 原则细节 查看这篇文章 )亦或是设计模式,而是 Laravel 实际开发中容易被忽略的最佳实践。


内容概览

单一职责原则
胖模型,瘦控制器
验证
业务逻辑应该放到服务类
DRY(Don’t Repeat Yourself,不要重复造轮子)
优先使用 Eloquent 而不是查询构建器和原生 SQL 查询,优先使用集合而不是数组
批量赋值
不要在 Blade 模板中执行查询 & 使用渴求式加载(避免 N+1 问题)
注释代码
不要把 JS 和 CSS 代码放到 Blade 模板里面,不要在 PHP 类中写 HTML 代码
使用配置、语言文件、常量而不是在代码中写死
使用社区接受的标准 Laravel 工具
遵循 Laravel 命名约定
使用更短的、可读性更好的语法
使用 IoC 容器或门面而不是创建类
不要直接从 .env 文件获取数据
以标准格式存储日期,使用访问器和修改器来编辑日期格式
其他好的实践

单一职责原则

一个类和方法只负责一项职责。


坏代码:


public function getFullNameAttribute()
{
if (auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified()) {
return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' $this->last_name;
} else {
return $this->first_name[0] . '. ' . $this->last_name;
}
}

好代码:


public function getFullNameAttribute()
{
return $this->isVerifiedClient() ? $this->getFullNameLong() : $this->getFullNameShort();
}

public function isVerfiedClient()
{
return auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified();
}

public function getFullNameLong()
{
return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
}

public function getFullNameShort()
{
return $this->first_name[0] . '. ' . $this->last_name;
}
胖模型、瘦控制器

如果你使用的是查询构建器或原生 SQL 查询的话将所有 DB 相关逻辑都放到 Eloquent 模型或 Repository 类。


坏代码:


public function index()
{
$clients = Client::verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();

return view('index', ['clients' => $clients]);
}

好代码:


public function index()
{
return view('index', ['clients' => $this->client->getWithNewOrders()]);
}

Class Client extends Model
{
public function getWithNewOrders()
{
return $this->verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
}
}
验证

将验证逻辑从控制器转移到请求类。


坏代码:


public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);

....
}

好代码:


public function store(PostRequest $request)
{
....
}

class PostRequest extends Request
{
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
];
}
}
业务逻辑需要放到服务类

一个控制器只负责一项职责,所以需要把业务逻辑都转移到服务类中。


坏代码:


public function store(Request $request)
{
if ($request->hasFile('image')) {
$request->file('image')->move(public_path('images') . 'temp');
}

....
}

好代码:


public function store(Request $request)
{
$this->articleService->handleUploadedImage($request->file('image'));

....
}

class ArticleService
{
public function handleUploadedImage($image)
{
if (!is_null($image)) {
$image->move(public_path('images') . 'temp');
}
}
}
DRY

尽可能复用代码,单一职责原则可以帮助你避免重复,此外,尽可能复用 Blade 模板,使用 Eloquent 作用域。


坏代码:


public function getActive()
{
return $this->where('verified', 1)->whereNotNull('deleted_at')->get();
}

public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->where('verified', 1)->whereNotNull('deleted_at');
})->get();
}

好代码:


public function scopeActive($q)
{
return $q->where('verified', 1)->whereNotNull('deleted_at');
}

public function getActive()
{
return $this->active()->get();
}

public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->active();
})->get();
}
优先使用 Eloquent 和 集合

通过 Eloquent 可以编写出可读性和可维护性更好的代码,此外,Eloquent 还提供了强大的内置工具如软删除、事件、作用域等。


坏代码:


SELECT *
FROM `articles`
WHERE EXISTS (SELECT *
FROM `users`
WHERE `articles`.`user_id` = `users`.`id`
AND EXISTS (SELECT *
FROM `profiles`
WHERE `profiles`.`user_id` = `users`.`id`)
AND `users`.`deleted_at` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC

好代码:


Article::has('user.profile')->verified()->latest()->get();
批量赋值

关于批量赋值细节可查看对应文档。


坏代码:


$article = new Article;
$article->title = $request->title;
$article->content = $request->content;
$article->verified = $request->verified;
// Add category to article
$article->category_id = $category->id;
$article->save();

好代码:


$category->article()->create($request->all());
不要在 Blade 执行查询 & 使用渴求式加载

坏代码:


@foreach (User::all() as $user)
{{ $user->profile->name }}
@endforeach

好代码:


$users = User::with('profile')->get();

...

@foreach ($users as $user)
{{ $user->profile->name }}
@endforeach
注释你的代码

坏代码:


if (count((array) $builder->getQuery()->joins) > 0)

好代码:


// Determine if there are any joins.
if (count((array) $builder->getQuery()->joins) > 0)

最佳:


if ($this->hasJoins())
将前端代码和 PHP 代码分离:

不要把 JS 和 CSS 代码写到 Blade 模板里,也不要在 PHP 类中编写 HTML 代码。


坏代码:


let article = `{{ json_encode($article) }}`;

好代码:




或者

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台