Laravel 5动态创建Eloquent模型


Laravel 5 Dynamically create Eloquent Models

假设我有一个of mysql表名和一个行id:

['table_name' => 'things', 'row_id' => 11],
['table_name' => 'stuff', 'row_id' => 5]

这些表中的每个表都有一个引用该表的Eloquent模型。如何迭代列表并动态使用Model从table_name键和基于row_id键的行find创建新实例?

我可以通过Builder实例获得所需的数据,但我确实需要构造一个Model实例。这是因为我正在通过Eloquent模型实现一个契约,并从该契约中寻找特定的属性。我无法通过Builder实例获取属性。

(我正在使用的程序包:https://github.com/jarektkaczyk/revisionable.我正在型号上实施Revisionable

为了澄清一点,这是有效的:

dd('App'Models'Thing::find(11)->latestRevision); // returns Revision model

而这不是:

// foreach($rows as $row)
$model = new Dynamic([])->setTable($row['table_name']);
dd($model->find($row)); // returns model with correct data
dd($model->find($row['row_id'])->latestRevision); // returns null
// endforeach

如果这还不够清楚,请告诉我。

编辑

dd($model->find($row)); // returns model with correct data but shows table as `null` as if it isn't being persisted across the request.

此外,这里还有Dynamic型号:

<?php
namespace App'Models;
use Illuminate'Database'Eloquent'Model;
use Sofa'Revisionable'Laravel'RevisionableTrait;
use Sofa'Revisionable'Revisionable;
class Dynamic extends Model implements Revisionable
{
    use RevisionableTrait;
    /**
     * @param $table
     */
    public function __construct($attributes = [])
    {
        parent::__construct($attributes);
    }
    /**
     * Dynamically set a model's table.
     *
     * @param  $table
     * @return void
     */
    public function setTable($table)
    {
        $this->table = $table;
        return $this;
    }
}

首先,latestRevision是由RevisionableTrait添加的关系,因此您需要确保您的Dynamic类具有use RevisionableTrait;语句。

接下来,由于find()方法(以及任何其他检索方法)返回了模型的新实例,您需要在找到每个模型后重新设置该表

$model = new Dynamic([]);
$model->setTable($row['table_name']);
$model = $model->find($row['row_id']);
$model->setTable($row['table_name']);
$revision = $model->latestRevision;

另一种选择是,假设您遵循Laravel的命名约定,您可以从table_name中确定Model名称,并从一开始就使用正确的Model,而不是Dynamic模型:

$modelName = Str::studly(Str::singular($row['table_name']));
$model = $modelName::find($row['row_id']);
$revision = $model->latestRevision;