10

我试图实现多态关系。它们工作得很好......但是,我正在尝试尽可能减少我的数据库大小,所以......我有这个

Table action
|  id  |  realatable_type  |  relatable_id
|  1   |  Lion\People      |  65
|  2   |  Lion\Company     |  13

显然我有这个

<?php namespace Lion;

class Company extends \Eloquent { ... }
class People extends \Eloquent { ... }

假设命名空间总是“狮子”,有没有办法只存储“人”或“公司”?

4

2 回答 2

23

从 Laravel 4.1 开始,在您的模型中(在本例中为CompanyPeople),您可以将受保护的属性设置$morphClass为您想要的任何内容。

<?php namespace Lion;

class Company extends \Eloquent { 

    protected $morphClass = 'Company';
}

现在在您的表中,您可以存储没有命名空间的类型:

 |  id  |  realatable_type  |  relatable_id
 |  2   |  Company          |  13
于 2014-06-06T19:23:47.063 回答
3

我相信这里最好的解决方案(至少对于数据库大小)是简单地更改readable_typeENUM('Lion\Company', 'Lion\People').


话虽这么说,如果你真的想在 Laravel 端处理这个问题,你必须创建从Illuminate\Database\Eloquent\Relations\Morph* ¹扩展的新类并覆盖它们的构造函数²以便只获得破折号后的最后一个值, on $morphClass。像这样的东西:

<?php

use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Builder;

class MyMorphOne extends \Illuminate\Database\Eloquent\Relations\MorphOne {
    public function __construct(Builder $query, Model $parent, $type, $id) {
        parent::__construct($query, $parent, $type, $id);

        $this->morphClass = substr($this->morphClass, strrpos($this->morphClass, '\\') + 1);
    }
}

然后,扩展您自己的模型或基础模型,覆盖morphOne,morphManymorphToMany方法以使用您的新扩展类。像这样的东西:

<?php

class People extends Eloquent {

    // ...

    public function morphOne($related, $name, $type = null, $id = null) {
        $instance = new $related;

        list($type, $id) = $this->getMorphs($name, $type, $id);

        $table = $instance->getTable();

        return new MyMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id);
    }

}
  1. *= One,ManyToMany
  2. 这实际上是从MorphOneOrManyonMorphOne和继承的MorphMany
于 2013-11-10T00:47:47.090 回答