Подзапросы для 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
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Потом сложно обновлять сайты, и нужно все файлы сверять.
запрос
так, чтоб в конфиге запроса не было названий таблиц с префиксом базы modx_tsklad_detail_naryad_smena_link, modx_tsklad_smena и не надо лишних сниппетов(Я уже заманался вспоминать какой сниппет для чего нужен). Я проверю у себя :-).
И этот код я уже считаю простеньким :-). Есть у меня подобные конфиги и на 571 строку! Жесть.
Вот вывел:
P.S.
В каждой строчке…
Это из-за чего могли отступы полезть?
Какая связь вообще между генерацией SQL запроса в БД и шаблонизатором?
Ты вот такое прям серьёзно пишешь, это не прикол?
Нет конечно, не примет. Ты меня за дурака держишь, или что?
Да хоть бы отформатировал в PSR-2 свою писанину, чтобы читать это возможно было.
Это ты еще и 2 новых версии pdoTools сразу выпустил? Ну вообще орёл.
Подзапроса нет. Заменяем 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 заработало. И дальше я со стандартным пакетом не работал. И тут
, тоже оговорился что скорее всего.
PR Add Fenom soft mode не требуется. Если он вам так не нравиться, подзапросы можно принять без него. Актуальные изменения только в pdofetch.class.php.
Правок не много и сами можете написать так как вам хочется. Только синтаксис subpdo просьба сохранить, но тоже не обязательно :-). 1 сниппет можно и поправить.
Скажи пожалуйста, каким образом у тебя построение запроса через xPDO приводит к ошибке работы Fenom? Это откуда должны расти руки, чтобы так получалось? Ты понимаешь, что Fenom в pdoTools был добавлен лишь в версии 2.0, и как-то до этого запросы прекрасно строились без него?
Пока ты не ответишь на этот вопрос, я не вижу смысла продолжать общение.
Что-то я совсем не понял с честь чего у вас такой вопрос?? «построение запроса через xPDO приводит к ошибке работы Fenom» — вроде нигде такого не говорил. Василий, пожалуйста, поясните, что вы имеете в виду.
Вот это вот — оно про что?
Почему у тебя какие-то ошибки в парсинге именно после выполнения запроса? Какие ты там display и font меняешь, зачем? Какое оно имеет отношение к запросам или подзапросам в БД?
Или ты (я только сейчас об этом подумал) проверяешь свой новый придуманный синтаксис на pdoFetch с твоими изменениями, и без них? И приводишь как доказательство, что твой синтаксис без твоих изменений в pdoFetch не работает?
Если это и правда так, то я вообще уже не знаю, куда в скорую звонить, в какой регион.
2) Проверил синтаксис только с заменой pdoFetch. Заработало. То есть
принимать этот PR Не требуется..
3) Ну и на всякий случай проверил как весь сайт без предыдущего PR будет работать. Нормально работает. (Только в стилях пробелов понаставил).
Сейчас подготовлю PR чисто для подзапросов. Еще через минут 20 будет.
Не надо.
Подсадили всех на pdoTools, а теперь нужные правки отказываетесь принять? :-) Проявите ответственность :-)
Я и так много времени на тебя потратил. Иди, просвещайся.
Я, например, когда начинал свой путь в MODX и мне надо было добавить функционал в Tickets, сделал отдельный TicketMessages, расширяющий исходный компонент, в который добавил всё, что мне надо. Я не мучал автора своими пулами.
Зря :-). Авторы бывают ленивыми и зазнайками. Их надо мучать, чтоб прогресс был. Подзапросы вроде вещь актуальная. Разве нет?
И не стоит плодить кучу разных компонентов. В wordpress, взяв сделанный кем-то сайт, приходиться изучать десяток новых плагинов. Такой компонент как pdoTools лучше, чтоб один был и со стандартным синтаксисом.
Пиши свои допы, развивай — Сергей верно говорит.
Внезапно, нет.
pdoTools появился в 2013 году и целых 7 лет эти подзапросы никого не волновали. И сейчас не волнуют, увы.
Как можно сделать доп, чтобы можно было так же через pdoResources вывести нужную информацию, не меняя pdoTools?
Офтопик (скрытый раскрывающейся блок) вроде уже давно стандарт. Километры кодов, логов и запросов нагружают восприятие текста, а вырезать лишнее замучишся. В офтопик проще засунуть и восприятие не нагружает и кому надо может все полностью посмотреть.
Еще выделение цветом блока в блоке кода тоже хорошо было бы. И загрузка файлов без перехода в Файлохранилище тоже не помешает.
Авторам Tickets (обрати внимание на правильное написание) есть много чем другим заняться. Судя по твоему энтузиазму, ты легко запилишь прекрасный форк, на который все пользователи Tickets легко перейдут без потери данных.
И будешь его потом поддерживать бесплатно, годами.
Не буду :-). Наверно передам кому-нибудь, если будут желающие. Но пока такой ситуации нет, так что вопрос открытый. Проблемы решаю по мере поступления.
Вполне логично написать свой сниппет или плагин!
Лишние сниппеты не нужны!!! А, кстати, плагин тут причем?
Короче не морочте мне голову :-)
И тогда вполне возможно написать даже то, что он приводит в начале заметки:
Запрос, вполне себе, подготавливается
У меня он не может быть выполнен просто потому, что таких таблиц в системе нет.
Но можно сравнить исходные параметры и конечный код — они идентичны, за исключением FROM из несуществующей таблицы (что при наличии модели tSkladDetNSLink будет заменено на FROM `modx_tsklad_detail_naryad_smena_link` AS `tSkladDetNSLink`) и экранирования сортировки (которой xPDO закрывает старую уязвимость).
Так что, кому уж прям очень нужны подзапросы в pdoTools — они уже там есть, с самого начала.
А если серьёзно, то ты пишешь очень сложный запрос, который не понадобится 99% пользователей pdoTools, а может и вообще MODX.
Он не станет менее сложным, если засунуть его в массив Fenom, никто ничего от этого не выиграет.
Усилия по добавлению этого функционала не просто ничего не стоят, они отрицательные не длинной дистанции, потому что нужно будет отвечать на вопросы по конвертации этих твоих вложенных массивов в SQL.
Периодически будут находиться люди, пытающиеся наворотить какую-нибудь фигню с этими параметрами. Как сейчас это делают с долбаным tvFilters.
Рейтинг этой заметки на данный момент составляет 0 при 34 комментариях, что уже намекает на её полезность.
Я этот PR гарантированно не приму, удачи в развитии своих дополнений.
А, кстати, тогда зачем вообще запросы описывать массивом феном? Можно же вообще писать чисто SQL.
XPDO это типа ORM. В нем получил объект и сразу можно что-то записать в базу. В pdoTools только чисто вывод.
Мне просто удобнее сам синтаксис pdoTools писать. И, так как запрос массив, есть возможность на лету его поменять. Приготовил массив запроса, а потом where добавляешь или удаляешь когда надо. На чисто sql менять where жуть. Код 5 лет назад :-). Ни pdoTools ни strftime еще не знал.
Тоже для XPDO и pdoTools
Явно проще. Особенно когда фильтр больше на параметров 6.
А вот пример уже с феном.
Так что запрос в массиве штука полезная.
А вот подзапросов в массиве у меня не было. Поиграюсь, посмотрю, что можно с ними сделать. Хотя, конечно, их на каждом шагу внедрять не стоит.
Это аргумент. Отвечать на вопросы кучи начинающих прогеров не самая приятная перспектива. Но тормозить из-за этого компоненты или проекты?? Это раз. И два. Отвечать имеет смысл, если развивать свою команду. С которой можно делать очень большие проекты. Такие как linux, например. Думаю сеньор не предел развития программиста. Можно как-бы основать свою школу и стать что-то вроде академика.
Будут явно. Люди пытаются решить свои задачи. Изучаем их задачи и пишем код, чтобы у них был инструмент для их задач :-). Прикалываюсь, если что :-). Но в каждой шутке доля шутки…
Резюме.
Ну как хотите. Я то надеялся, что вот крутая фишка пользуйтесь. Но, возможно, это и не так круто как мне кажется. Подзапросы, когда они мне понадобятся буду писать в своей версии синтаксиса pdoTools. Просто потому, что мне так удобнее. Сейчас, практические преимущества этой версии не понятны :-(.
PS. Сюда $fields массивом иногда приходят.
В итоге запрос выглядит так:
Где $fields массивом становиться не нашел. Просто implode сделал. Может разберетесь?
Магистр кода 99 уровня
Ну нахер. Штопать таки дыры, искать в коде display и fonts. И ещё Бог знает чего.
(int) это понятно. Для даты strftime можно использовать. А остальное? string, decimal, float. Хотя тоже все понятно. Только писать такие преобразования во все сниппеты долго. Плагин или что-то такое посмотрю. Ну здесь на интранет хакеров лет 10 не предвидеться. А если и предвидятся, то взлом внутреннего сайта это уже мелочь.
Такие сложные запросы я выполню с помощью $modx->query
Сколько будет выполнятся такой вопрос, если сверху на него навесить абстракцию в виде pdoTools? Сорок лет?
После последней правки, подзапрос добавил плюс 7 мс к общему выполнению запроса. getChunk операция затратная. Целых 5 мс :-).
Для таких запросов проще временную таблицу сделать куда будут данные сливаться на бэкенде, и потом уже готовые данные забирать на фронте.
Такими запросами, только фронт напрягать.
Почему то всегда охота все в один запрос запихать, но по опыту еще больше времени тратишь на всякие такие выборки.
Еще как вариант делать несколько запросов и получать id которые уже потом идут where в виде product_id IN (тут список id из какой то таблицы)
На примере получения товаров:
Этот код будет делать выборку в десятки раз быстрее:
Чем
join — зло еще то))
И еще за актуальность временных таблиц следить. Причем разных нужных данных может быть много вариантов. Вроде кол-во перестановок пропорционально n! Если 2 таблицы по 5 колонок, то кол-во возможных выборок 10! = 3628800 вариантов :-).
Актуальность в одну минут, вообще не принципиально)))
IN — еще большее зло, если в нем указана целая простыня (тысячи или десятки тысяч) id.
Вот ради интереса копипастнул себе на один из проектов оба варианта и, как я и ожидал, второй существенно быстрее.
На проекте 29705 товаров.
Ну и я заменил getCollection на getCount, потому что получать 30к объектов — самоубийство, даже через более оптимальный getIterator.
Вариант с IN:
Вариант с join:
Но вариант с IN может оказаться действительно быстрее там, где небольшой перечень id, тут согласен.
Дело в количестве указанных id, их слишком много, поэтому join работает быстрее.
getCollection — дергает все поля как с site_content так и c ms2_products
Как он может быть быстрее даже с этого ракурса?
Обращение к msProduct?
Вариант с IN:
Вариант с join:
Сейчас разница уже не такая большая, но она все еще в пользу join'а.
А теперь тоже самое только к примеру с получением pagetitle и price)
Вот тут явно увидите разницу
я бы тут из-за удобства выбрал join, хоть он действительно будет немного медленнее
Вариант с IN:
Можно было еще сделать через ASSOC и array_column, но это медленнее, как мне показалось
Вариант с join:
Ноооооо если мы используем getCollection) То innerJoin не позволит сделать select!
Так что скорость ощутим упадет))
Кстати, твой код, исключает getCollection. О чем я писал когда говорил о IN.
Так что если по играть, с кодом, то явно увидишь разницу.
return $objectCount;
}
в $objectCount запишется 0
Приходилось встречаться что в итоге 0 это тоже true, скорей всего это в старом каком то php
по этому лучше так
Можно было прям сразу
Только, если ты не умеешь его готовить )) Молотком можно и гвозди забивать и шурупы.