Eloquent hasMany с внешним ключом на объединенном столе

Предположим это:

class List extends Model
{
    public function items(){
        return $this->hasMany(Items::class, 'c.class_id', 'class_id')
            ->rightjoin('items_classes as c', 'c.items_id', '=', 'items.id');
    }
}

Проблема в том, что Eloquent добавляет items к полю внешнего ключа, и окончательный запрос выглядит так:

SELECT * FROM items
RIGHT JOIN items_classes as c ON c.items_id = items.id
// here it is
WHERE items.c.class_id = 10

Даже использование DB::raw('c.class_id') не решило проблему.

Как выглядит код построения вашего запроса? Как вы определяете свой запрос? Кроме того, является ли хорошей практикой правильное соединение в методе отношений?

Fjarlaegur 20.02.2019 10:03

Я согласен с @Fjarlaegur. Не рекомендуется выполнять правильное объединение методов отношений. Вместо этого создайте новый метод, повторно используйте этот метод и прикрепите туда правильное соединение. Кроме того, где написано условие where, которое вы показали?

nice_dev 20.02.2019 10:07

@Fjarlaegur Я действительно понятия не имею, что вы подразумеваете под «Как выглядит код построения вашего запроса?». Запрос генерируется этой функцией отношения.

Omid 20.02.2019 10:19

@ vivek_23 Не могли бы вы дать мне ссылку на любую документацию, посвященную такому решению? Мне нужен пример.

Omid 20.02.2019 10:20

@Omid Для методов, определяющих отношения, к ним не должно быть никаких дополнительных вещей. Это заставит его выполняться каждый раз, когда вызывается items(), даже если иногда в этом нет необходимости. Это сделало бы его тесно связанным. Вместо этого создайте новый метод и присоедините к нему этот метод с помощью правильного соединения. Кроме того, если запрос генерируется самим этим методом, то выполняется какой-то boot() метод, присоединяющий это where условие каждый раз, когда он выполняется. Можете ли вы показать нам этот метод?

nice_dev 20.02.2019 10:32

@vivek_23 Я разместил все, что хочу сделать. Нет никакого дополнительного метода, чтобы показать вам. Также я не собираюсь добавлять дополнительное предложение where к запросу отношений. Это условие where является поведением Eloquent Builder по умолчанию, и мы хотели его изменить. Однако я обнаружил, что это не будет решено, и ядро ​​Laravel нуждается в некоторых изменениях. github.com/laravel/ideas/issues/1528

Omid 20.02.2019 10:42

@ Омид This where condition is the default behavior of Eloquent builder Такого никогда не бывает. Laravel только определяет отношения и соответственно включает joins. Вы проверили, есть ли какой-либо метод boot() в любом из определений ваших моделей? Дополнительные сведения см. в статье здесь.

nice_dev 20.02.2019 13:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
7
611
1

Ответы 1

Если вы заметили подпись метода отношения hasMany:

return $this->hasMany(Model::class, 'foreign_key', 'local_key');

Это означает, что когда Laravel сделает запрос, он будет рассматривать второй аргумент foreign_key как столбец table, определенный в Model::class.

Чтобы упростить в вашем случае:

return $this->hasMany(Items::class, 'c.class_id', 'class_id')->...

Оставив на мгновение правое соединение, Laravel рассматривает c.class_id как внешний ключ Item::class таблицы, которая на самом деле является items таблицей.

Таким образом, результирующий запрос:

SELECT * FROM items WHERE items.c.class_id = 10

Затем, когда вы добавляете правильное соединение, laravel просто добавляет в основной запрос и делает это:

SELECT * FROM items
RIGHT JOIN items_classes as c ON c.items_id = items.id
WHERE items.c.class_id = 10

Laravel не будет ссылаться на items_classes в отношении, потому что вы связываете List модель с Item::class, а не с ItemClass::class.

Я не уверен в данных, которые вам нужны, но посмотрите, можете ли вы использовать их, как показано ниже:

class List extends Model
{
    public function items(){
        return $this->hasMany(Items::class, 'c.class_id', 'class_id');
    }

}


List::with(['items', function($q){

    return $q->->rightjoin('items_classes as c', 'c.items_id', '=', 'items.id');
}])->get();

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

Спасибо, что уделили время моей проблеме. Однако я обнаружил, что это все равно не решит, но с переопределением метода hasMany. github.com/laravel/ideas/issues/1528

Omid 25.02.2019 08:29

Другие вопросы по теме