我們平時可能在應用中建立了大量的模型。這些模型的程式碼量總是隨著大量的訪問器 / 修改器、增加的 Scope
、甚至各種關聯關係而擴大。例如:
// Models/Article.php
class Article extends Model
{
/**
* 狀態
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeStatus($query, $status)
{
return $query->where('status', $status);
}
/**
* 關聯使用者
*/
public function user()
{
return $this->belongsTo(User::class);
}
//......
//甚至訪問器 / 修改器
}
// usage of the scope
Article::status($status)->get();
正如您可能想象的那樣,這些方法會在一段時間後導致模型臃腫,您可以通過以下方法使模型變得更簡潔。
一、擴充套件 Eloquent Builder
1、編寫自己的 Eloquent Builder
可以建立您自己的 Eloquent Builder 並將其繫結到您的模型。這可以通過建立一個擴充套件 Eloquent Builder 的類來完成。首先讓我們從建立一個 ArticleBuilder 開始。將它放在哪裡並不重要,但我傾向於在 App 名稱空間中為它建立一個目錄 App\EloquentBuilders
。
<?php
declare(strict_types=1);
namespace App\EloquentBuilders;
use Illuminate\Database\Eloquent\Builder;
class ArticleBuilder extends Builder
{
public function published(): self
{
return $this->whereNotNull('published_at');
}
}
如您所見,它使用與以前相同的方法,因為作用域在後臺使用查詢構建器!
2、註冊全新的 Eloquent Builder
現在剩下的就是將我們的自定義查詢構建器繫結到模型中。通過覆蓋 newEloquentBuilder
方法來完成。覆蓋它後,您可以刪除任何舊 Scope
。您的最終結果將如下所示:
<?php
declare(strict_types=1);
namespace App\Models;
use App\EloquentBuilders\ArticleBuilder;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
public function newEloquentBuilder($query): Builder
{
return new ArticleBuilder($query);
}
}
// usage of the scope
Article::published()->get();
二、在Eloquent 模型中使用 Trait (推薦)
例如:常見的訂單模型為例,可以這樣定義目錄結構:
├── Order/
├── Traits/
├── Relationship/ //定義關聯關係
├── OrderRelationship.php
├── Scope/ //定義Scope
├── OrderScope.php
├── Order.php //定義模型
訂單模型 Order.php:
<?php
namespace App\Models\Order;
use Illuminate\Database\Eloquent\Model;
use App\Models\Order\Traits\Relationship\OrderRelationship;
use App\Models\Order\Traits\Scope\OrderScope;
class Order extends Model
{
use OrderRelationship,
OrderScope,
//......
}
// usage of the scope
Order::status($status)->get();
根據需要定義關聯關係 Traits\Relationship\OrderRelationship.php
:
<?php
namespace App\Models\Order\Traits\Relationship;
use App\Models\User\User;
trait OrderRelationship
{
/**
* 使用者
*/
public function user()
{
return $this->belongsTo(User::class);
}
//......
}
根據需要定義 Scope Traits\Scope\OrderScope.php
:
<?php
namespace App\Models\Order\Traits\Scope;
trait OrderScope
{
/**
* 訂單狀態
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeStatus($query, $status)
{
return $query->where('status', $status);
}
//......
}
最後,功能方面沒有任何改變,但您的模型變得更加簡潔。
如果有好用的處理方法,請在評論中說出你的想法。
本作品採用《CC 協議》,轉載必須註明作者和本文連結