Reputation: 7152
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;
}
}
Upvotes: 2
Views: 7575
Reputation: 62228
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;
Upvotes: 2