Подзапросы для pdoTools
Добрый день всем! Мне понадобилось сделать сложные запросы в mysql и, так как уже привык к pdoTools, решил доработать его, чтоб с ним делать подзапросы. Извиняюсь, загружен работой и не хватило времени оттестировать все и расписать.
Вкратце под катом.
Нужен был запрос типа такого:
сделал инструкцию для джоин подзапроса:
Добавил массив инструкцию subpdo в первый уровень массива pdoTools, вида:
Проходя по всему массиву инструкций pdoTools и с феном подменяем {$subpdo.smena_limit} на этот SQL.
Было:
Эта возможно с этой правкой Add Fenom soft mode.. Без нее, скорей всего, феном не поймет свою инструкцию в своей инструкции.
Проверка показала, что и без Add Fenom soft mode все прекрасно работает.
Вот полная распечатка массив нужного запроса:
github
Установочный пакет
Сделал пул. Может сейчас @Василий Наумкин примет.
ЗЫ. Наверно можно сделать кучу вложенных подзапросов. Сделано так, что подзапросы обрабатываются рекурсивно. Но не тестировал.
Upd 04.03.2020
Хотелки к следующей версии:
Вкратце под катом.
Нужен был запрос типа такого:
SELECT *
FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`
LEFT JOIN `modx_tsklad_order_list` `Detail` ON Detail.id=tSkladDetNSLink.det_id
LEFT JOIN `modx_tsklad_orders` `Order` ON Order.id=Detail.sk_order_id
LEFT JOIN `modx_tsklad_naryad` `Naryad` ON Naryad.id=tSkladDetNSLink.naryad_id
LEFT JOIN `modx_tsklad_smena` `Smena` ON Smena.id=tSkladDetNSLink.smena_id
LEFT JOIN `modx_nomenclature_detail_nom` `DetailNom` ON DetailNom.id=Detail.nom_id
LEFT JOIN `modx_nomenclature_detail_class` `DetailClass` ON DetailClass.id=DetailNom.class_id
LEFT JOIN `modx_nomenclature_type_job` `NomTypeJob` ON NomTypeJob.id=DetailClass.type_job_id
LEFT JOIN (
#subquery subpdo join
SELECT NextDNL.det_id AS next_det_id, NextDNL.naryad_id AS next_naryad_id, NextN.name AS next_naryad_name, NextDNL.smena_id AS next_smena_id, NextS.date AS next_smena_date, NextS.number AS next_smena_number
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
ORDER BY NextS.date ASC, NextS.number ASC) `NextDNL1`
ON tSkladDetNSLink.det_id = NextDNL1.next_det_id AND
(NextDNL1.next_smena_date > Smena.date OR (NextDNL1.next_smena_date = Smena.date AND NextDNL1.next_smena_number > Smena.number)
)
AND NextDNL1.next_smena_id = (
#subquery {$subpdo.smena_limit}
SELECT NextDNL.smena_id AS on_next_smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
WHERE NextS.date > Smena.date OR (NextS.date = Smena.date AND NextS.number > Smena.number)
ORDER BY NextS.date ASC, NextS.number ASC
LIMIT 1
)
LEFT JOIN `modx_plazma_list` `PlazmaList` ON PlazmaList.det_id=tSkladDetNSLink.det_id
WHERE (`Detail`.`sech` = 'pryam' AND `Detail`.`name` = 'зонт' AND `DetailNom`.`A` = '2000' AND `DetailNom`.`B` = '1500' AND `DetailNom`.`a_s` = '500' AND `DetailNom`.`b_s` = '500' AND `Detail`.`metall` = '0,7Ц' AND `Detail`.`L` = '0' AND `Detail`.`comment` = 'тип 1, ф355 заузить под наш отвод' AND `tSkladDetNSLink`.`smena_id` = 65 AND `tSkladDetNSLink`.`naryad_id` = 8 AND `NextDNL1`.`next_smena_id` = '66' AND `PlazmaList`.`file_true` = '0')
ORDER BY Detail.sech DESC, Detail.name ASC, DetailNom.A DESC, DetailNom.B DESC, DetailNom.a_s DESC, DetailNom.b_s DESC, Detail.metall DESC, Detail.L DESC, Detail.comment DESC
Сперва исходя из Джоины подзапросов средствами xPDO Сапсибо Fi1osofсделал инструкцию для джоин подзапроса:
[leftJoin] => Array(
[NextDNL1] => Array
(
[class] => tSkladDetNSLink
[on] => tSkladDetNSLink.det_id = NextDNL1.next_det_id
[subpdo] => Array
(
/* Здесь массив обычных инструкций pdoTools для запроса. Функция getSubSelectSQL преобразует его в SQL код.
https://github.com/touol/pdoTools/blob/61af551759b1d83a2ee5aba21cbaff772a24312b/core/components/pdotools/model/pdotools/pdofetch.class.php#L390
Затем джоиниться
https://github.com/touol/pdoTools/blob/61af551759b1d83a2ee5aba21cbaff772a24312b/core/components/pdotools/model/pdotools/pdofetch.class.php#L352
*/
)
)
)
Получилось:LEFT JOIN (
#subquery subpdo join
SELECT NextDNL.det_id AS next_det_id, NextDNL.naryad_id AS next_naryad_id, NextN.name AS next_naryad_name, NextDNL.smena_id AS next_smena_id, NextS.date AS next_smena_date, NextS.number AS next_smena_number
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
ORDER BY NextS.date ASC, NextS.number ASC) `NextDNL1`
ON tSkladDetNSLink.det_id = NextDNL1.next_det_id AND
(NextDNL1.next_smena_date > Smena.date OR (NextDNL1.next_smena_date = Smena.date AND NextDNL1.next_smena_number > Smena.number)
)
Затем понадобился запрос в on. Сделал так:Добавил массив инструкцию subpdo в первый уровень массива pdoTools, вида:
[subpdo] => Array
(
[smena_limit] => Array
(
/* Здесь массив обычных инструкций pdoTools для запроса. Функция getSubSelectSQL преобразует его в SQL код.
*/
)
)
Преобразуем в SQL. Затем array_walk_recursive github.com/touol/pdoTools/blob/61af551759b1d83a2ee5aba21cbaff772a24312b/core/components/pdotools/model/pdotools/pdofetch.class.php#L214Проходя по всему массиву инструкций pdoTools и с феном подменяем {$subpdo.smena_limit} на этот SQL.
Было:
[on] => tSkladDetNSLink.det_id = NextDNL1.next_det_id
and NextDNL1.next_smena_id = ({$subpdo.smena_limit})
Получилось:ON tSkladDetNSLink.det_id = NextDNL1.next_det_id AND
AND NextDNL1.next_smena_id = (
#subquery {$subpdo.smena_limit}
SELECT NextDNL.smena_id AS on_next_smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
WHERE NextS.date > Smena.date OR (NextS.date = Smena.date AND NextS.number > Smena.number)
ORDER BY NextS.date ASC, NextS.number ASC
LIMIT 1
)
Проверка показала, что и без Add Fenom soft mode все прекрасно работает.
Вот полная распечатка массив нужного запроса:
Array
(
[class] => tSkladDetNSLink
[limit] => 0
[sortby] => Array
(
[Detail.sech] => DESC
[Detail.name] => ASC
[DetailNom.A] => DESC
[DetailNom.B] => DESC
[DetailNom.a_s] => DESC
[DetailNom.b_s] => DESC
[Detail.metall] => DESC
[Detail.L] => DESC
[Detail.comment] => DESC
)
[sortdir] =>
[groupby] =>
[totalVar] => total
[setTotal] =>
[tpl] => Smena.Naryad.Plazma.row
[return] => data
[select] => Array
(
[tSkladDetNSLink] => `tSkladDetNSLink`.`id`, `tSkladDetNSLink`.`name`, `tSkladDetNSLink`.`det_id`, `tSkladDetNSLink`.`naryad_id`, `tSkladDetNSLink`.`smena_id`, `tSkladDetNSLink`.`det_count`, `tSkladDetNSLink`.`smena_count`, `tSkladDetNSLink`.`flanec_con`, `tSkladDetNSLink`.`done`
[Detail] => `Detail`.`sk_order_id` AS `d_sk_order_id`, `Detail`.`excel_id` AS `d_excel_id`, `Detail`.`nom_id` AS `d_nom_id`, `Detail`.`detail_nom_id` AS `d_detail_nom_id`, `Detail`.`systema` AS `d_systema`, `Detail`.`sys_number` AS `d_sys_number`, `Detail`.`sech` AS `d_sech`, `Detail`.`name` AS `d_name`, `Detail`.`articul` AS `d_articul`, `Detail`.`mark` AS `d_mark`, `Detail`.`A` AS `d_A`, `Detail`.`B` AS `d_B`, `Detail`.`a_s` AS `d_a_s`, `Detail`.`b_s` AS `d_b_s`, `Detail`.`L` AS `d_L`, `Detail`.`number_shina` AS `d_number_shina`, `Detail`.`metall` AS `d_metall`, `Detail`.`detType` AS `d_detType`, `Detail`.`comment` AS `d_comment`, `Detail`.`count` AS `d_count`, `Detail`.`pro_count` AS `d_pro_count`, `Detail`.`sklad_count` AS `d_sklad_count`, `Detail`.`otgr_count` AS `d_otgr_count`, `Detail`.`SN` AS `d_SN`, `Detail`.`price_metall` AS `d_price_metall`, `Detail`.`price_job` AS `d_price_job`, `Detail`.`price` AS `d_price`, `Detail`.`status_id` AS `d_status_id`, `Detail`.`flanec` AS `d_flanec`, `Detail`.`add_job` AS `d_add_job`, `Detail`.`add_mat` AS `d_add_mat`, `Detail`.`price_svarka` AS `d_price_svarka`, `Detail`.`price_pokraska` AS `d_price_pokraska`, `Detail`.`price_office` AS `d_price_office`, `Detail`.`price_ceh` AS `d_price_ceh`, `Detail`.`price_zp` AS `d_price_zp`, `Detail`.`sektor_upravleniya` AS `d_sektor_upravleniya`, `Detail`.`fas_krug` AS `d_fas_krug`, `Detail`.`fas_pryam` AS `d_fas_pryam`, `Detail`.`vozd_krug` AS `d_vozd_krug`, `Detail`.`vozd_pryam` AS `d_vozd_pryam`, `Detail`.`fanec_count0` AS `d_fanec_count0`, `Detail`.`plazma` AS `d_plazma`
[Order] => `Order`.`period_id` AS `o_period_id`, `Order`.`order_id` AS `o_order_id`, `Order`.`excel_id` AS `o_excel_id`, `Order`.`org_id` AS `o_org_id`, `Order`.`loc_org_id` AS `o_loc_org_id`, `Order`.`type` AS `o_type`, `Order`.`kontragent` AS `o_kontragent`, `Order`.`automobile` AS `o_automobile`, `Order`.`sentdate` AS `o_sentdate`, `Order`.`plan_makedate` AS `o_plan_makedate`, `Order`.`makedate` AS `o_makedate`, `Order`.`sklad_date` AS `o_sklad_date`, `Order`.`otgr_date` AS `o_otgr_date`, `Order`.`createby_user_id` AS `o_createby_user_id`, `Order`.`status_id` AS `o_status_id`, `Order`.`comment` AS `o_comment`, `Order`.`price` AS `o_price`, `Order`.`beznal` AS `o_beznal`, `Order`.`sum_closed` AS `o_sum_closed`, `Order`.`order_date` AS `o_order_date`, `Order`.`koef_zhuk` AS `o_koef_zhuk`
[Naryad] => `Naryad`.`name` AS `n_name`
[Smena] => `Smena`.`date` AS `s_date`, `Smena`.`number` AS `s_number`, `Smena`.`hour` AS `s_hour`
[DetailNom] => `DetailNom`.`class_id` AS `dn_class_id`, `DetailNom`.`sech` AS `dn_sech`, `DetailNom`.`name2` AS `dn_name2`, `DetailNom`.`articul` AS `dn_articul`, `DetailNom`.`articul2` AS `dn_articul2`, `DetailNom`.`A` AS `dn_A`, `DetailNom`.`B` AS `dn_B`, `DetailNom`.`a_s` AS `dn_a_s`, `DetailNom`.`b_s` AS `dn_b_s`, `DetailNom`.`L` AS `dn_L`, `DetailNom`.`number_shina` AS `dn_number_shina`, `DetailNom`.`metall` AS `dn_metall`, `DetailNom`.`gauge` AS `dn_gauge`, `DetailNom`.`detType` AS `dn_detType`, `DetailNom`.`S` AS `dn_S`
[NomTypeJob] => `NomTypeJob`.`name` AS `tj_name`, `NomTypeJob`.`description` AS `tj_description`
[NextDNL1] => NextDNL1.next_naryad_id, NextDNL1.next_naryad_name,
NextDNL1.next_smena_id, NextDNL1.next_smena_date, NextDNL1.next_smena_number
[0] => tSkladDetNSLink.smena_count as sum_smena_count
[1] => Detail.SN/tSkladDetNSLink.det_count*tSkladDetNSLink.smena_count as sum_naryad_s
)
[leftJoin] => Array
(
[Detail] => Array
(
[class] => tSkladOrderList
[on] => Detail.id=tSkladDetNSLink.det_id
)
[Order] => Array
(
[class] => tSkladOrders
[on] => Order.id=Detail.sk_order_id
)
[Naryad] => Array
(
[class] => tSkladNaryad
[on] => Naryad.id=tSkladDetNSLink.naryad_id
)
[Smena] => Array
(
[class] => tSkladSmena
[on] => Smena.id=tSkladDetNSLink.smena_id
)
[DetailNom] => Array
(
[class] => DetailNom
[on] => DetailNom.id=Detail.nom_id
)
[DetailClass] => Array
(
[class] => DetailClass
[on] => DetailClass.id=DetailNom.class_id
)
[NomTypeJob] => Array
(
[class] => NomTypeJob
[on] => NomTypeJob.id=DetailClass.type_job_id
)
[NextDNL1] => Array
(
[class] => tSkladDetNSLink
[on] => tSkladDetNSLink.det_id = NextDNL1.next_det_id and
(NextDNL1.next_smena_date > Smena.date OR (NextDNL1.next_smena_date = Smena.date AND NextDNL1.next_smena_number > Smena.number))
and NextDNL1.next_smena_id = ({$subpdo.smena_limit})
[subpdo] => Array
(
[class] => tSkladDetNSLink
[alias] => NextDNL
[select] => Array
(
[NextDNL] => NextDNL.det_id as next_det_id, NextDNL.naryad_id AS next_naryad_id, NextN.name AS next_naryad_name,
NextDNL.smena_id AS next_smena_id, NextS.date AS next_smena_date, NextS.number AS next_smena_number
)
[leftJoin] => Array
(
[NextS] => Array
(
[class] => tSkladSmena
[on] => NextS.id=NextDNL.smena_id
)
[NextN] => Array
(
[class] => tSkladNaryad
[on] => NextN.id=NextDNL.naryad_id
)
)
[sortby] => Array
(
[NextS.date] => ASC
[NextS.number] => ASC
)
)
)
[PlazmaList] => Array
(
[class] => PlazmaList
[on] => PlazmaList.det_id=tSkladDetNSLink.det_id
)
)
[where] => Array
(
[Detail.sech] => pryam
[Detail.name] => зонт
[DetailNom.A] => 2000
[DetailNom.B] => 1500
[DetailNom.a_s] => 500
[DetailNom.b_s] => 500
[Detail.metall] => 0,7Ц
[Detail.L] => 0
[Detail.comment] => тип 1, ф355 заузить под наш отвод
[tSkladDetNSLink.smena_id] => 65
[tSkladDetNSLink.naryad_id] => 8
[NextDNL1.next_smena_id] => 66
[PlazmaList.file_true] => 0
)
[tplWrapper] => Smena.Naryad.Plazma.Outer
[tpl_sort_sum] => Smena.Naryad.Plazma.row_sort_sum
[subpdo] => Array
(
[smena_limit] => Array
(
[class] => tSkladDetNSLink
[alias] => NextDNL
[select] => Array
(
[NextDNL] => NextDNL.smena_id AS on_next_smena_id
)
[leftJoin] => Array
(
[NextS] => Array
(
[class] => tSkladSmena
[on] => NextS.id=NextDNL.smena_id
)
[NextN] => Array
(
[class] => tSkladNaryad
[on] => NextN.id=NextDNL.naryad_id
)
)
[where] => Array
(
[0] => NextS.date > Smena.date OR (NextS.date = Smena.date AND NextS.number > Smena.number)
)
[sortby] => Array
(
[NextS.date] => ASC
[NextS.number] => ASC
)
[limit] => 1
)
)
)
Надеюсь подзапросы в pdoTools вам пригодятся :-). Вот ссылкиgithub
Установочный пакет
Сделал пул. Может сейчас @Василий Наумкин примет.
ЗЫ. Наверно можно сделать кучу вложенных подзапросов. Сделано так, что подзапросы обрабатываются рекурсивно. Но не тестировал.
Upd 04.03.2020
Хотелки к следующей версии:
- Обработка JSON и JS. Хотелось бы, чтоб, если обнаружился JSON или JS, чтоб ошибки вообще не возникало. Для JSON при парсинге кода можно проверить является ли строка JSON. Как проверить, является ли строка JSON'ом на PHP. Для JS отследить открытие тега script.
- Обработка ошибок феном. Если у юзера есть разрешение fenom_debuger, то на страницу, где возникла ошибка, и в лог и на почту выводить описание ошибки вида:
- Error: Описание ошибки, как сейчас в логе.
- call stack pdoTools: страница ошибки(id, pagetitle, ссылка в менеджер, № строки)->Шаблон, если ошибка не в контенте страницы(id, name, ссылка в менеджер, № строки)->Чанк (id, name или имя файла, ссылка в менеджер, № строки). (Еще бы сниппет, где возникло если сниппеты вызываются парсером феном это может возможно???). (В классе ввести pdoTools ввести массив call_stack и записывать в него все вызовы чанков)
- call stack Femon: У него стандартная для PHP обработка ошибок и полный call stack можно вывести.
- Конфигурация модификаторов феном в системных параметрах MODX.Тут которые.. Только по безопасности продумывать надо. Или не надо??
- Псевдокод. Мне нужно предоставить юзерам возможность вводить и править формулы. С нуля писать интерпретатор псевдокода — это жесть. Тем более в феном уже практически все есть. То есть, ограничение вызываемых функций php. Можно сделать отдельный компонент от pdoTools, но пока не понятно, может лучше конфигуратор параметров pdoTools сделать.
- femonSyntax вывести из $this->config или разделить $this->config на массив параметров pdoTools и массив конфига запроса pdoTools
- Проверять на присутствие инструкций фенома перед вызовом getChunk. В walkFunc точно надо.
Поблагодарить автора
Отправить деньги
Комментарии: 64
А при чём здесь pdoTools, зачем править исходник? Почему не использовать pdoFetch, или pdoResources или чем то другом построеном на pdoFetch? Они умеет работать с любими таблицами так что не нужно и костылей лепить. И можно спокойно делать leftJoin.
Потом сложно обновлять сайты, и нужно все файлы сверять.
Потом сложно обновлять сайты, и нужно все файлы сверять.
Подзапросы pdoTools не умеет делать!!! Точнее pdoFetch не умеет.
Он умеет, работаю проблем не возникало. Если у Вас проблема можно в сниппете сделать
запрос
запрос
Напишите с pdoFetch запрос
SELECT tSkladDetNSLink.id, Smena.id, (SELECT NextDNL.smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
WHERE NextS.date > Smena.date
ORDER BY NextS.date ASC, NextS.number ASC
LIMIT 1) AS on_next_smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`
LEFT JOIN `modx_tsklad_smena` `Smena` ON Smena.id=tSkladDetNSLink.smena_id
WHERE Smena.id > 0
ORDER BY tSkladDetNSLink.id DESC
LIMIT 10
так, чтоб в конфиге запроса не было названий таблиц с префиксом базы modx_tsklad_detail_naryad_smena_link, modx_tsklad_smena и не надо лишних сниппетов(Я уже заманался вспоминать какой сниппет для чего нужен). Я проверю у себя :-).
Решил проверить как сработает и написал простенький код :-):
Вот вывел:
{'!pdoResources' | snippet :[
'loadModels'=>'tSklad',
'subpdo'=>[
'test'=>[
'class'=>'tSkladDetNSLink',
'alias'=>'NextDNL',
'select'=>[
'NextDNL'=>'NextDNL.smena_id',
],
'leftJoin'=>[
'NextS'=>[
'class'=>'tSkladSmena',
'on'=>'NextS.id=NextDNL.smena_id',
'where'=>[
'NextS.date > Smena.date',
],
],
],
'where'=>[
'NextS.date > Smena.date',
],
'sortby'=>[
'NextS.date'=>'ASC',
'NextS.number'=>'ASC',
],
'limit'=>1,
],
],
'class'=>'tSkladDetNSLink',
'select'=>[
'tSkladDetNSLink'=>'tSkladDetNSLink.id,Smena.id as smena_id, ({$subpdo.test}) as on_next_smena_id',
],
'leftJoin'=>[
'Smena'=>[
'class'=>'tSkladSmena',
'on'=>'Smena.id=tSkladDetNSLink.smena_id',
],
],
'where'=>[
'Smena.id > 0',
],
'sortby'=>[
'tSkladDetNSLink.id'=>'DESC',
],
'limit'=>10,
'tpl'=>'subpdo_test',
'showLog'=>1,
]}
И этот код я уже считаю простеньким :-). Есть у меня подобные конфиги и на 571 строку! Жесть.Вот вывел:
Потом сложно обновлять сайты, и нужно все файлы сверять.Надеюсь Василий пул реквест примет и будет стандарт. Подзапросы нужны, хотя и не часто.
PR отредактируйте, чтобы код был написан красиво и по тому стандарту, который используется в pdoTools.
P.S.
В каждой строчке…
P.S.
В каждой строчке…
Это из-за чего могли отступы полезть?
У вас табуляция, насколько я вижу… А в pdotools — пробелы.
Поправил. Правильно поправил-то?
Вроде да, Вася там уже более тщательно проверит.
Я уже не принял предыдущий PR и пропихивать мне его еще раз, под видом необходимого для подзапросов — очень странно.
Какая связь вообще между генерацией SQL запроса в БД и шаблонизатором?
Ты вот такое прям серьёзно пишешь, это не прикол?
Да хоть бы отформатировал в PSR-2 свою писанину, чтобы читать это возможно было.
Это ты еще и 2 новых версии pdoTools сразу выпустил? Ну вообще орёл.
Какая связь вообще между генерацией SQL запроса в БД и шаблонизатором?
Ты вот такое прям серьёзно пишешь, это не прикол?
Может сейчас Василий Наумкин примет.Нет конечно, не примет. Ты меня за дурака держишь, или что?
Да хоть бы отформатировал в PSR-2 свою писанину, чтобы читать это возможно было.
Это ты еще и 2 новых версии pdoTools сразу выпустил? Ну вообще орёл.
под видом необходимого для подзапросовЛадно счас протестирую на коде из коммента. Поставил чистый pdoTools 2.11.3-pl. Ответ:
0.0009770: SQL prepared "SELECT tSkladDetNSLink.id, Smena.id as smena_id, () as on_next_smena_id
Подзапроса нет. Заменяем pdofetch.class.php. Все правильно выведено :-). Add Fenom soft mode не потребовалось.
Страницы сайта не работают. Ошибка pdotools.class.php: 989) Unexpected tag 'display' in 0b3013274c174a9c5505daeb0e70dfc6 line 27, near '{display:' < — there
Через modDevTools заменяю все {display на { display. Затем также {font
Сайт заработал. В getTables тоже все работает :-). Ну я написал, что не все тестировал. Что-то когда-то не запустилось, а с Add Fenom soft mode заработало. И дальше я со стандартным пакетом не работал. И тут
Эта возможно с этой правкой Add Fenom soft mode… Без нее, скорей всего, феном не поймет, тоже оговорился что скорее всего.
PR Add Fenom soft mode не требуется. Если он вам так не нравиться, подзапросы можно принять без него. Актуальные изменения только в pdofetch.class.php.
Правок не много и сами можете написать так как вам хочется. Только синтаксис subpdo просьба сохранить, но тоже не обязательно :-). 1 сниппет можно и поправить.
Саша, ты несёшь такую пургу, что я просто теряюсь.
Скажи пожалуйста, каким образом у тебя построение запроса через xPDO приводит к ошибке работы Fenom? Это откуда должны расти руки, чтобы так получалось? Ты понимаешь, что Fenom в pdoTools был добавлен лишь в версии 2.0, и как-то до этого запросы прекрасно строились без него?
Пока ты не ответишь на этот вопрос, я не вижу смысла продолжать общение.
Скажи пожалуйста, каким образом у тебя построение запроса через xPDO приводит к ошибке работы Fenom? Это откуда должны расти руки, чтобы так получалось? Ты понимаешь, что Fenom в pdoTools был добавлен лишь в версии 2.0, и как-то до этого запросы прекрасно строились без него?
Пока ты не ответишь на этот вопрос, я не вижу смысла продолжать общение.
Саша, ты несёшь такую пургу, что я просто теряюсь.Для меня вроде все логично что я пишу, но я могу ошибаться и у людей с разным опытом разные мнения. И не супер писатель я. Не всегда понятно пишу. Надо общаться и писать просто больше…
Скажи пожалуйста, каким образом у тебя построение запроса через xPDO приводит к ошибке работы Fenom?Что-то я совсем не понял с честь чего у вас такой вопрос?? «построение запроса через xPDO приводит к ошибке работы Fenom» — вроде нигде такого не говорил. Василий, пожалуйста, поясните, что вы имеете в виду.
Что-то я совсем не понял с честь чего у вас такой вопрос?? «построение запроса через xPDO приводит к ошибке работы Fenom» — вроде нигде такого не говорил.У тебя с памятью беда, или с логикой?
Вот это вот — оно про что?
Почему у тебя какие-то ошибки в парсинге именно после выполнения запроса? Какие ты там display и font меняешь, зачем? Какое оно имеет отношение к запросам или подзапросам в БД?
Или ты (я только сейчас об этом подумал) проверяешь свой новый придуманный синтаксис на pdoFetch с твоими изменениями, и без них? И приводишь как доказательство, что твой синтаксис без твоих изменений в pdoFetch не работает?
Если это и правда так, то я вообще уже не знаю, куда в скорую звонить, в какой регион.
проверяешь свой новый придуманный синтаксис на pdoFetch с твоими изменениями, и без них? И приводишь как доказательство, что твой синтаксис без твоих изменений в pdoFetch не работает?1) Сперва проверил синтаксис на чистом pdoTools. Понятно дело ошибка.
2) Проверил синтаксис только с заменой pdoFetch. Заработало. То есть
Я уже не принял предыдущий PR
принимать этот PR Не требуется..
3) Ну и на всякий случай проверил как весь сайт без предыдущего PR будет работать. Нормально работает. (Только в стилях пробелов понаставил).
Сейчас подготовлю PR чисто для подзапросов. Еще через минут 20 будет.
принимать этот PR Не требуется..А нафига ж ты его прислал с своём PR?
Еще через минут 20 будет.Не надо.
А нафига ж ты его прислал с своём PR?Торопился не проверил. И мне он нравиться :-).
Не надо.Подсадили всех на pdoTools, а теперь нужные правки отказываетесь принять? :-) Проявите ответственность :-)
И мне он нравиться :-).Ну не может быть хороший программист неграмотным. tsya.ru
Проявите ответственность :-)Я и так много времени на тебя потратил. Иди, просвещайся.
Зачем стучаться в закрытую дверь? Просто сделай отдельный пакет. Кому надо поставит. Не нужно лезть в исходники!!!
Я, например, когда начинал свой путь в MODX и мне надо было добавить функционал в Tickets, сделал отдельный TicketMessages, расширяющий исходный компонент, в который добавил всё, что мне надо. Я не мучал автора своими пулами.
Я, например, когда начинал свой путь в MODX и мне надо было добавить функционал в Tickets, сделал отдельный TicketMessages, расширяющий исходный компонент, в который добавил всё, что мне надо. Я не мучал автора своими пулами.
Не нужно лезть в исходники!!!Думал расширить феном, но там все функции оказались privite и protected. И меня это так разочаровало, что функции pdoTools я и не думал расширять, а тупо писал что мне нужно в исходники. Иногда нужно исходники править, чтоб не усложнять код и, если исходники обновились, чтобы компонент смог работать.
Я не мучал автора своими пулами.Зря :-). Авторы бывают ленивыми и зазнайками. Их надо мучать, чтоб прогресс был. Подзапросы вроде вещь актуальная. Разве нет?
И не стоит плодить кучу разных компонентов. В wordpress, взяв сделанный кем-то сайт, приходиться изучать десяток новых плагинов. Такой компонент как pdoTools лучше, чтоб один был и со стандартным синтаксисом.
Авторы бывают ленивыми и зазнайками. Их надо мучать, чтоб прогресс был.А еще авторы бывают опытными, и понимающими, что нужно их дополнениям, а что нет.
Пиши свои допы, развивай — Сергей верно говорит.
Подзапросы вроде вещь актуальная. Разве нет?Внезапно, нет.
pdoTools появился в 2013 году и целых 7 лет эти подзапросы никого не волновали. И сейчас не волнуют, увы.
Меня волновали. Года 3 :-). Просто обходился чистым sql. Думаю, далеко не всем, но нужны. Может просто никто не говорил. Вообще интересно опрос устроить. Правда на modx.pro опросов нет :-(.
Пиши свои допы, развивай — Сергей верно говорит.Ниже пример с подзапросом. Нужно для одного этапа производства детали получить на когда запланирован следующий этап. С измененным pdoTool, это можно получить через pdoResources. Не надо писать никаких сниппетов. Их уже и так целая куча.
Как можно сделать доп, чтобы можно было так же через pdoResources вывести нужную информацию, не меняя pdoTools?
{'!pdoResources' | snippet :[
'loadModels'=>'tSklad',
'subpdo'=>[
'test'=>[
'class'=>'tSkladDetNSLink',
'alias'=>'NextDNL',
'select'=>[
'NextDNL'=>'NextDNL.smena_id',
],
'leftJoin'=>[
'NextS'=>[
'class'=>'tSkladSmena',
'on'=>'NextS.id=NextDNL.smena_id',
'where'=>[
'NextS.date > Smena.date',
],
],
],
'where'=>[
'NextS.date > Smena.date',
],
'sortby'=>[
'NextS.date'=>'ASC',
'NextS.number'=>'ASC',
],
'limit'=>1,
],
],
'class'=>'tSkladDetNSLink',
'select'=>[
'tSkladDetNSLink'=>'tSkladDetNSLink.id,Smena.id as smena_id, ({$subpdo.test}) as on_next_smena_id',
],
'leftJoin'=>[
'Smena'=>[
'class'=>'tSkladSmena',
'on'=>'Smena.id=tSkladDetNSLink.smena_id',
],
],
'where'=>[
'Smena.id > 0',
],
'sortby'=>[
'tSkladDetNSLink.id'=>'DESC',
],
'limit'=>10,
'tpl'=>'subpdo_test',
'showLog'=>1,
]}
А авторы Tikkets вообще собираются редактор сообщений обновлять?
Офтопик (скрытый раскрывающейся блок) вроде уже давно стандарт. Километры кодов, логов и запросов нагружают восприятие текста, а вырезать лишнее замучишся. В офтопик проще засунуть и восприятие не нагружает и кому надо может все полностью посмотреть.
Еще выделение цветом блока в блоке кода тоже хорошо было бы. И загрузка файлов без перехода в Файлохранилище тоже не помешает.
Офтопик (скрытый раскрывающейся блок) вроде уже давно стандарт. Километры кодов, логов и запросов нагружают восприятие текста, а вырезать лишнее замучишся. В офтопик проще засунуть и восприятие не нагружает и кому надо может все полностью посмотреть.
Еще выделение цветом блока в блоке кода тоже хорошо было бы. И загрузка файлов без перехода в Файлохранилище тоже не помешает.
А авторы Tikkets вообще собираются редактор сообщений обновлять?Нет, не собираются.
Авторам Tickets (обрати внимание на правильное написание) есть много чем другим заняться. Судя по твоему энтузиазму, ты легко запилишь прекрасный форк, на который все пользователи Tickets легко перейдут без потери данных.
И будешь его потом поддерживать бесплатно, годами.
ты легко запилишь прекрасный форкЗапилю :-). Надо для работы. Не легко :-(.
И будешь его потом поддерживать бесплатно, годами.Не буду :-). Наверно передам кому-нибудь, если будут желающие. Но пока такой ситуации нет, так что вопрос открытый. Проблемы решаю по мере поступления.
Полная хрень! Зачем изобретать велосипед и влезать в ядро pdoTools ради 1-3 вложенных запросов, если есть xPDO.getCollection!?
Вполне логично написать свой сниппет или плагин!
Вполне логично написать свой сниппет или плагин!
Уф… Пример напишите запроса с xPDO.getCollection раз. Два pdoTools удобнее.
Короче не морочте мне голову :-)
Вполне логично написать свой сниппет или плагин!Лишние сниппеты не нужны!!! А, кстати, плагин тут причем?
Короче не морочте мне голову :-)
Что то странно, то не подходит, это тоже. )))
$query = $xpdo->newQuery('Box');
$query->select($xpdo->getSelectColumns('Box'));
$query->select(array(
'Owner.name'
));
$query->leftJoin('Owner','Owner');
$boxes = $xpdo->getCollection('Box',$query);
Ответ про плагин: плагином можно сформировать ответ после сохранения ресурса к примеру или наоборот подгрузить. Нужен был запрос типа такого:Александр не знает, что xPDO и следовательно, pdoTools, прекрасно понимают сырые запросы, если засунуть их в строку внутри массива.
И тогда вполне возможно написать даже то, что он приводит в начале заметки:
{'!pdoResources' | snippet :[
'class' => 'tSkladDetNSLink',
'select' => ['*
FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`
LEFT JOIN `modx_tsklad_order_list` `Detail` ON Detail.id=tSkladDetNSLink.det_id
LEFT JOIN `modx_tsklad_orders` `Order` ON Order.id=Detail.sk_order_id
LEFT JOIN `modx_tsklad_naryad` `Naryad` ON Naryad.id=tSkladDetNSLink.naryad_id
LEFT JOIN `modx_tsklad_smena` `Smena` ON Smena.id=tSkladDetNSLink.smena_id
LEFT JOIN `modx_nomenclature_detail_nom` `DetailNom` ON DetailNom.id=Detail.nom_id
LEFT JOIN `modx_nomenclature_detail_class` `DetailClass` ON DetailClass.id=DetailNom.class_id
LEFT JOIN `modx_nomenclature_type_job` `NomTypeJob` ON NomTypeJob.id=DetailClass.type_job_id
LEFT JOIN (
SELECT NextDNL.det_id AS next_det_id, NextDNL.naryad_id AS next_naryad_id, NextN.name AS next_naryad_name, NextDNL.smena_id AS next_smena_id, NextS.date AS next_smena_date, NextS.number AS next_smena_number
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
ORDER BY NextS.date ASC, NextS.number ASC) `NextDNL1`
ON tSkladDetNSLink.det_id = NextDNL1.next_det_id AND
(NextDNL1.next_smena_date > Smena.date OR (NextDNL1.next_smena_date = Smena.date AND NextDNL1.next_smena_number > Smena.number)
)
AND NextDNL1.next_smena_id = (
SELECT NextDNL.smena_id AS on_next_smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
WHERE NextS.date > Smena.date OR (NextS.date = Smena.date AND NextS.number > Smena.number)
ORDER BY NextS.date ASC, NextS.number ASC
LIMIT 1
)
LEFT JOIN `modx_plazma_list` `PlazmaList` ON PlazmaList.det_id=tSkladDetNSLink.det_id
'],
'where' => [
"(`Detail`.`sech` = 'pryam' AND `Detail`.`name` = 'зонт' AND `DetailNom`.`A` = '2000' AND `DetailNom`.`B` = '1500' AND `DetailNom`.`a_s` = '500' AND `DetailNom`.`b_s` = '500' AND `Detail`.`metall` = '0,7Ц' AND `Detail`.`L` = '0' AND `Detail`.`comment` = 'тип 1, ф355 заузить под наш отвод' AND `tSkladDetNSLink`.`smena_id` = 65 AND `tSkladDetNSLink`.`naryad_id` = 8 AND `NextDNL1`.`next_smena_id` = '66' AND `PlazmaList`.`file_true` = '0')"
],
'sortby' => 'Detail.sech DESC, Detail.name ASC, DetailNom.A DESC, DetailNom.B DESC, DetailNom.a_s DESC, DetailNom.b_s DESC, Detail.metall DESC, Detail.L DESC, Detail.comment',
'sortdir' => 'DESC'
'limit' => 0,
'showLog' => 1,
]}
Запрос, вполне себе, подготавливается
У меня он не может быть выполнен просто потому, что таких таблиц в системе нет.
Но можно сравнить исходные параметры и конечный код — они идентичны, за исключением FROM из несуществующей таблицы (что при наличии модели tSkladDetNSLink будет заменено на FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`) и экранирования сортировки (которой xPDO закрывает старую уязвимость).
Так что, кому уж прям очень нужны подзапросы в pdoTools — они уже там есть, с самого начала.
Блин. Мне не нужны сырые запросы. Мне надо, чтоб запрос был подготовлен. Вдруг я префикс базы захочу изменить, а в куче запросов он будет указан.
Вдруг я префикс базы захочу изменить, а в куче запросов он будет указан.Ну ты же любишь использовать плейсхолдеры в запросах, вот тебе еще один: {'table_prefix' | option}
А если серьёзно, то ты пишешь очень сложный запрос, который не понадобится 99% пользователей pdoTools, а может и вообще MODX.
Он не станет менее сложным, если засунуть его в массив Fenom, никто ничего от этого не выиграет.
Усилия по добавлению этого функционала не просто ничего не стоят, они отрицательные не длинной дистанции, потому что нужно будет отвечать на вопросы по конвертации этих твоих вложенных массивов в SQL.
Периодически будут находиться люди, пытающиеся наворотить какую-нибудь фигню с этими параметрами. Как сейчас это делают с долбаным tvFilters.
Рейтинг этой заметки на данный момент составляет 0 при 34 комментариях, что уже намекает на её полезность.
Я этот PR гарантированно не приму, удачи в развитии своих дополнений.
А если серьёзно, то ты пишешь очень сложный запрос, который не понадобится 99% пользователей pdoTools, а может и вообще MODXЕсли 1% понадобится, то уже неплохо. 99% не понадобиться — это не слишком хороший критерий. Взлетит не взлетит 100% не угадаешь. То есть, это критерий на способности предсказывать будущие. А оно не слишком предсказуемо.
Он не станет менее сложным, если засунуть его в массив Fenom, никто ничего от этого не выиграет.А, кстати, тогда зачем вообще запросы описывать массивом феном? Можно же вообще писать чисто SQL.
XPDO это типа ORM. В нем получил объект и сразу можно что-то записать в базу. В pdoTools только чисто вывод.
Мне просто удобнее сам синтаксис pdoTools писать. И, так как запрос массив, есть возможность на лету его поменять. Приготовил массив запроса, а потом where добавляешь или удаляешь когда надо. На чисто sql менять where жуть. Код 5 лет назад :-). Ни pdoTools ни strftime еще не знал.
if(isset($_GET['date1'])){
$modx->setPlaceholder('date1',$_GET['date1']);
if(isset($_GET['date2'])){
$modx->setPlaceholder('date2',$_GET['date2']);
}
if($_GET['date1']!='' and $_GET['date2']==''){
$where = "where o.makedate >='".$_GET['date1']." 00:00:00' and l.status_id=1";
}elseif($_GET['date2']!=''){
$where = "where o.makedate >='".$_GET['date1']." 00:00:00' and o.makedate <='".$_GET['date2']." 23:59:59' and l.status_id=1";
}
}else{
$where = "where l.status_id=1";
}
Тоже для XPDO и pdoTools$where = [ 'l.status_id'=>1];
if($_GET['date1']){
$modx->setPlaceholder('date1',$_GET['date1']);
$where['o.makedate:>='] = '".$_GET['date1']." 00:00:00'";
}
if($_GET['date2']){
$modx->setPlaceholder('date2',$_GET['date2']);
$where['o.makedate:<='] = '".$_GET['date2']." 23:59:59'";
}
Явно проще. Особенно когда фильтр больше на параметров 6.А вот пример уже с феном.
{set $where = [
'Detail.flanec:NOT IN'=>[1,3],
'Detail.sech'=>'pryam',
]}
{if $.get.sk_order_id}{set $where['Detail.sk_order_id']=$.get.sk_order_id}{/if}
{if $.get.smena_id}{set $where['tSkladDetNSLink.smena_id']=$.get.smena_id}{/if}
{if $.get.type_job_id}{set $where['DetailClass.type_job_id']=$.get.type_job_id}{/if}
Так что запрос в массиве штука полезная. А вот подзапросов в массиве у меня не было. Поиграюсь, посмотрю, что можно с ними сделать. Хотя, конечно, их на каждом шагу внедрять не стоит.
Усилия по добавлению этого функционала не просто ничего не стоят, они отрицательные не длинной дистанции, потому что нужно будет отвечать на вопросы по конвертации этих твоих вложенных массивов в SQL.Это аргумент. Отвечать на вопросы кучи начинающих прогеров не самая приятная перспектива. Но тормозить из-за этого компоненты или проекты?? Это раз. И два. Отвечать имеет смысл, если развивать свою команду. С которой можно делать очень большие проекты. Такие как linux, например. Думаю сеньор не предел развития программиста. Можно как-бы основать свою школу и стать что-то вроде академика.
Периодически будут находиться люди, пытающиеся наворотить какую-нибудь фигню в этими параметрами. Как сейчас это делают с долбаным tvFilters.Будут явно. Люди пытаются решить свои задачи. Изучаем их задачи и пишем код, чтобы у них был инструмент для их задач :-). Прикалываюсь, если что :-). Но в каждой шутке доля шутки…
Резюме.
Я этот PR не приму, удачи в развитии своих дополнений.
Ну как хотите. Я то надеялся, что вот крутая фишка пользуйтесь. Но, возможно, это и не так круто как мне кажется. Подзапросы, когда они мне понадобятся буду писать в своей версии синтаксиса pdoTools. Просто потому, что мне так удобнее. Сейчас, практические преимущества этой версии не понятны :-(.
PS. Сюда $fields массивом иногда приходят.
$fields = 'SQL_CALC_FOUND_ROWS ' . $fields;
В итоге запрос выглядит так:SELECT SQL_CALC_FOUND_ROWSArray FROM
Где $fields массивом становиться не нашел. Просто implode сделал. Может разберетесь?
Дико извиняюсь, не удержался
$where['o.makedate:>='] = '".$_GET['date1']." 00:00:00'";
$where['Detail.sk_order_id']=$.get.sk_order_id
Если бы ты принял этот PR, пришлось бы pdoTools удалять.
Магистр кода 99 уровня
Магистр кода 99 уровня
$modx->setPlaceholder('date1',$_GET['date1']);Ну нахер. Штопать таки дыры, искать в коде display и fonts. И ещё Бог знает чего.
$where['o.makedate:>='] = '".$_GET['date1']." 00:00:00'";
Ну если вы магистр напишите внятную инструкцию как делать санацию параметров.
$where['id'] = (int)$_POST['id'];
(int) это понятно. Для даты strftime можно использовать. А остальное? string, decimal, float. Хотя тоже все понятно. Только писать такие преобразования во все сниппеты долго. Плагин или что-то такое посмотрю. Ну здесь на интранет хакеров лет 10 не предвидеться. А если и предвидятся, то взлом внутреннего сайта это уже мелочь.
Давно уже написано. Да и в инете полно такой информации.
Читал год назад. (int) использую, а с санацией строки проблема вышла. В поле название города кавычки писались и его никто найти не мог. Так что, санация это работа надолго :-(.
Если бы ты принял этот PR, пришлось бы pdoTools удалять.Дыры много где есть. И никто вам не мешает взять и переписать PR или что-то еще без дыр, если они там есть. Вроде ничего такого не должно быть. Все стандартные дыры MODX только.
Я в целом не понимаю, зачем все это.
Такие сложные запросы я выполню с помощью $modx->query
Сколько будет выполнятся такой вопрос, если сверху на него навесить абстракцию в виде pdoTools? Сорок лет?
Такие сложные запросы я выполню с помощью $modx->query
Сколько будет выполнятся такой вопрос, если сверху на него навесить абстракцию в виде pdoTools? Сорок лет?
Сколько будет выполнятся такой вопрос, если сверху на него навесить абстракцию в виде pdoTools? Сорок лет?Преобразовать массив на 10-40 ключей в строку 100-600 символов? Явно миллисекунды :-).
После последней правки, подзапрос добавил плюс 7 мс к общему выполнению запроса. getChunk операция затратная. Целых 5 мс :-).
'select' => ['*
FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`
LEFT JOIN `modx_tsklad_order_list` `Detail` ON Detail.id=tSkladDetNSLink.det_id
LEFT JOIN `modx_tsklad_orders` `Order` ON Order.id=Detail.sk_order_id
LEFT JOIN `modx_tsklad_naryad` `Naryad` ON Naryad.id=tSkladDetNSLink.naryad_id
LEFT JOIN `modx_tsklad_smena` `Smena` ON Smena.id=tSkladDetNSLink.smena_id
LEFT JOIN `modx_nomenclature_detail_nom` `DetailNom` ON DetailNom.id=Detail.nom_id
LEFT JOIN `modx_nomenclature_detail_class` `DetailClass` ON DetailClass.id=DetailNom.class_id
LEFT JOIN `modx_nomenclature_type_job` `NomTypeJob` ON NomTypeJob.id=DetailClass.type_job_id
LEFT JOIN (
SELECT NextDNL.det_id AS next_det_id, NextDNL.naryad_id AS next_naryad_id, NextN.name AS next_naryad_name, NextDNL.smena_id AS next_smena_id, NextS.date AS next_smena_date, NextS.number AS next_smena_number
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
ORDER BY NextS.date ASC, NextS.number ASC) `NextDNL1`
ON tSkladDetNSLink.det_id = NextDNL1.next_det_id AND
(NextDNL1.next_smena_date > Smena.date OR (NextDNL1.next_smena_date = Smena.date AND NextDNL1.next_smena_number > Smena.number)
)
AND NextDNL1.next_smena_id = (
SELECT NextDNL.smena_id AS on_next_smena_id
FROM `modx_tsklad_detail_naryad_smena_link` AS `NextDNL`
LEFT JOIN `modx_tsklad_smena` `NextS` ON NextS.id=NextDNL.smena_id
LEFT JOIN `modx_tsklad_naryad` `NextN` ON NextN.id=NextDNL.naryad_id
WHERE NextS.date > Smena.date OR (NextS.date = Smena.date AND NextS.number > Smena.number)
ORDER BY NextS.date ASC, NextS.number ASC
LIMIT 1
)
LEFT JOIN `modx_plazma_list` `PlazmaList` ON PlazmaList.det_id=tSkladDetNSLink.det_id
'],
Никогда не понимал зачем такие мега запросы писать. Бесполезных join-нов куча. Этаж сколько выборка этого всего идти будет. А потом еще сидеть постоянно разбирать что там написано.Для таких запросов проще временную таблицу сделать куда будут данные сливаться на бэкенде, и потом уже готовые данные забирать на фронте.
Такими запросами, только фронт напрягать.
Почему то всегда охота все в один запрос запихать, но по опыту еще больше времени тратишь на всякие такие выборки.
Еще как вариант делать несколько запросов и получать id которые уже потом идут where в виде product_id IN (тут список id из какой то таблицы)
На примере получения товаров:
Этот код будет делать выборку в десятки раз быстрее:
$ids = [];
$q = $modx->newQuery('modResource');
$q->select('id');
$q->where(array(
'published' => 1,
'class_key' => 'msProduct',
));
if ($q->prepare() && $q->stmt->execute()){
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$ids[] = $row['id'];
}
}
/* @var msProductData $object*/
$q = $modx->newQuery('msProductData');
$q->where(array(
'id:IN' => $ids
));
if($objectList = $modx->getCollection('msProductData', $q)) {
foreach ($objectList as $object) {
echo '<pre>';
print_r( $object->toArray()); die;
}
}
Чем
/* @var msProduct $object*/
$q = $modx->newQuery('msProductData');
$q->where(array(
'Product.published' => 1,
'Product.class_key' => 'msProduct',
));
$q->innerJoin('msProduct','Product','Product.id = msProductData.id');
if($objectList = $modx->getCollection('msProductData', $q)) {
foreach ($objectList as $object) {
echo '<pre>';
print_r( $object->toArray()); die;
}
}
join — зло еще то)) Никогда не понимал зачем такие мега запросы писать. Бесполезных join-нов куча. Этаж сколько выборка этого всего идти будет. А потом еще сидеть постоянно разбирать что там написано.Выборка достаточно быстро идет. Какие-то тормоза не заметны. И в каком таком случае не приходиться разбирать что написано? Что в сниппете что в запросе одинаково приятно.
Для таких запросов проще временную таблицу сделать куда будут данные сливаться на бэкенде, и потом уже готовые данные забирать на фронте.
И еще за актуальность временных таблиц следить. Причем разных нужных данных может быть много вариантов. Вроде кол-во перестановок пропорционально n! Если 2 таблицы по 5 колонок, то кол-во возможных выборок 10! = 3628800 вариантов :-). И еще за актуальность временных таблиц следить. Причем разных нужных данных может быть много вариантов. Вроде кол-во перестановок пропорционально n! Если 2 таблицы по 5 колонок, то кол-во возможных выборок 10! = 3628800 вариантов :-).Временная таблица!
Актуальность в одну минут, вообще не принципиально)))
Актуальность в одну минут, вообще не принципиально)))В смысле, крон настраивать запросы для этих таблиц писать. На 80 базовых таблиц — это офигенное кол-во временных. Сайт только висеть будет их генерировать.
+1
Справедливости ради, я бы поспорил про join.
IN — еще большее зло, если в нем указана целая простыня (тысячи или десятки тысяч) id.
Вот ради интереса копипастнул себе на один из проектов оба варианта и, как я и ожидал, второй существенно быстрее.
На проекте 29705 товаров.
Ну и я заменил getCollection на getCount, потому что получать 30к объектов — самоубийство, даже через более оптимальный getIterator.
Вариант с IN:
IN — еще большее зло, если в нем указана целая простыня (тысячи или десятки тысяч) id.
Вот ради интереса копипастнул себе на один из проектов оба варианта и, как я и ожидал, второй существенно быстрее.
На проекте 29705 товаров.
Ну и я заменил getCollection на getCount, потому что получать 30к объектов — самоубийство, даже через более оптимальный getIterator.
Вариант с IN:
Total time: 0.7136 sВариант с join:
Total time: 0.4630 sНо вариант с IN может оказаться действительно быстрее там, где небольшой перечень id, тут согласен.
Наверное поле куда делался IN, без индекс, и это обычное текстов поле.
Не, это же таблица ms2_products, где id — PK и, естественно, с индексом.
Дело в количестве указанных id, их слишком много, поэтому join работает быстрее.
Дело в количестве указанных id, их слишком много, поэтому join работает быстрее.
Как)) Мне просто интересно?
getCollection — дергает все поля как с site_content так и c ms2_products
Как он может быть быстрее даже с этого ракурса?
Обращение к msProduct?
getCollection — дергает все поля как с site_content так и c ms2_products
Как он может быть быстрее даже с этого ракурса?
Обращение к msProduct?
Покажите код? Один и другой
Да я прям копипастнул, только getCollection на getCount заменил
Вариант с IN:
Вариант с IN:
$ids = [];
$q = $modx->newQuery('modResource');
$q->select('id');
$q->where(array(
'published' => 1,
'class_key' => 'msProduct',
));
if ($q->prepare() && $q->stmt->execute()){
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$ids[] = $row['id'];
}
}
/* @var msProductData $object*/
$q = $modx->newQuery('msProductData');
$q->where(array(
'id:IN' => $ids
));
if($objectCount = $modx->getCount('msProductData', $q)) {
return $objectCount;
}
Total time: 0.4705 sВариант с join:
/* @var msProduct $object*/
$q = $modx->newQuery('msProductData');
$q->where(array(
'Product.published' => 1,
'Product.class_key' => 'msProduct',
));
$q->innerJoin('msProduct','Product','Product.id = msProductData.id');
if($objectCount = $modx->getCount('msProductData', $q)) {
return $objectCount;
}
Total time: 0.4096 sСейчас разница уже не такая большая, но она все еще в пользу join'а.
ну это интересно)) Запомню на будущие.
А теперь тоже самое только к примеру с получением pagetitle и price)
Вот тут явно увидите разницу
А теперь тоже самое только к примеру с получением pagetitle и price)
Вот тут явно увидите разницу
pagetitle и price не самый удачный пример, способом с IN их не очень удобно доставать)
я бы тут из-за удобства выбрал join, хоть он действительно будет немного медленнее
Вариант с IN:
Вариант с join:
я бы тут из-за удобства выбрал join, хоть он действительно будет немного медленнее
Вариант с IN:
$data = [];
$c = $modx->newQuery('msProduct', ['class_key' => 'msProduct', 'published' => 1]);
$c->select(['id', 'pagetitle']);
if ($c->prepare() && $c->stmt->execute()) {
$data = $c->stmt->fetchAll(PDO::FETCH_KEY_PAIR);
}
$c = $modx->newQuery('msProductData', ['id:IN' => array_keys($data)]);
$c->select(['id', 'price']);
if ($c->prepare() && $c->stmt->execute()) {
while ($item = $c->stmt->fetch(PDO::FETCH_ASSOC)) {
$data[$item['id']] = ['pagetitle' => $data[$item['id']], 'price' => $item['price']];
}
}
print_r($data);
return;
Total time: 0.4112 sМожно было еще сделать через ASSOC и array_column, но это медленнее, как мне показалось
Memory: 22 MB
Вариант с join:
$c = $modx->newQuery('msProduct', ['msProduct.class_key' => 'msProduct', 'msProduct.published' => 1]);
$c->select(['msProduct.pagetitle', 'Data.price']);
$c->innerJoin('msProductData', 'Data', 'msProduct.id = Data.id');
if ($c->prepare() && $c->stmt->execute()) {
print_r($c->stmt->fetchAll(PDO::FETCH_ASSOC));
}
return;
Total time: 0.4927 s
Memory: 18 MB
При учете что мне к примеру не нежно ничего получать из site_content а только id, оно еще быстрее будет.
Ноооооо если мы используем getCollection) То innerJoin не позволит сделать select!
Так что скорость ощутим упадет))
Кстати, твой код, исключает getCollection. О чем я писал когда говорил о IN.
Так что если по играть, с кодом, то явно увидишь разницу.
Ноооооо если мы используем getCollection) То innerJoin не позволит сделать select!
Так что скорость ощутим упадет))
Кстати, твой код, исключает getCollection. О чем я писал когда говорил о IN.
Так что если по играть, с кодом, то явно увидишь разницу.
При учете что мне к примеру не нежно ничего получать из site_content а только id, оно еще быстрее будет.Не будет. Только если ты поле контент гнать не будешь. Даже 3G не заметит разницы в несколько небольших полей. Простыня айдишников весит больше, чем price и pagetitle вместе взятые.
Хотя эти айдишники будут внутри сетки гоняться.
if($objectCount = $modx->getCount('msProductData', $q)) {
return $objectCount;
}
в $objectCount запишется 0
Приходилось встречаться что в итоге 0 это тоже true, скорей всего это в старом каком то php
по этому лучше так
return $objectCount;
}
в $objectCount запишется 0
Приходилось встречаться что в итоге 0 это тоже true, скорей всего это в старом каком то php
по этому лучше так
if($count = (boolean)$modx->getCount('modResource', array())){
}
На самом деле getCount всегда возвращает число, поэтому проверка по сути не нужна)
Можно было прям сразу
Можно было прям сразу
return $modx->getCount('modResource', $q));
В варианте с join нет селекта. Т.е. условия теста не равнозначны.
Этот код будет делать выборку в десятки раз быстрее:На практике или в теории? Уверен, если замерить, то join выиграет. Ибо один подготовленный запрос отработает быстрее, чем 2 запроса. Тем более со вторым запросом нужно гнать тонны айдишников по сетке.
join — зло еще то))Только, если ты не умеешь его готовить )) Молотком можно и гвозди забивать и шурупы.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.