celinederoland / eloquent-polymorphic-model
扩展eloquent功能,将一个类层次结构的分支映射到数据库中的一个表
Requires
- php: 7.*
- ext-json: *
- ext-pdo: *
- illuminate/database: *
Requires (Dev)
This package is not auto-updated.
Last update: 2024-09-30 20:54:33 UTC
README
扩展eloquent功能,将一个类层次结构的分支映射到数据库中的一个表。
目的
如果您数据库中有一个表(比如说一个包含字段 person_id
、name
和 gender
的 Person
表)并且您想将它与您的类层次结构(比如说一个父类 Person
和两个子类 Man extends Person
和 Woman extends Person
)关联起来,那么您可以使用这个包来自动进行映射。
配置类映射
从父类检索实例
在父类中,像通常一样定义模型
class Person extends Model { protected $table = 'Person'; protected $primaryKey = 'person_id'; }
定义空的子类
class Man extends Person {}
class Woman extends Person {}
在父类中使用 EloquentPolymorphism\PolymorphicParent
辅助类。您必须定义数据库结果如何与您的类层次结构绑定(在我这个例子中取决于 gender
字段的值)
protected function instanceFactory($attributes) { if (!array_key_exists('gender', $attributes)) { return static::class; } switch ($attributes['gender']) { case self::TYPE_WOMAN: return Woman::class; case self::TYPE_MAN: return Man::class; } return static::class; }
有了这个,您可以检索到男性集合和女性集合
$persons = Person::all(); //an eloquent collection, containing instances of `Man` and instances of `Woman`
从子类检索实例
现在我们必须在子类中定义约束(否则 Man::all()
也会检索到男性和女性的集合)。为此,在子类中,您必须使用 EloquentPolymorphism\PolymorphicChild
特性并定义 polymorphismScope
约束;
class Man extends Person { * This scope will be added to all requests to make sure not retrieving other child. * * @param Builder $query */ protected function polymorphismScope(Builder $query) { $query->where('gender', 'm'); } }
现在,如果您编写 Man::all()
或对 Man
模型执行任何更复杂的查询,它将返回一个包含 Man
实例的集合,对应于表示男性的表条目。
可选地,您可以通过在父类或子类中添加以下代码覆盖您在 Man
类中定义的作用域的名称
protected function polymorphismScopeIdentifier() { return 'polymorphism_scope_identifier'; }
更新/创建模型
默认属性
强烈建议在子类中定义默认属性值。
在我们的例子中,这将非常方便地编写
$woman = new Woman(['name' => 'Sandra']); $woman->save();
而不必设置她的性别。
为此,您必须在子类中覆盖 setChildDefaultAttributes
方法
public function setChildDefaultAttributes() { $this->gender = 'f'; }
在保存方法调用时的验证
PolymorphicParent
特性防止对子类进行不自然的更新/创建,例如
$man = new Man(); $man->gender = 'f'; $man->save(); //returns false, entry is not saved
这是通过检查 instanceFactory
方法中定义的条件是否确实检索到 Man
的实例来完成的。您可以通过实现 checkHierarchyConstraintsBeforeSaving
方法来覆盖此行为
class Man extends Person { /** * @return bool */ protected function checkHierarchyConstraintsBeforeSaving() { //Your logic : return true if it's correct to consider this instance as beeing a man, false otherwise } }
复杂查询、关系等。
您可以使用 Eloquent 模型的所有其他功能,就像平常一样。特别是,您可以定义所需的关系和复杂查询。
贡献
在您的github账户中fork项目。初始化gitflow
git flow init git flow feature start feature-name develop
Composer安装
sh composer.sh install
测试
docker-compose up testunit
代码
git push
从您的发布分支创建一个合并请求到develop