Pull to refresh

Проблема Eloquent фреймворка Laravel

Работая над очередным проектом на фреймворке Laravel мы обнаружили его уязвимое место. Это модель Eloquent, о которой написано немало, и примеров её использования тоже достаточно. Вот что мы разглядели. Возьмём простую модель (не Eloquent) на рисунке 1.


image


Видим, что джойнятся несколько таблиц, делается какая-то выборка по определённым свойствам из этого join, а потом апдейтится определённое поле определённой таблицы. Случай ординарный и не заслуживает, чтобы его подробно разбирали.


Но что произойдёт если мы применим модель Eloquent вместо предыдущей модели? Как например на рисунке 2.


image


Здесь идёт выборка полей из таблиц ‘prospects’, ‘properties’, ‘leads’. Во всех трёх таблицах есть поле ‘id’.


Что мы ожидали? После join таблиц по определённым признакам мы хотели взять у этих leads поле ‘mailer_address_1’ и отправить его на geocoding и получить для этого поля новое значение, т.е. сделать update.


Что по факту получилось благодаря Eloquent? Поскольку поле ‘id’ встречается в нескольких таблицах, то при update leads у нас финальный sql получился — update leads & id where id от prospects, а не от ‘leads’. Если подробнее, то на выходе join получаем множество столбцов с одинаковыми (повторяющимися) полями. Когда модель Eloquent наполняется, то перебираются столбцы по очереди. В случае ‘id’ каждый следующий перезатирает предыдущий ‘id’, который взят из join. Коварство Eloquent в том, что если даже задать alias, то имена полей после join всё равно будут без префиксов, просто ‘id’.


Решение проблемы Eloquent. Надо указывать конкретные поля. Мы добавили строку → selectRaw (“distinct leads.*”)
как на рисунке 3.


image


Эти ошибки невероятно коварны, так как ваш скрипт работает, а вы получаете ерунду в базе. Узнаёте вы об этом спустя время, когда уже поздно.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.