Префикс таблицы отношений Laravel eloquent

Поздний комментарий

Похоже, что единственный способ заставить это работать — определить столбцы внешнего ключа в формате table_name_primary_key. Если они не соответствуют этому формату, отношения просто не работают без указания имен столбцов.

Я пытаюсь научиться использовать внешние ключи с генератором кода reliese/laravel (он генерирует модели из базы данных), но у меня есть проблема, которая заставляет меня повторно указывать имена всех внешних ключей в сгенерированном коде. Вот мой код миграции и сгенерированные коды отношений:

// миграция

Schema::create('hotels', function(Blueprint $table) {
    $table->increments('hotel_id');
    $table->string('name', 64);
    $table->string('description', 512);
    $table->softDeletes();
    $table->timestamps();
});

Schema::create('floors', function(Blueprint $table){
    $table->increments('floor_id');
    $table->integer('hotel_id')->unsigned();
    $table->string('label', 128);
    $table->softDeletes();
    $table->timestamps();

    $table->foreign('hotel_id')->references('hotel_id')->on('hotels')->onDelete('cascade');
});

// отношение

// Hotel.php contains

public function floors()
{
    return $this->hasMany(\Otellier\Floor::class);
}

// Floor.php contains

public function hotel()
{
    return $this->belongsTo(\Otellier\Hotel::class);
}

Теперь, когда я создаю пол с Faker:

$hotel = factory(App\Hotel::class)->make();
$floor = factory(App\Floor::class)->make([ "label" => "Floor #" . $floor_number ]);
$hotel->floors()->save($floor);

В последней строке я получаю эту ошибку:

Illuminate\Database\QueryException: SQLSTATE[42S22]: Столбец не найден: 1054 Неизвестный столбец 'hotel_hotel_id' в 'списке полей' (SQL: вставить в значения floors (label, hotel_hotel_id, updated_at, created_at) (этаж № 1, 8, 2018 г. -03-22 12:37:39, 2018-03-22 12:37:39))

По-видимому, он ищет поле hotel_hotel_id как столбец внутри таблицы floors, что, как я подозреваю, добавляет имя таблицы в качестве префикса к имени столбца. Почему это происходит и как я могу предотвратить это и заставить всю систему не добавлять префикс ни к одному столбцу

не делая этого:

public function hotel()
{
    return $this->belongsTo(\Otellier\Hotel::class, "hotels", "hotel_id", "hotel_id");
}

person Taha Paksu    schedule 22.03.2018    source источник
comment
ты поставил hotel_id в $fillable атрибутах себя Floor Model   -  person Yves Kipondo    schedule 22.03.2018
comment
да, это определено в модели   -  person Taha Paksu    schedule 22.03.2018
comment
Laravel обычно добавляет к внешнему ключу префикс имени таблицы, ведь вы добавляете этот внешний ключ   -  person Yves Kipondo    schedule 22.03.2018
comment
но ошибка не связана с внешним ключом, она связана с именем столбца, в который Laravel пытается вставить данные.   -  person Taha Paksu    schedule 22.03.2018
comment
Все ли ваши модели расширяют \Illuminate\Database\Eloquent\Model? Вы можете изменить это?   -  person Jonas Staudenmeir    schedule 22.03.2018
comment
Да, они делают, нет, я не могу это изменить.   -  person Taha Paksu    schedule 22.03.2018


Ответы (3)


Laravel использует метод getForiegnKey() в Model.php для прогнозирования внешнего ключа отношения.

/**
 * Get the default foreign key name for the model.
 *
 * @return string
 */
public function getForeignKey()
{
    return Str::snake(class_basename($this)).'_'.$this->primaryKey;
}

Вы можете переопределить его в своей модели или базовом классе, чтобы изменить его поведение. В вашем случае это может быть использовано как,

public function getForeignKey()
{
    return $this->primaryKey;
}

он вернет ваш $primaryKey в качестве внешнего ключа, когда отношение попытается получить доступ к соответствующему внешнему ключу.

NB: Если вы укажете внешний ключ в отношении, этот метод не будет работать.

person iamab.in    schedule 22.03.2018
comment
Да, но вам все равно нужно изменить сгенерированный файл модели. Это был самый близкий BTW. - person Taha Paksu; 22.03.2018
comment
используйте базовый класс и укажите в нем функцию. - person iamab.in; 22.03.2018
comment
Не будет ли он по-прежнему изменять файл модели? Извините, я думаю, это невозможно без изменения какого-либо основного файла или файла модели. - person Taha Paksu; 22.03.2018

По умолчанию eloquent определяет внешний ключ отношения на основе имени модели. В этом случае автоматически предполагается, что модель Floor имеет внешний ключ hotel_id. Кроме того, Eloquent предполагает, что внешний ключ должен иметь значение, соответствующее столбцу id (или пользовательскому столбцу $primaryKey) родителя. Другими словами, Eloquent будет искать значение столбца id отеля в столбце hotel_id столбца Floor. Если вы хотите, чтобы отношение использовало значение, отличное от id, вы можете передать третий аргумент в метод hasMany, указав свой собственный local key

public function floors()
{
    return $this->hasMany(\Otellier\Floor::class, 'hotel_id', 'hotel_id');
}
person NIKHIL NEDIYODATH    schedule 22.03.2018
comment
Я попросил способ, кроме изменения сгенерированных классов. Извиняюсь. - person Taha Paksu; 22.03.2018
comment
Если вы считаете, что то, что я сказал, правильно и может быть кому-то полезно, пожалуйста, проголосуйте за мой ответ. - person NIKHIL NEDIYODATH; 22.03.2018

Вам нужно определить свой собственный первичный ключ в моделях:

protected $primaryKey='floor_id';

и для другого:

protected $primaryKey='hotel_id';
person GabMic    schedule 22.03.2018
comment
У вас есть сводная таблица? - person GabMic; 22.03.2018
comment
Нет, я использую сводные таблицы, но здесь их нет. - person Taha Paksu; 22.03.2018
comment
Ну, вот поэтому все и запуталось. вы можете попробовать передать третий аргумент этой функции с именем столбцов, которые вы изменили. - person GabMic; 22.03.2018
comment
Нет, я использую сводные таблицы для отношений «многие ко многим». Это не нужно, потому что для этого требуется один ко многим. - person Taha Paksu; 22.03.2018