Отношение 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, потому что я также искал это.

С документация API:

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, который позволяет вам получить более конкретную ссылку.