Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Добрый день. Решил не создавать новых тем. Только начал изучат Laravel и возник затык при переводе своих "старых" sql запросов в "ларавель правильные"Вот один из
Привет. На Stackoverflow очень многие просят переделать сырой запрос в Eloquent и у тамошнего сообщества принято советовать изучить Eloquent и попробовать создать запрос самому. Если не получится, тогда человек постит текущую неработающую версию запроса и объясняет что именно он хотел бы получить и что именно у него не получается. В таком случае всегда помогают. Я считаю, что это отличная практика, потому что бесплатно вникать в проблему (задавать тебе вопросы) и переделывать сложный запрос мало кто захочет. Также, это отличный пинок для задающего вопрос пойти и изучить 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 нравится все меньше и меньше(((
Не в сети
Собственно остановился на таком "query builder извращение" :
Надо понимать, что ничего не будет понятнее обычного SQL. Цепочки вызовов в ORM это не более чем приближение к SQL ради двух вещей: безопасности (SQL это простой текст, как следствие в него нельзя вставлять данные не в виде текста) и мутабельности (нельзя сказать строке с SQL-запросом "добавь такое-то условие WHERE, если выполняете то-то"). Для маленьких запросов с 2-3-4 вызовами методов Query Builder'а все выглядит нормально и даже хорошо, но вложенные запросы и/или запросы с кучей JOIN'ов уже сложнее для понимания, чем простой SQL (особенно если запрос активно изменяется в зависимости от условий - добавляются поля, меняется сортировка и так далее).
С другой стороны, какие альтернативы? Писать SQL от руки и вставлять данные прямо в него, рискуя получить SQL injection? Построитель запросов - меньшее зло.
Не в сети
А такой вариант является ли SQL injection безопасным?
$results = DB::select('select * from users where id = ?', array(1));
Если да, то не понятно для чего тогда Конструктор запросов нужен? Вижу только дополнительный,лишний синтаксис.
Не в сети
А такой вариант является ли 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.
Не в сети
Я всего лишь спросил совета, как мне в сыром запросе адекватно вставить переменную в условие IN().
создать столько плейсхолдеров внутри IN, сколько елементов в массиве. принцип тот же, что и на "голом PDO".
https://stackoverflow.com/a/29653461/272885
очевидно что пустому массиву соответствует пустой результат, и запрос можно не выполнять вообще.
Изменено artoodetoo (27.11.2017 13:41:49)
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
Но поинтересуюсь: а за что такого страшного в старом добром SQL?
Proger_XP пишет:В том, что где сырой запрос, там и SQL injection.
ага, а ORM типа без использования SQL работает, на чистом волшебстве.
топикстартер изначально показал запрос с плейсхолдером. почему вдруг контекст поменялся на прямую вставку строки в тело запроса?
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
С другой стороны, какие альтернативы? Писать SQL от руки и вставлять данные прямо в него, рискуя получить SQL injection? Построитель запросов - меньшее зло.
можно вообще без зла: SQL запрос с параметрами.
сам же пишешь, что "цепочка запросов это приближение к SQL", — истинная правда. некоторое подмножество запросов можно довольно дословно выразить через эти цепочки, а некоторые будет трудновато или вообще не получится, потому что SQL очень богат.
построитель запросов отлично справляется там, где нужен именно построитель запросов, простите за тавтологию. например когда визуальный "фильтр" с чекбоксами и радиобатонами надо транслировать в запрос к базе.
ну или для тех разработчиков, кто ниасилил SQL и ему проще оставаться в рамках Query Builder.
Изменено artoodetoo (27.11.2017 14:04:13)
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
Не удержусь, дам ещё годноты
Когда-то писал собственные обёртки DBAL над mysqli и PDO. В частности, для упрощения работы с массивами. Так вот, если вы хотите "автоматизировать" списки параметров из массива, можете вместо пустого массива подставлять NULL. Таким образом избежите синтаксических ошибок и лишних if-ов в вызывающем коде.
Запрос вида
.. WHERE x IN (NULL)
вернёт пустой набор, даже если x null-able и в колонке есть значения NULL !
Пруф: http://sqlfiddle.com/#!9/1cd3c3/1
Про магию NULL в SQL полезно знать даже тем, кто не использует SQL напрямую
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
Так вот, если вы хотите "автоматизировать" списки параметров из массива, можете вместо пустого массива подставлять NULL.
О, это отличный ход конем. Действительно, сравнение с NULL всегда возвращает false (за исключением оператора IS). Я для этого заменял x IN (...) на 0 = 1, что тоже всегда false и отбрасывается оптимизатором БД на этапе подготовки запроса.
Не в сети
Смотрите, что обнаружил на эту тему.
https://laravel-news.com/convert-sql-la … der-orator
Данная штуковина есть онлайн-конвертер "сырых" запросов в ORM.
Ссылка на сам инструмент:
http://www.midnightcowboycoder.com/
Изменено Androbim (05.12.2017 08:02:41)
Не в сети
Ну не знаю… ладно бэктики (`) почему-то вместо апострофов ('), я вообще не вижу пользы от этого дословного заворачивания в функции
зачем так делать, да???
Я бы написал
$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')
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
Ну не знаю… ладно бэктики (`) почему-то вместо апострофов ('), я вообще не вижу пользы от этого дословного заворачивания в функции
Обратные апострофы это нестандартная фишка MySQL - по стандарту обычные апострофы используются для строк, а кавычки - для идентификаторов (столбцов). То есть так:
WHERE "username" = 'artoodetoo'
А сложные запросы можно писать без мусора на честном SQL
Пара функций в столбцах это не сложный, сложный это вложенные запросы, вот тут, действительно, лучше без ORM.
Не в сети