See if this helps: https://stackoverflow.com/questions/43240247/laravel-eloquent-uuid-in-a-pivot-table
In your model that defines the BelongsToMany relationship add this property:
protected $casts = ['relationName.pivot.id' => 'string'];
I want to use uuid as my primary key inside of pivot table (many to many relationship). But I could not found a way to catch creating hook or something like that in my pivot table to generate uuid.
How can I achieve my goal?
See if this helps: https://stackoverflow.com/questions/43240247/laravel-eloquent-uuid-in-a-pivot-table
In your model that defines the BelongsToMany relationship add this property:
protected $casts = ['relationName.pivot.id' => 'string'];
@Cronix In that case developer used MySQL trigger to generate id field. I want to let Eloquent to do that. I have trait which is generating uuid for creating model hook.
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->{$model->getKeyName()})) {
$model->{$model->getKeyName()} = Uuid::generate()->string;
}
});
}
But then i tried to hook that trait to my pivot table using pivot model via using method it does not fire up and I'm getting error in DB.
*Relationship method
public function items()
{
return $this
->belongsToMany(Item::class)
->using(UserItem::class);
}
*Pivot class
class UserItem extends Pivot
{
use Uuids;
/**
* Indicates if the IDs are auto-incrementing.
* @var bool
*/
public $incrementing = false;
/**
* The "type" of the auto-incrementing ID.
* @var string
*/
public $keyType = 'string';
}
*Error
[PDOException]
SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value
Found a hacky way to solve this problem by ovverriding fromRawAttributes method.
class UserItem extends Pivot
{
use Uuids;
/**
* Indicates if the IDs are auto-incrementing.
* @var bool
*/
public $incrementing = false;
/**
* The "type" of the auto-incrementing ID.
* @var string
*/
public $keyType = 'string';
/**
* Create a new pivot model from raw values returned from a query.
* @param \Illuminate\Database\Eloquent\Model $parent
* @param array $attributes
* @param string $table
* @param bool $exists
* @return static
* @throws \Exception
*/
public static function fromRawAttributes(Model $parent, $attributes, $table, $exists = false)
{
if (!$exists and !array_key_exists('id', $attributes)) {
$attributes['id'] = Uuid::generate()->string;
}
return parent::fromRawAttributes($parent, $attributes, $table, $exists);
}
}
Create Custom Intermedia model for pivot table
//add below attributes
public $incrementing = false;
protected $keyType = 'string';
protected $primaryKey = 'id';
//add below function in it
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->id = (string) Uuid::generate(4);
});
}
It will work then
Laravel 11 Updated Answer
Say the Many to Many was between Articles and Posts. Effectively, you're just specifiying the Pivot class, otherwise the pivot table would default to using auto-incrementing ids.
class ArticlePost extends Pivot
{
use HasUlids;
}
class Article extends Model
{
use HasUlids;
public function articles(): BelongsToMany
{
return $this->belongsToMany(Post::class)
->using(ArticlePost::class);
}
}
class Post extends Model
{
use HasUlids;
public function articles(): BelongsToMany
{
return $this->belongsToMany(Article::class)
->using(ArticlePost::class);
}
}
Please or to participate in this conversation.