Laravel Чем грозит использование прямых запросов к БД?

210
19 декабря 2016, 19:28

Чем грозит использование прямых запросов к БД через DB::select() ? Мне проще написать запрос на SQL или написать сложную процедуру в БД, чем использовать правила Eloquent ORM.

Answer 1

Если использовать привязку параметров в запросах, то инъекция не пройдёт:

DB::select('SELECT * FROM users WHERE id = ?', array($userId));

Опасность представляет непосредственная вставка пользовательских данных:

DB::query('SELECT * FROM users WHERE id = ' . $userId); // НИКОГДА так не делайте!

Я солидарен с вами в отказе от ORM, и всегда использую parameter binding.

Answer 2

Плюсы от использования ORM:

  • Меньше соблазна написать незащищенный код, который будет страдать от SQL-инъекций и тому подобных багов.
  • ORM задает протоколы общения между несвязанными между собой командами. Допустим, две команды делают два модуля, работающие с одной и той же базой данных. Но одна из них в России, а другая в США, поэтому общаются они в течение 30 минут раз в день, утром. Без фанатичной дисциплины они понапишут на SQL такого, что потом это будет очень сложно стыковать между собой.
  • В ORMах (в т.ч. Eloquent) UPDATE очень похож на INSERT, это позволяет уменьшить логическое дублирование кода.
  • В случае работы со вложенными структурами, в ORM гораздо проще писать UPDATE, он возьмет на себя всю работу.
  • В случае хорошего знания инструментов, написание тривиального кода на ORM занимает очень мало времени и серьезно ускоряет разработку в стиле "добавить 9000 фич до вечера". Грубо говоря, если вся твоя работа - это писать админки с веб-интерфейсом, делающим CRUD, ORM может помочь тебе выдавать в 10 раз больше кода и стать сотрудником года :-)
  • Весь код написан на одном языке и лежит в одном месте. Нужно меньше заботиться о deployment-части проблемы. Если все находится в коде на основном языке программирования, все что нужно для обновления - это git и средства накатывания миграций, если же они хоть как-то завязаны на базу, то мгновенно появляется проблема разворачивания. Это не очень важно, когда у тебя 1 база данных и 3 хранимых процедуры, но когда тебе нужно поддерживать в живом состоянии кластер дублирующихся микросервисов - это может стать головной болью.
  • В каком-то виде имеется информация о структуре запросов, что может помочь, например, при написании собственных инструментов миграции.
  • Код, написанный с использованием ORM, относительно легко портировать на разные виды баз данных. Синтаксис запросов к БД может очень отличаться между разными базами данных. Не всем нужна эта фича, но когда нужна - это критично.

Минусы использования ORM:

  • Полученные запросы почти наверняка будут медленными. Особенно это касается PHP. Вполне возможно, придется заниматься профилировкой и оптимизацией в тех местах, где на чистом SQL не пришлось бы задумываться вообще.
  • В ORM часто встречаются баги, поправить которые самостоятельно сложно, из-за огромной сложности кода самого ORM. Иногда сами создатели ORM не знают хороших ответов на сложные вопросы, в результате пользователям остается только искать обходные пути.
  • На клиент часто вытягиваются данные, которых там быть не должно, что делает некоторые задачи просто невыполнимыми. Например, генерацию банковской опердени, которая в stored procedure отрабатывает в течение целого дня, проводя операции над всей базой целиком, может оказаться вообще невозможно написать в рамках ORM.
  • Предыдущие знания о хаках SQL будут помогать очень редко. Гениальный написатель SQL-скриптов будет чувствовать себя закованным цепями в темнице сырой.
  • Не всё, что можно сделать с помощью специальных функций БД, можно повторить в ORM. Это может быть не только минусом, но и благом, в зависимости от точки зрения.
  • ORM нужно изучать. Знания, приобретенные в Hibernate навряд ли помогут в Active Record или Eloquent.

Как всегда, использование или неиспользование ORM есть инженерный компромисс, и нужно четко понимать, что и зачем вы делаете.

Предполагаю, что SQL удобно использовать в двух случаях - простых скриптах уровня Hello World, и наоборот - в случае необходимости серьезных оптимизаций.

В обычных проектах, особенно в тех, где участвует большая географически распределенная команда, лучше использовать ORM как средство устранения хаоса и упрощения написания кода.

Answer 3

На самом деле, ORM это не единственный путь абстрагирования от "чистых" SQL запросов со всеми их плюсами/минусами. Существует еще один слой абстракции, позволяющий с одной стороны избавиться от SQL кода в приложении, а с другой не вносить лишних усложнений в проект. Я говорю о концепции Query Builder.

Query Builder -- это дополнительный слой абстракции, который позволяет строить SQL запросы через объектный интерфейс. Query Builder позволяет практически полностью абстрагироваться от различий в диалектах SQL для различных БД.

Плюсы использования Query Builder'а:

  • Относительная простота перехода от одной БД к другой.
  • Простота и гибкость динамического конструирования запросов.
  • Возможность модификации запроса "на лету" без необходимость заниматься разбором строки SQL.
  • Написать код, подверженный SQL-инъекциям сложнее (хотя все еще возможно), потому что конкатенация строк при построении запроса не используется в явном виде.
  • Можно использовать большинство приемов оптимизации SQL запросов.

Минусы использования Query Builder'а:

  • Дополнительный слой абстракции несколько усложняет приложение.
  • Необходимо изучить API еще одной сторонней библиотеки.

В Laravel, есть даже специальный сервис реализующий концепцию Query Builder. Существуют и другие реализации Query Builder, например, Doctrine DBAL, который можно использовать независимо от фреймворка.

READ ALSO
Yii2 relation выборка изображений для сущностей

Yii2 relation выборка изображений для сущностей

Существует модель Image в которой хранятся, как понятно из названия, изображенияКаждое отдельное изображение прикрепляется к любой другой...

192
Laravel Factory: указание значения поля для Primary Key (типа VARCHAR)

Laravel Factory: указание значения поля для Primary Key (типа VARCHAR)

Есть таблица, в которой поле для Primary Key типа VARCHARИспользую factory для заполнения таблицы записями

151
Не работает логин через псевдоним в roundcube

Не работает логин через псевдоним в roundcube

Создаю в ISP Manager новый почтовый ящик для roundcube - user@domainru И несколько псевдонимов для него - user0, user1

158
Как отправить данные, которые пришли в гугл-форм?

Как отправить данные, которые пришли в гугл-форм?

Пользователи заполняют гугл-формы и нажимают отправитьФорма не вставлена на сайте

180