Laravel принадлежит множество отношений, определяющих локальный ключ для обеих таблиц

#php #sql #database #laravel #laravel-4

#php #sql #База данных #laravel #laravel-4

Вопрос:

Таким образом, отношение belongsToMany — это отношение «многие ко многим», поэтому требуется сводная таблица

Например, у нас есть users таблица, roles таблица и user_roles сводная таблица.

Сводная таблица имеет два столбца, user_id , foo_id foo_id ссылающихся id на таблицу ролей.

Итак, чтобы сделать это, мы пишем следующее в модели user eloquent:

return $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');

Теперь это ищет id поле в users таблице и соединяет его с user_id полем в user_roles таблице.

Проблема в том, что я хочу указать другое поле, отличное id от join on в users таблице. Например, у меня есть bar_id в таблице users, которую я хочу использовать в качестве local key соединения с user_id

Из документации laravel неясно, как это сделать. В других отношениях, таких как hasMany and belongsTo , мы можем указать local key and foriegn key , но по какой-то причине не здесь.

Я хочу local key , чтобы в таблице users было bar_id вместо just id .

Как я могу это сделать?

Ответ №1:

Обновление: начиная с версии 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;
}
  

Комментарии:

1. Повлияет ли это на другие отношения?

2. Если вы имеете в виду настройку, то нет. Я думаю, это не повлияет ни на что, кроме этого самого отношения.

3. Похоже, это работает при получении. Но когда я прикрепляю, он прикрепляет идентификатор вместо моего desiredUserColumn . Как я могу это исправить?

4. Только с пользовательским классом отношений. Что это за столбец и зачем вам вообще нужна такая функция?

5. Я импортирую данные, и все отношения были установлены с другим ключом, кроме ключа ‘id’. Итак, теперь мне нужно убедиться, что эти отношения выполнены правильно.

Ответ №2:

В 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)
    {}
  

Комментарии:

1. Какой L5? Не в моем L5.4.

2. Невозможно редактировать, поэтому добавляю: не L5. L5.5 (или L5.6). Он недоступен ранее

3. Отлично, это работает, именно то, что я ищу.

Ответ №3:

Это недавно добавленная функция. Мне пришлось обновиться до 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 позволяет указать ключи с обеих сторон отношения.

Ответ №4:

Лучший способ — установить первичный ключ.

 class Table extends Eloquent {

     protected $table = 'table_name';

     protected $primaryKey = 'local_key';
  

Ответ №5:

belongsToMany позволяет определять имена полей, которые будут хранить ключи che в сводной таблице, но метод всегда вставляет значения первичного ключа в эти поля.

Вы должны:

  • определите в методе belongsToMany таблицу и столбцы;

  • затем, используя защищенный $PrimaryKey = ‘local_key’; вы можете выбрать, какое значение хранить.

Ответ №6:

Недавно я столкнулся с той же проблемой, когда мне нужно было иметь связанную таблицу, которая использовала идентификаторы для связывания двух таблиц вместе, которые не были первичными ключами. По сути, я создал копию своей модели, которая моделирует сводную таблицу, и установил первичному ключу значение, которое я хотел, чтобы оно использовало. Я попытался создать экземпляр модели, настроить первичный ключ, а затем передать его в отношение, но Laravel не соблюдал установленный мной первичный ключ (используя метод ->setPrimaryKey() выше).

Создание копии модели и установка первичного ключа кажутся немного «хакерскими», но в итоге все работает так, как должно, и поскольку модели сводных таблиц, как правило, очень маленькие, я не вижу, чтобы это вызывало какие-либо проблемы в будущем.

Хотелось бы, чтобы в следующем выпуске Laravel была доступна опция третьего ключа, которая позволит вам уточнить ваши ссылки.