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