srlabs / eloquent-sti
在Eloquent ORM中实现单表继承
v6.0.0
2022-02-09 04:46 UTC
Requires
- php: ^8.0
- illuminate/database: ^9.0
- illuminate/support: ^9.0
README
本包提供了一种扩展Eloquent模型对象以支持单表继承的简单方法。灵感来源于Pallav Kaushish撰写的文章。
安装
应通过composer安装此包
$ composer require srlabs/eloquent-sti
用法
在你的模型中添加 SingleTableInheritanceTrait
特性,然后指定以下配置值
table
: 分配给基模型的数据库表名称morphClass
: 基Eloquent对象的完整类名discriminatorColumn
: 用于区分STI实体类型的数据库表中的列inheritanceMap
: 将鉴别列值映射到相应实体类的数组
以下是一个假设的Widget模型示例
// app/Epiphyte/Widget.php class Widget extends Illuminate\Database\Eloquent\Model { /***************************************************************************** * Eloquent Configuration *****************************************************************************/ protected $guarded = ['id']; protected $fillable = ['name', 'description', 'status']; /***************************************************************************** * Single Table Inheritance Configuration *****************************************************************************/ use SingleTableInheritanceTrait; protected $table = 'widgets'; protected $morphClass = 'Epiphyte\Widget'; protected $discriminatorColumn = 'status'; protected $inheritanceMap = [ 'new' => 'Epiphyte\Entities\Widgets\NewWidget', 'processed' => 'Epiphyte\Entities\Widgets\ProcessedWidget' 'complete' => 'Epiphyte\Entities\Widgets\CompleteWidget' ]; // ... }
接下来,你需要创建每个子实体类。我通常将它们保存在一个Entities
文件夹中,但任何命名空间位置都适用。
以下是一个假设的示例
// app/Epiphyte/Entities/Widgets/NewWidget.php class NewWidget extends Epiphyte\Widget { /** * Limit the query scope if we define a query against the base table using this class. * * @param bool $excludeDeleted * * @return $this */ public function newQuery($excludeDeleted = true) { return parent::newQuery($excludeDeleted)->where('status', '=', 'new'); } // Remaining child entity methods go here... }
每当Eloquent想要返回基模型的实例时,它将使用鉴别列的值来确定适当的实体类型,并返回该类的实例。这对于所有Eloquent操作都成立,但不会直接在数据库(即DB::table()
)调用中工作。
在子类中提供 newQuery()
方法允许你将实体用作传统的Eloquent访问器,它只返回其自身的实体。在这种情况下,NewWidget::all();
将返回数据库中标记为'new'的所有Widget。
有关此包的任何问题都应发布在包网站上。