Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#26 22.11.2017 12:12:20

Re: Select..in(). Сырые запросы против ORM

Добрый день. Решил не создавать новых тем. Только начал изучат Laravel и возник затык при переводе своих "старых" sql запросов в "ларавель правильные"Вот один из

Привет. На Stackoverflow очень многие просят переделать сырой запрос в Eloquent и у тамошнего сообщества принято советовать изучить Eloquent и попробовать создать запрос самому. Если не получится, тогда человек постит текущую неработающую версию запроса и объясняет что именно он хотел бы получить и что именно у него не получается. В таком случае всегда помогают. Я считаю, что это отличная практика, потому что бесплатно вникать в проблему (задавать тебе вопросы) и переделывать сложный запрос мало кто захочет. Также, это отличный пинок для задающего вопрос пойти и изучить ORM.

Не в сети

#27 23.11.2017 11:44:42

Re: Select..in(). Сырые запросы против ORM

Спасибо за наставление). Углубился в ORM и для себя понял, что Eloquent только для простых селектов в не больших БД. Даже для данного запросика он не годен.
Собственно остановился на таком "query builder извращение" :

$answers = DB::table('answer')
  ->leftJoin('answer_type', 'answer.answer_type_id', '=', 'answer_type.answer_type_id')
  ->leftJoin('answer_image', 'answer.answer_id', '=', 'answer_image.answer_id')
  ->leftJoin(DB::raw ('(SELECT at.type as type_other, question_id, answer_id, value as other_value ' .
                  'FROM answer_other ao JOIN answer_type at ON (ao.answer_type_id = at.answer_type_id) ' .
                  'WHERE ao.question_id =" ' . (int)$question->question_id . '") ao1'), 'answer.answer_id', '=', 'ao1.answer_id')
  ->where('answer.question_id', '=', (int)$question->question_id)

Чем дальше, тем laravel нравится все меньше и меньше(((

Не в сети

#28 23.11.2017 21:17:49

Re: Select..in(). Сырые запросы против ORM

Собственно остановился на таком "query builder извращение" :

Надо понимать, что ничего не будет понятнее обычного SQL. Цепочки вызовов в ORM это не более чем приближение к SQL ради двух вещей: безопасности (SQL это простой текст, как следствие в него нельзя вставлять данные не в виде текста) и мутабельности (нельзя сказать строке с SQL-запросом "добавь такое-то условие WHERE, если выполняете то-то"). Для маленьких запросов с 2-3-4 вызовами методов Query Builder'а все выглядит нормально и даже хорошо, но вложенные запросы и/или запросы с кучей JOIN'ов уже сложнее для понимания, чем простой SQL (особенно если запрос активно изменяется в зависимости от условий - добавляются поля, меняется сортировка и так далее).

С другой стороны, какие альтернативы? Писать SQL от руки и вставлять данные прямо в него, рискуя получить SQL injection? Построитель запросов - меньшее зло.

Не в сети

#29 24.11.2017 07:08:22

Re: Select..in(). Сырые запросы против ORM

А такой вариант является ли SQL injection безопасным?
$results = DB::select('select * from users where id = ?', array(1));
Если да, то не понятно для чего тогда Конструктор запросов нужен? Вижу только дополнительный,лишний синтаксис.

Не в сети

#30 25.11.2017 00:09:35

Re: Select..in(). Сырые запросы против ORM

А такой вариант является ли SQL injection безопасным?
$results = DB::select('select * from users where id = ?', array(1));

Да, с точки зрения SQLi это безопасный вариант.

Если да, то не понятно для чего тогда Конструктор запросов нужен? Вижу только дополнительный,лишний синтаксис.

Ты взял очень простой пример. Если у тебя условие состоит из трех проверок: одна постоянная и две в зависимости от запроса, то как это будет выглядеть?

$where = ['id = :id'];
$data = [];

if ($if_var1) { 
  $where[] = 'var1 = :var1';
  $data['var1'] = $if_var1;
}

if ($if_var2) { 
  $where[] = 'var2 = :var2';
  $data['var2'] = $if_var2;
}

$sql = 'select * from users where '.join(' and ', $where);
$results = DB::select($where, $data);

А если еще надо добавить ORDER BY? Или поля в SELECT?

Явно, что такой синтаксис на порядок хуже Query Builder'а, и еще дальше от первичного SQL.

Не в сети

#31 27.11.2017 13:40:52

Re: Select..in(). Сырые запросы против ORM

Fridz пишет:

Я всего лишь спросил совета, как мне в сыром запросе адекватно вставить переменную в условие IN().

создать столько плейсхолдеров внутри IN, сколько елементов в массиве. принцип тот же, что и на "голом PDO".
https://stackoverflow.com/a/29653461/272885

очевидно что пустому массиву соответствует пустой результат, и запрос можно не выполнять вообще.

Изменено artoodetoo (27.11.2017 13:41:49)

Не в сети

#32 27.11.2017 13:47:58

Re: Select..in(). Сырые запросы против ORM

tmanager пишет:

Но поинтересуюсь: а за что такого страшного в старом добром SQL?

Proger_XP пишет:

В том, что где сырой запрос, там и SQL injection.

ага, а ORM типа без использования SQL работает, на чистом волшебстве. big_smile
топикстартер изначально показал запрос с плейсхолдером. почему вдруг контекст поменялся на прямую вставку строки в тело запроса?

Не в сети

#33 27.11.2017 14:03:19

Re: Select..in(). Сырые запросы против ORM

Proger_XP пишет:

С другой стороны, какие альтернативы? Писать SQL от руки и вставлять данные прямо в него, рискуя получить SQL injection? Построитель запросов - меньшее зло.

можно вообще без зла: SQL запрос с параметрами.

сам же пишешь, что "цепочка запросов это приближение к SQL", — истинная правда. некоторое подмножество запросов можно довольно дословно выразить через эти цепочки, а некоторые будет трудновато или вообще не получится, потому что SQL очень богат.

построитель запросов отлично справляется там, где нужен именно построитель запросов, простите за тавтологию. например когда визуальный "фильтр" с чекбоксами и радиобатонами надо транслировать в запрос к базе.
ну или для тех разработчиков, кто ниасилил SQL и ему проще оставаться в рамках Query Builder.

Изменено artoodetoo (27.11.2017 14:04:13)

Не в сети

#34 30.11.2017 13:52:28

Re: Select..in(). Сырые запросы против ORM

Не удержусь, дам ещё годноты smile

Когда-то писал собственные обёртки DBAL над mysqli и PDO. В частности, для упрощения работы с массивами. Так вот, если вы хотите "автоматизировать" списки параметров из массива, можете вместо пустого массива подставлять NULL. Таким образом избежите синтаксических ошибок и лишних if-ов в вызывающем коде.

Запрос вида

.. WHERE x IN (NULL)

вернёт пустой набор, даже если x null-able и в колонке есть значения NULL !

Пруф: http://sqlfiddle.com/#!9/1cd3c3/1

Про магию NULL в SQL полезно знать даже тем, кто не использует SQL напрямую wink

Не в сети

#35 30.11.2017 22:42:30

Re: Select..in(). Сырые запросы против ORM

Так вот, если вы хотите "автоматизировать" списки параметров из массива, можете вместо пустого массива подставлять NULL.

О, это отличный ход конем. Действительно, сравнение с NULL всегда возвращает false (за исключением оператора IS). Я для этого заменял x IN (...) на 0 = 1, что тоже всегда false и отбрасывается оптимизатором БД на этапе подготовки запроса.

Не в сети

#36 05.12.2017 08:00:48

Re: Select..in(). Сырые запросы против ORM

Смотрите, что обнаружил на эту тему.

https://laravel-news.com/convert-sql-la … der-orator

Данная штуковина есть онлайн-конвертер "сырых" запросов в ORM.

Ссылка на сам инструмент:

http://www.midnightcowboycoder.com/

Изменено Androbim (05.12.2017 08:02:41)

Не в сети

#37 05.12.2017 09:17:34

Re: Select..in(). Сырые запросы против ORM

Ну не знаю… ладно бэктики (`) почему-то вместо апострофов ('), я вообще не вижу пользы от этого дословного заворачивания в функции smile

VYa58E2TO7JMeiRYuEaYeK60Oa8gs9.png
зачем так делать, да???

Я бы написал

$count = DB::table('users')->where('role', 'admin)->count();

А сложные запросы можно писать без мусора на честном SQL

$rows = DB::select('SELECT
  manager_id,
  COUNT(*) AS appt_count,
  MIN(booking_time) AS min_date,
  MAX(booking_time) AS max_date
FROM appointments
GROUP BY manager_id')

Не в сети

#38 05.12.2017 22:06:45

Re: Select..in(). Сырые запросы против ORM

Ну не знаю… ладно бэктики (`) почему-то вместо апострофов ('), я вообще не вижу пользы от этого дословного заворачивания в функции

Обратные апострофы это нестандартная фишка MySQL - по стандарту обычные апострофы используются для строк, а кавычки - для идентификаторов (столбцов). То есть так:

WHERE "username" = 'artoodetoo'

А сложные запросы можно писать без мусора на честном SQL

Пара функций в столбцах это не сложный, сложный это вложенные запросы, вот тут, действительно, лучше без ORM.

Не в сети

Подвал раздела