与命名空间的多态Eloquent关系

时间:2013-11-09 19:15:33

标签: laravel laravel-4 eloquent polymorphism

我试图实现多态关系。它们完美地工作......但是,我正在尽可能地减少我的数据库大小,所以......我已经这样了

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 { ... }

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

2 个答案:

答案 0 :(得分:23)

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

<?php namespace Lion;

class Company extends \Eloquent { 

    protected $morphClass = 'Company';
}

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

 |  id  |  realatable_type  |  relatable_id
 |  2   |  Company          |  13

答案 1 :(得分:3)

我认为这里的最佳解决方案(至少对于数据库大小)只需将readable_type更改为ENUM('Lion\Company', 'Lion\People')


话虽如此,如果你真的想在Laravel方面处理这个问题,你必须创建从Illuminate\Database\Eloquent\Relations\Morph* ¹扩展的新类并覆盖它们的构造函数²< / strong>仅在$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);
    }
}

然后,扩展您自己的模型或基本模型,以覆盖morphOnemorphManymorphToMany方法,以便使用新的扩展类。像这样:

<?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. * = OneManyToMany
  2. 实际上是从MorphOneOrManyMorphOne上的MorphMany继承的。