一些常見的最佳實踐,整理一下,如果你有更好的建議,可以一起討論。
一個類或一個方法應該只做一件事
不推薦:
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;
}
一些常用的查詢,應該把它們封裝到模型中,控制器不應該知道太多事情。
不推薦:
public function index()
{
$clients = Client::verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
return view('index', ['clients' => $clients]);
}
推薦使用:
// Controller
public function index()
{
return view('index', ['clients' => $this->client->getWithNewOrders()]);
}
// Model
Class Client extends Model
{
public function getWithNewOrders()
{
return $this->verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
}
}
本著單一職責,我們應該把控制器中的業務邏輯抽離到 Service 類裡。
不推薦:
public function store(Request $request)
{
if ($request->hasFile('image')) {
$request->file('image')->move(public_path('images') . 'temp');
}
....
}
推薦使用:
// Controller
public function store(Request $request)
{
$this->articleService->handleUploadedImage($request->file('image'));
....
}
// Service
class ArticleService
{
public function handleUploadedImage($image)
{
if (!is_null($image)) {
$image->move(public_path('images') . 'temp');
}
}
}
如果你踐行 單一職責,其實已經很大程度上避免了 DRY。
不推薦:
public function getActive()
{
return $this->where('verified', 1)->get();
}
public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->where('verified', 1);
})->get();
}
推薦使用:
public function scopeActive($q)
{
return $q->where('verified', 1);
}
public function getActive()
{
return $this->active()->get();
}
public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->active();
})->get();
}
Eloquent 編寫的查詢可讀性比原生 SQL 要好很多。而且 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();
最差的:
if (count((array) $builder->getQuery()->joins) > 0)
好一點的:
// 判斷是否存在連線
if (count((array) $builder->getQuery()->joins) > 0)
最佳的:
使用方法來封裝它,並且起一個一目瞭然的名字。
if ($this->hasJoins())
不推薦:
public function isNormal()
{
return $article->type === 'normal';
}
return back()->with('message', 'Your article has been added!');
推薦的:
public function isNormal()
{
return $article->type === Article::TYPE_NORMAL;
}
return back()->with('message', __('app.article_added'));
env()
函式在配置檔案之外使用。如果配置被快取,你將獲取不到它。
不推薦:
$apiKey = env('API_KEY');
推薦使用:
// 配置 config/api.php
'key' => env('API_KEY'),
// 獲取
$apiKey = config('api.key');
不推薦:
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->toDateString() }}
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->format('m-d') }}
推薦使用:
// Model
protected $dates = ['ordered_at', 'created_at', 'updated_at']
public function getMonthDayAttribute($date)
{
return $date->format('m-d');
}
// View
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->monthDay }}
都是一些老生常談的問題了,整理一下,希望對你有幫助。
enjoy
本作品採用《CC 協議》,轉載必須註明作者和本文連結