Schema.org + Laravel =太复杂了


Schema.org + Laravel = way too complicated?

我最近完成了我的第一个Laravel项目(我真的很喜欢这个框架的外观,想尝试一下),并在反思我认为自己做得好的地方,做得不好的地方,以及下次我想做的不同的地方。

我注意到我遇到的最大问题之一是,为了避免数据重复,我做了一些非常可怕的工作,以便从数据库中提取有意义的信息。

在项目开始时,我使用schema.org作为设计模型的粗略基础。例如,当我想要存储Employee s和Customer s时:

  • 创建Person模型
  • A Person hasMany Role s
  • Customer (变种)Role
  • Employee (变形)Role
  • 一个Organization有许多Employee s一个Organization有许多Customer s

乍一看这似乎很好,因为一个人可以是雇员顾客(你可以在沃尔玛购物并为沃尔玛工作)。另外,由于一个人可以有多个角色,如果他们在多个商店购物,或者他们有两份工作,他们可以是多个客户和多个雇员。

然而,当我想做一些事情时,我遇到了问题,比如"查找组织X的所有员工,其名称是John":

$employees = $organization->employees;
$employeesNamedJohn = new Collection();
foreach( $employees as $employee ) {
    if( $employee->role->person->name == 'John' )
        $employeesNamedJohn->add( $employee );
}

这看起来非常复杂(更不用说效率低下了),特别是考虑到如果我没有发明这个混乱的模式,它将只是一个一行代码:

$employees = $organization->employees()->where('name', 'John')->get();

所以我只是做错了什么?Laravel是否有一种简单的方法来处理这种复杂的关系,或者答案是永远不要让你的关系变得如此复杂?

在模型上添加查询范围真的很有帮助:

class Role extends Model
{
    public function scopeNamed($query, $name)
    {
        $query->whereHas('person', function ($query) use ($name) {
            $query->where('name', $name);
        });
    }
}
class Employee extends Model
{
    public function scopeNamed($query, $name)
    {
        $query->whereHas('role', function ($query) use ($name) {
            $query->named($name);
        });
    }
}

那么你可以这样做:

$employees = $organization->employees()->named('John')->get();

更好。

另外,

我确实实现了joseph Silber的答案https://github.com/noud/seo

请查看readme.md中下面的实体关系图具有字段

的实体角色
  • roleable_id(外键指向的id)
  • roleable_type(外键指向的实体)

在Laravel中,这是

  • 榜样
  • 员工、客户、…的特征
  • 所以你可以获取员工的名字$name