I would like to add some additional, at runtime calculated attributes with no according database field available, to a Laravel model. As we know this can be achieved with an accessor method (get...Attribute()) and adding the attribute to the $appends array.
But, I need this feature for a pivot table/model, where I'm not able to get the additional attributes to be shown in the output. And what I don't understand is, why this is not working for a pivot model, though it is extending from Illuminate\Database\Eloquent\Model, just with some extra methods loaded from trait Illuminate\Database\Eloquent\Relations\Concerns\AsPivot.
Is it even possible to add extra attributes (not having database fields) to a pivot model? Can you give me a hint, how to achieve this?
This is an example pivot model, where I would like to add a non database field attribute "test" to the model. But, as explained, it doesn't show up in the model as it would in a "common" model class:
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* @property int $id
* @property-read Collection<Tyres> $tyres
*/
class Car extends Model
{
/**
* m:n relation to Tyres
*/
public function tyres(): BelongsToMany
{
return $this->belongsToMany(Tyres::class);
}
}
The Pivot Class:
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Carbon;
/**
* @property-read int $car_id
* @property-read int $tyre_id
* @property-read Carbon $created_at
* @property-read Carbon $updated_at
*/
class CarTyres extends Pivot
{
protected $appends = ['test'];
public function getTestAttribute(): string
{
return 'testing value';
}
}
Laravel will use the default joins for the pivot table unless you define the model on the relation. So you need to use using()
method on relation.
Your code will be like this:
class Car extends Model
{
/**
* m:n relation to Tyres
*/
public function tyres(): BelongsToMany
{
return $this->belongsToMany(Tyres::class)->using(CarTyres::class);
}
}
More details: https://laravel.com/docs/11.x/eloquent-relationships#defining-custom-intermediate-table-models