Отношение Laravel belongsToMany, определяющее локальный ключ в обеих таблицах
таким образом, отношение belongsToMany является отношением "многие ко многим", поэтому требуется сводная таблица
пример у нас есть users
таблица и roles
таблица и user_roles
сводная таблица.
сводная таблица имеет два столбца,user_id
, foo_id
... foo_id
со ссылкой на id
в таблице ролей.
так для этого мы пишем следующее в user
красноречивый модели:
return $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');
теперь это ищет в users
таблица и присоединяется к ней с user_id
поле в user_roles
таблица.
проблема в том, что я хочу указать другое поле, отличное от id
присоединиться к users
таблица. Например у меня есть bar_id
в таблице пользователей, которую я хочу использовать в качестве local key
вместе с user_id
из документации laravel неясно, как это сделать. В других отношениях, таких как hasMany
и belongsTo
мы можем указать local key
и foriegn key
но не здесь по какой-то причине.
я хочу local key
в таблице пользователей должно быть просто id
.
как я могу это сделать?
6 ответов
обновление: по состоянию на Laravel 5.5 далее это возможно с помощью метода общих отношений, как указано @cyberfly ниже:
public function categories()
{
return $this->belongsToMany(
Category::class,
'service_categories',
'service_id',
'category_id',
'uuid', // new in 5.5
'uuid' // new in 5.5
);
}
для справки, предыдущий метод:
предполагаю id
является первичным ключом на вашем User
модель, поэтому нет способа сделать это с помощью красноречивых методов, потому что belongsToMany
использует $model->getKey()
чтобы получить этот ключ.
поэтому вам нужно создать пользовательское расширение отношений belongsToMany
что делать Что вам нужно.
быстрое предположение, которое вы можете попробовать: (не протестировано, но не будет работать с нетерпеливой загрузкой наверняка)
// User model
protected function setPrimaryKey($key)
{
$this->primaryKey = $key;
}
public function roles()
{
$this->setPrimaryKey('desiredUserColumn');
$relation = $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');
$this->setPrimaryKey('id');
return $relation;
}
на Laravel 5.5 и выше,
public function categories()
{
return $this->belongsToMany(Category::class,'service_categories','service_id','category_id', 'uuid', 'uuid');
}
в исходном коде:
public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
$parentKey = null, $relatedKey = null, $relation = null)
{}
это недавно добавленная функция. Мне пришлось перейти на 4.1, потому что я также искал это.
public BelongsToMany belongsToMany(string $related, string $table = null, string $foreignKey = null, string $otherKey = null, string $relation = null)
на $otherKey
и $relation
параметры были добавлены в 4.1. С помощью $foreignKey
и $otherKey
parameters позволяет указать ключи с обеих сторон отношения.
самый лучший способ-установить первичный ключ.
class Table extends Eloquent {
protected $table = 'table_name';
protected $primaryKey = 'local_key';
belongsToMany позволяет определить имя полей, которые будут хранить ключи che в сводной таблице но метод insert всегда первичный ключ значения в эти поля.
вы должны:
определить в методе belongsToMany таблица и столбцы;
затем с помощью protected $primaryKey = 'local_key'; вы можете выбрать какое значение хранить.
недавно я прошел через ту же проблему, где мне нужно было иметь связанную таблицу, которая использовала ID, чтобы связать две таблицы вместе, которые не были первичными ключами. В основном я создал копию моей модели, которая моделирует сводную таблицу и устанавливает первичный ключ к значению, которое я хотел использовать. Я попытался создать экземпляр модели, настроить первичный ключ, а затем передать его в отношение, но Laravel не соблюдал первичный ключ, который я установил ( используя - >setPrimaryKey() метод выше ).
создание копии модели и установка первичного ключа чувствует себя немного "взломанным", но в конце концов он работает так, как должен, и поскольку модели сводной таблицы, как правило, очень малы, я не вижу, что это вызывает какие-либо проблемы в будущем.
хотелось бы увидеть третий ключевой вариант, доступный в следующем выпуске Laravel, который позволяет вам получить более конкретную ссылку.