Laravel 5 - 使用模型查询,使用不同的模型

时间:2016-02-29 06:09:42

标签: php laravel-5

问题

是否可以通过与最初进行查询的模型不同的模型返回模型查询结果?

例如,如果我们有两个模型ModelAModelB,我们会获取一些数据库结果:

$modelA = new ModelA;

$results = $modelA->all();

dd($results);

它可以以某种方式返回ModelB对象而不是ModelA对象的集合吗?所需的输出,例如:

Collection {#325 ▼
    #modelA_Table: Array:4 [▼
        0 => ModelB { #297 ▶}
        1 => ModelB { #306 ▶}
        2 => ModelB { #311 ▶}
        3 => ModelB { #318 ▶}
    ]
}

上下文

关系是一个分类层次结构,其中ModelBModelA的子分类:

class ModelA extends Model {
    protected $table = 'ModelA_Table';

    protected $fillable = [];

    private $discriminator = 'a_type';

    public function __construct(array $attributes = array()){
        $this->initialize();
        parent::__construct($attributes);
    }

    private function initialize() {
        $this->fillable = array_merge($this->fillable, $this->fillables());
    }

    private function fillables() {
        return [
            'a_name',
            'a_type'
            'a_price'
        ];
    }

}

class ModelB extends ModelA {

    protected $fillable = [];

    public function __construct(array $attributes = array()){
        $this->initialize();
        parent::__construct($attributes);
    }

    private function initialize() {
        $this->fillable = array_merge($this->fillable, $this->fillables());
    }

    private function fillables() {
        return [
            'b_width',
            'b_height'
        ];

    }
}

两个模型都是由单表继承(ModelA_Table)持久化的单个实体的不同分类单元(分类级别)。

类比 - 一般:具体:: ModelA:ModelB ::车辆:卡车

回到代码,当ModelB被实例化时,它会通过构造函数中的initialize()将自己的填充附加到其继承的父元素。在ModelB可以继承ModelA的可填写的情况下,反之则不然。 ModelA无法继承ModelB的可填写文件。我可以要求Truck-> find(1)并获得Truck和Vehicle属性,但是Vehicle-> find(1)只会给我Vehicle属性,因为Vehicle(一般分类法)不能从它的子代继承(来自特定分类)。

这让我离开了现在的位置。

基本上,如果ModelA是Vehicle,而ModelB是Car,我需要这样做:

1)车辆模型按ID读取

2)车辆模型查看字段'a_type'

3)'a_type'将是'Car','Motorcycle'或'Truck'等等

4)返回的水合物体将属于'a_type'类

<小时/> 使用ModelA查询,使用ModelB获取结果。

1 个答案:

答案 0 :(得分:0)

我使用修改Eloquent模型newFromBuilder方法的Jeff Madsen's solution解决了这个问题。

Model.php:

public function newFromBuilder($attributes = array())
{
    $instance = $this->newInstance(array(), true);

    $instance->setRawAttributes((array) $attributes, true);

    return $instance;
}   

在扩展类中覆盖:

public function newFromBuilder($attributes = array())
{
    $class = $this->{$this->discriminator} . ucwords($attributes->status);
    $instance = new $class;
    $instance->exists = true;
    $instance->setRawAttributes((array) $attributes, true);
    return $instance;
}  

新类将为$class,这是检索到的鉴别字段的值,由属性discriminator指定