mannikj / laravel-sti
适用于您 eloquent 模型的单表继承特性
v5.0.2
2023-02-07 15:22 UTC
Requires
- php: ^8.0
Requires (Dev)
- dms/phpunit-arraysubset-asserts: ^0.4.0
- laravel/legacy-factories: ^1.3
- orchestra/testbench: ^7.0
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2024-09-07 18:53:46 UTC
README
此包提供了一种特性,使您的 eloquent 模型能够实现单表继承。如果配置正确,查询将自动返回正确的模型子类实例,根据类型列。
安装
您可以通过 composer 安装此包
composer require mannikj/laravel-sti
基本用法
迁移
您要应用单表继承的表必须包含一个类型列。
包的服务提供程序向 Blueprint 类添加了一个宏,用于创建类型列。
Schema::table('table', function (Blueprint $table) { $table->sti()->nullable(); });
使用特性
您需要将 SingleTableInheritance
特性添加到您的根模型类中。子模型需要扩展根类。
use MannikJ\Laravel\SingleTableInheritance\Traits\SingleTableInheritance; class Root extends Model { use SingleTableInheritance; } class Sub1 extends Root {} class Sub2 extends Root {}
对于默认用法,无需其他配置。特性将使用子类的类名作为类型,相应地范围查询,并自动返回正确的子类实例。
嵌套
如果您有多个子类层级,并且希望自动范围包括所有子类型,您需要通过设置 stiSubClasses
数组属性来为每个模型定义直接子类。
use MannikJ\Laravel\SingleTableInheritance\Traits\SingleTableInheritance; class Root extends Model { use SingleTableInheritance; protected $stiSubClasses = [ Sub1::class, Sub2::class ] } class Sub1 extends Root { protected $stiSubClasses = [ Sub3::class ] } class Sub2 extends Root {} class Sub3 extends Sub1 {}
高级用法
没有完全限定类名的类型
默认情况下,特性假定有一个类型列存储子类的完全限定名称。但是,如果您想使用不直接引用类的其他字符串作为类型标识符,可以通过覆盖特性的两个函数来实现。
public static function resolveTypeViaClass() { $type = (new \ReflectionClass(static::class))->getShortName(); $type = str_replace('Component', '', $type); $type = strtolower($type); return static::isSubclass() ? $type : null; } public function resolveModelClassViaAttributes($attributes = []) { $type = $this->resolveTypeViaAttributes($attributes); // Map class to type $mapping = [ 'motif' => MotifComponent::class, 'text' => TextComponent::class, ]; return $type ? data_get($mapping, $type) : static::class; }
根据相关模型解决类型
您还可以进一步调整行为,使类型根据相关模型来确定。
class Animal extends Model { use SingleTableInheritance; protected $fillable = ['name']; public function resolveTypeViaAttributes($attributes = []) { if ($category = Category::find(Arr::get($attributes, 'category_id'))) { return $category->config_class; }; } public function applyTypeCharacteristics($type) { $this->category_id = Category::where('config_class', $type)->first()?->id; } public function scopeSti(Builder $builder) { $builder->whereHas('category', function ($query) use ($builder) { $query->where('categories.config_class', static::class); }); } public function category() { return $this->belongsTo(Category::class, 'category_id')->withDefault([ 'config_class' => static::class ]); } }
测试
composer test
变更日志
有关最近更改的更多信息,请参阅CHANGELOG。
贡献
有关详细信息,请参阅CONTRIBUTING。
安全
如果您发现任何与安全相关的问题,请通过mannikj@web.de发送电子邮件,而不是使用问题跟踪器。
鸣谢
许可
MIT 许可证 (MIT)。有关更多信息,请参阅许可文件。
Laravel 包模板
此包是用Laravel 包模板生成的。