Description
Laravel Version
11.7.0
PHP Version
8.3.6
Database Driver & Version
mysql-community-server 8.0.35-1ubuntu22.04
Description
I created a pivot model to connect two tables, and set the protected $table attribute to a different table name that exists in my database. When attaching records, the $table property was not respected, and the getTable function must be overridden.
If no table is passed to Illuminate\Database\Eloquent\Concerns\HasRelationships::belongsToMany
it generates a new table name and (eventually) sets the table name of the model to that value once that value is passed to `Illuminate\Database\Eloquent\Relations\Concerns\AsPivot::fromAttributes.
There is no check on the model to ensure that the table name is set, and while I might imagine there could be concerns that the one writing the relationship would like to override the table, resolving the table name should be done later so that there's the possibility that it may be left to the Pivot once instantiated, given that the same table name resolution behavior is present in Illuminate\Database\Eloquent\Relations\BelongsToMany::resolveTableName
and Illuminate\Database\Eloquent\Relations\Concerns\AsPivot::getTable
That is to say, they both transform the model name to snake case in singular form.
There is an undocumented behavior, in that you can pass a Pivot instance to the $table parameter, which does not run into this issue, but the name of the variable gives no hint at this behavior (and is undocumented).
Steps To Reproduce
- Create two models
- Use a belongsToMany relationship with a Pivot class
$this->belongsToMany($relation)->using(PivotClass::class)
- Override
private $table
on the Pivot class - Attempt to attach the models together using the Pivot.
I created the two regular models and one pivot model to connect the two, and when attaching one to the other I get the error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_proj.card_category' doesn't exist (Connection: mysql, SQL: insert into `card_category` (`category_id`, `card_id`) values (3, ?))
When I use tinker to check the table name, everything appears normal, which means that the Pivot model's $table attribute is being modified by setTable()
Psy Shell v0.12.3 (PHP 8.3.6 — cli) by Justin Hileman
> app(CardCategory::class)->getTable()
[!] Aliasing 'CardCategory' to 'App\Models\CardCategory' for this Tinker session.
= "card_categories"
App\Models\CardCategory:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
class CardCategory extends \Illuminate\Database\Eloquent\Relations\Pivot {
protected $table = "card_categories";
}
App\Models\Card:
<?php
namespace App\Models;
class Card extends \Illuminate\Database\Eloquent\Model
{
public function categories()
{
return $this->belongsToMany(Category::class)->using(CardCategory::class);
}
}