I've been trying to create a Many To Many (Polymorphic) system that saves the state of every update done by a specific user on specific Models (for instance: Company
, Address
, Language
models) with a note
field and the updated_by
. The goal is to keep track of who updated the model and when, and the note
field is a text field that states where in the system the model was updated.
Below is what I created, but I'm open to getting a different solution that, in the end, allows me to accomplish the goal described above.
I've created the model Update
(php artisan make:model Update -m
) with the migration:
/**
* Run the migrations.
*
* @access public
* @return void
* @since
*/
public function up()
{
Schema::create('updates', function (Blueprint $table) {
$table->id()->comment('The record ID');
$table->bigInteger('updatable_id')->unsigned()->comment('THe model record id');
$table->string('updatable_type')->comment('THe model name');
$table->string('note')->nullable()->comment('The record note');
$table->integer('updated_by')->unsigned()->nullable()->comment('The user ID which updated the record');
$table->timestamps();
$table->softDeletes();
});
}
On the model Update
all the $fillable
, $dates
properties are standard, and the method of the Update
model:
class Update extends Model
{
/**
* Method to morph the records
*
* @access public
*/
public function updatable()
{
return $this->morphTo();
}
}
After trying several ways on the different models, my difficulty is getting the relation because when I save to the updates
table, it saves correctly. For instance, in the Company model: Company::where('id', 1)->with('updates')->get();
as in the model Company
I have the method:
public function updates()
{
return $this->morphToMany(Update::class, 'updatable', 'updates')->withPivot(['note', 'updated_by'])->withTimestamps();
}
Most certainly, I'm doing something wrong because when I call Company::where('id', 1)->with('updates')->get();
it throws an SQL error "Not unique table/alias".
Thanks in advance for any help.
CodePudding user response:
The problem I see here is using morphToMany
instead of morphMany
.
return $this->morphToMany(Update::class, 'updateable', 'updates');
will use the intermediate table (and alias) updates
(3rd argument) instead of using the default table name updateables
. Here it will clash with the table (model) updates
, so it will produce the error you are receiving.
return $this->morphMany(Update::class, 'updateable');
will use the table updates
and should work with your setup.
Do notice that morphMany
does not work with collecting pivot fields (e.g. withPivot([..])
, it's not an intermediate table. Only morphToMany
does.