Laravel 5 Dynamically create Eloquent Models

那年仲夏 提交于 2021-01-27 11:42:02

问题


Suppose I have an of mysql table names and a row id:

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

Each of these tables has an Eloquent model referencing the table. How can I iterate the list and dynamically use the Model to create a new instance from the table_name key and find the row based on the row_id key?

I can get the data I need through a Builder instance but I really need to construct a Model instance. This is because I am implementing a contract through the Eloquent model and looking for a specific attribute from that contract. I can't get the attribute through the Builder instance.

(The package that I am using: https://github.com/jarektkaczyk/revisionable. I am implementing Revisionable on the models)

To clarify a bit, this works:

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

While this does not:

// 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

Please let me know if this is not clear enough.

EDIT:

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

Also, here is the Dynamic model:

<?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;
    }
}

回答1:


First, latestRevision is a relationship added by the RevisionableTrait, so you need to make sure that your Dynamic class has the use RevisionableTrait; statement.

Next, since the find() method (and any other retrieval methods) return new instances of the models, you will need to reset the table again on every model after you find it. So, your code would look something like:

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

Another option, assuming you follow Laravel's naming conventions, is that you could determine the Model name from the table_name, and just use the correct Model from the start, instead of this Dynamic model:

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


来源:https://stackoverflow.com/questions/34700373/laravel-5-dynamically-create-eloquent-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!