Skip to content

Pivot models $table variable not respected / overridden #51410

Closed
@shortontech

Description

@shortontech

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);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions