Laravel по-русски

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

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

#1 24.10.2012 23:05:27

Генерация SQL-подзапроса в Fluent Query - возможна?

Добрый вечер уважаемое Сообщество.

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

price_table
id, field1, field2, field3, price, id_firm, hash

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

Запрос вот такой:

SELECT
  p1.*,
  (SELECT count(*) FROM price_table p2 WHERE p2.hash = p1.hash) as count_hash
FROM
  price_table p1
WHERE ...
GROUP BY p1.hash
ORDER BY ...
LIMIT ...
OFFSET ...

все получается кроме вот только конструкции вложенного селекта этого... Подскажите возможно ли так сделать в Fluent Query или ставить RAW запрос полный и забить на внутренние эти всякие "вспомогалки"?

Не в сети

#2 25.10.2012 08:34:01

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Не обязательно делать подзапрос, ты ведь уже группируешь по хэшу, просто добавь COUNT():

sqlSELECT
  *, COUNT(1) AS count_hash
FROM
  price_table
WHERE ...
GROUP BY hash
ORDER BY ...
LIMIT ...
OFFSET ...
PHP
$query->get(DB::raw('COUNT(1) AS count_hash'));

Не в сети

#3 25.10.2012 09:04:05

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Куда пиво/кофе/водку слать?.. smile))
Блин, у меня  тут  крышу уносило уже, начал с JOIN и прочими вещами закапываться... А простое решение даже не попробовал... Чегой-то казалось что... вобщем ну его... пора спать smile

PS: одна только проблема еще осталась, попробую ее раскопать, но интересная...
При этом запросе данные соответственно передаются в $db->paginate, а уже Paginator штатный, делает первый запрос

SELECT COUNT(id) AS `aggregate` FROM `cars` GROUP BY hash_code

Как итог, получаем количество страниц равное 1. Если исключаем GROUP_BY, то соответственно все работает корректно... кроме самого запроса... smile

Изменено Vertex (25.10.2012 09:24:08)

Не в сети

#4 25.10.2012 10:03:03

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

  1. Куда пиво/кофе/водку слать?.. ☺))

Просто делись информацией о ресурсе, мне большего не надо ☺

  1. Как итог, получаем количество страниц равное 1.

Просто перед вызовом PHPpaginate() убери группировку: PHP$query->groupings = array();.

Не в сети

#5 25.10.2012 11:10:53

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Да мне и самому Framework понравился... Достаточно чистая структура, нет тесно интегрированных навесок типа как в Yii, быстрый, не глюкавит как FuelPHP, очень легкий старт (напоминает Codeigniter по этому пункту), ну и не такой грузивный как Symfony и Zend, единственный это Paginator, который в принципе перекрыл уже. Не хватает немного информации расширенной конечно по нему, но благодаря таким как Вы, получил ответы на все вопросы. Некоторые вопросы еще на IRC-канале также очень много людей. smile

Блин... дурдом... 5-ый раз изменяю эту запись... цирк... big_smile
Вобщем никак не получается выполнить такую последовательность:
Запрос 1:

SELECT COUNT(DISTINCT hash_code) AS `aggregate` FROM `cars`

Запрос 2:

SELECT
 f1.hash_code, f1.field1, f1.field2
 count(firm_code) as cntm, max(f1.price) as price_max, min(f1.price) as price_min
FROM
 `cars` f1
GROUP BY f1.hash_code
ORDER BY cntm DESC

Т.е. насколько я понимаю все-таки группировку где-то надо убирать, но в этом случае, соответственно требуется уже не использовать функцию paginate, а генерировать линки вручную?

Ну или добавить в ядро "заплатку"... но как же я такие заплатки ненавижу... обновить потом ядро хрен выйдет. Надо расковырять как можно расширять ядро выносами.

  public function paginate_with_group_by($per_page = 20, $columns = array('*'))
  {
    // Because some database engines may throw errors if we leave orderings
    // on the query when retrieving the total number of records, we'll drop
    // all of the ordreings and put them back on the query.
    list($orderings, $this->orderings) = array($this->orderings, null);

    $temp_distinct = $this->distinct;
    $temp_groups = $this->groupings;
    $this->distinct();
    $this->groupings = null;
    $total = $this->count(reset($columns));
    $this->distinct = $temp_distinct;
    $this->groupings = $temp_groups;

    $page = Paginator::page($total, $per_page);
    $this->orderings = $orderings;

    // Now we're ready to get the actual pagination results from the table
    // using the for_page and get methods. The "for_page" method provides
    // a convenient way to set the paging limit and offset.
    $results = $this->for_page($page, $per_page)->get($columns);

    return Paginator::make($results, $total, $per_page);
  }

Изменено Vertex (25.10.2012 14:43:04)

Не в сети

#6 25.10.2012 21:24:48

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

  1. Не хватает немного информации расширенной конечно по нему, но благодаря таким как Вы, получил ответы на все вопросы.

На самом деле лучшая документация — сам код. Я ведь половину ответов на этом форуме, если не больше, беру именно оттуда — пока ещё я не запомнил всё и вся о нём. У Laravel компактный код, много комментариев, можно быстро разобраться, что к чему. На крайний случай есть отладчик.

  1. Ну или добавить в ядро «заплатку»… но как же я такие заплатки ненавижу…

Сделай статичный класс или файл с полезными функциями и складывай обёртки туда. Для этого конкретного случая расширять Paginator или Query не нужно, поэтому можно обойтись обёрткой.

Код я примерно таким себе и представлял — единственное, как его можно упростить — вычислить count до того, как добавлять distinct/group by и создавать Paginator напрямую, передавая ему эту сумму. Но в одну функцию это не обернёшь, поэтому «автоматический» вариант только как у тебя.

Не в сети

#7 26.10.2012 13:08:36

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

То что код там более чем нормально написанный, это да, читается легко. А при помощи PHPStorm так вообще никаких проблем. Но вот задаю вопросы для того чтобы узнать "True Way". Т.е. те кто уже давно пишут на фреймворке те уже выработали какой-то набор правил, куда выносить "обертки", какие способы расширения...

Query, к сожалению, пришлось заменить в коде, так как там жестко прописано было use Laravel/Paginator, и неважно что было переназначено... Хотя я еще не разобрался с автозагрузкой, в теории может получится переназначить alias. Разбираю фреймворк на реальном проекте, и сроки немного поджимали, а от Codeigniter я чешусь уже... smile

Не в сети

#8 26.10.2012 20:40:45

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

  1. Т.е. те кто уже давно пишут на фреймворке те уже выработали какой-то набор правил, куда выносить «обертки», какие способы расширения…

Нет такого понятия «true way», нет. Я давно пишу и на PHP, и на других языках и всегда убеждался, что понятие «правильно» — субъективное и варьируется от человека к человека или в случае с командой — от одной команды/проекта к другой.

Может быть понятие «красивый код», «краткий код», «рабочий код», но всё это как раз можно достать из первоисточника — кода фреймворка.

ИМХО.

  1. Хотя я еще не разобрался с автозагрузкой, в теории может получится переназначить alias.

Не получится. Это одна из проблем Laravel — весь его код написан внутри PHPnamespace Laravel\...;, что значит, что алиасы (как они заданы в application/config/application.php) вообще никак не влияют на код фреймворка. Они чисто для нашего удобства.

Единственный вариант без изменения кода библиотеки — переписывать методы, где жёстко прописаны эти классы (как PHPPaginator). Есть несколько методов, специально только конструирующие объект (например, PHPModel->query()), но их часто бывает мало.

Не в сети

#9 27.10.2012 11:01:35

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

А планируется переработка Laravel для возможности изменения ядра или это приницпиальное у разработчика (типа bcrypt'a)? Просто подумываю, может форкнуть...

Не в сети

#10 27.10.2012 11:10:00

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Я думаю можно предложить pull, тогда и узнаем.

Не в сети

#11 27.10.2012 21:40:51

Freeman
Откуда: Санкт-Петербург
Сообщений: 8
Сайт

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Запрос 2:

sqlSELECT
 f1.hash_code, f1.field1, f1.field2
 count(firm_code) as cntm, max(f1.price) as price_max, min(f1.price) as price_min
FROM
 `cars` f1
GROUP BY f1.hash_code
ORDER BY cntm DESC

Т.е. насколько я понимаю все-таки группировку где-то надо убирать

Если хочется решить задачу в рамках SQL, есть два способа:

  • Возвращать field1 и field2 как sqlmax(field1) field1, max(field2) field12, если по смыслу их значения одинаковы.
  • Вначале делать группировку подзапросом, а потом уже соединять с искомыми полями.

Правильно ведь понимаю, что эти поля — из справочника? Если нет, постановка неверна.

Не в сети

#12 28.10.2012 17:53:46

Re: Генерация SQL-подзапроса в Fluent Query - возможна?

Freeman, спасибо в любом случае, вопрос уже решен... просто выспаться надо было... smile

Не в сети

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