Александр Мельник

Александр Мельник

С нами с 02 сентября 2016; Место в рейтинге пользователей: #64
Александр Мельник
03 мая 2020, 21:28
0
массивом передавать нельзя. по крайней мере php масивом. пробовал разные варианты.
сниппет ожидает только json
потому что первой же строкой в msproducts вызывается функция декодирования json
$filters = json_decode($scriptProperties['optionFilters'], true);

можно передавать
'optionFilters' => json_encode(['height:=' => 500]),
но суть не меняется. только пытаешься передать в условии OR, получаешь ошибку синтаксиса mysql
Александр Мельник
03 мая 2020, 21:13
0
Теперь вызов
$products=$modx->runSnippet('msProducts',[
    'parents'=>2,
    'limit'=>100,
    'showLog'=>1,
    'optionFilters'=>'{"height:=":"200","OR:height:=":"900"}'   
]);
Дает результаты и лог без ошибок.
0.0001228: pdoTools loaded.
0.0125182: Conditions prepared
0.0001228: xPDO query object created
0.0003409: leftJoined msProductData as Data
0.0002599: leftJoined msVendor as Vendor
0.0007038: leftJoined msProductOption as height
0.0002830: leftJoined msProductOption as OR:height
0.0000050: Grouped by msProduct.id
0.0001090: Added selection of msProduct: `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`
0.0000601: Added selection of msProductData: `article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`
0.0000439: Added selection of msVendor: `name` AS `vendor.name`, `resource` AS `vendor.resource`, `country` AS `vendor.country`, `logo` AS `vendor.logo`, `address` AS `vendor.address`, `phone` AS `vendor.phone`, `fax` AS `vendor.fax`, `email` AS `vendor.email`, `description` AS `vendor.description`, `properties` AS `vendor.properties`
0.0120971: Processed additional conditions
0.0125079: Added where condition: class_key=msProduct, height.value:==200, OR:height.value:==900, msProduct.parent:IN(2,3,4,5), msProduct.published=1, msProduct.deleted=0
0.0002041: Sorted by msProduct.id, ASC
0.0000041: Limited to 100, offset 0
0.0006971: SQL prepared "SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`properties`, `Data`.`article`, `Data`.`price`, `Data`.`old_price`, `Data`.`weight`, `Data`.`image`, `Data`.`thumb`, `Data`.`vendor`, `Data`.`made_in`, `Data`.`new`, `Data`.`popular`, `Data`.`favorite`, `Data`.`tags`, `Data`.`color`, `Data`.`size`, `Data`.`source`, `Vendor`.`name` AS `vendor.name`, `Vendor`.`resource` AS `vendor.resource`, `Vendor`.`country` AS `vendor.country`, `Vendor`.`logo` AS `vendor.logo`, `Vendor`.`address` AS `vendor.address`, `Vendor`.`phone` AS `vendor.phone`, `Vendor`.`fax` AS `vendor.fax`, `Vendor`.`email` AS `vendor.email`, `Vendor`.`description` AS `vendor.description`, `Vendor`.`properties` AS `vendor.properties` FROM `modx_site_content` AS `msProduct` LEFT JOIN `modx_ms2_products` `Data` ON `msProduct`.`id` =  `Data`.`id` LEFT JOIN `modx_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `modx_ms2_product_options` `height` ON `height`.product_id = Data.id AND `height`.key = 'height' LEFT JOIN `modx_ms2_product_options` `OR:height` ON `OR:height`.product_id = Data.id AND `OR:height`.key = 'OR:height' WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `height`.`value` = '200' OR `height`.`value` = '900' AND `msProduct`.`parent` IN (2,3,4,5) AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 )  GROUP BY msProduct.id ORDER BY msProduct.id ASC LIMIT 100 "
0.0026391: SQL executed
0.0000298: Rows fetched
0.0000670: Returning raw data
0.0011890: Checked the active modifiers
0.0076141: Loaded "modChunk" with name "tpl.msProducts.row"
0.0296071: Compiled Fenom chunk with name "modchunk/2"
0.0068347: Time to load products options
0.0851350: Total time
4 194 304: Memory usage
Александр Мельник
03 мая 2020, 21:08
0
Ну к сожалению, без модификации исходного сниппета решить вопрос не удалось (и как только у стольких людей все работало, вот умеют же люди).
Переписал логику регулярных выражений в msProducts, врядли это самое изящное решение, но пока лучше не нашел, разве что уж использовать очень сложные конструкции регулярных выражений — просмотр вперед и назад.
// Add filters by options
$joinedOptions = array();
if (!empty($scriptProperties['optionFilters'])) {
    $filters = json_decode($scriptProperties['optionFilters'], true);
    foreach ($filters as $key => $value) {
        $option = preg_replace('#\:.*#', '', $key);
// начало вставки
        $sql=['OR','AND','LIKE'];
        if (in_array($option,$sql)){
            $option = preg_replace('#\:=#', '', $key);
        }
// конец вставки
        $key = str_replace($option, $option . '.value', $key);
        if (!in_array($option, $joinedOptions)) {
            $leftJoin[$option] = array(
                'class' => 'msProductOption',
                'on' => "`{$option}`.product_id = Data.id AND `{$option}`.key = '{$option}'",
            );
            $joinedOptions[] = $option;
            $where[$key] = $value;
        }
    }
}
теперь OR, AND, LIKE вроде бы разбираются корректно и работаю.
Немного жаль, что моя затея построить функционал на сниппете minishop2 прогорела, теперь нужно будет использовать свой модифицированный сниппет, а значит лишиться обновлений.

Или же я все-таки неправильно изначально составляю условия для optionFilters?
Александр Мельник
03 мая 2020, 20:10
0
подсказки при вводе — эти задачи решаются на js а не при помощи mSearch2. Поищите в сети, решений масса.
Ну а по поводу отображения заведений и описания, все как я выше написал.
Получаете на id ресурса его поля — поле content и ваш migx и выводите на страницу.
Александр Мельник
03 мая 2020, 19:57
0
передавайте в форме для самой уж простоты еще два скрытых поля — два идентификатора ресурса аэропортов.
В том месте где вы обрабатываете эту форму ловите идентификатор и по нему получаете все данные этого ресурса на fenom

{set $id} - каким то образом полученный идентифиатор
{set $objects = $id|resource:"migx_name"|fromJSON}
{foreach $objects as $object}
<p>{$object.name}</p>
<p>{$object.type}</p>
<p>{$object.worktime}</p>
{/foreach}
Александр Мельник
03 мая 2020, 19:50
0
то есть речь не о какой-то карте полета и пересадок?
Простите мне пятый десяток, но я никогда не летал на самолете, так что мало в этом понимаю.
А зачем тогда вводить два аэропорта? Вылета и прилета?
Александр Мельник
03 мая 2020, 19:38
0
не совсем понятно. Что должен увидеть пользователь введя два аэропорта? города? Какие? по какому принципу?
Вы пишите — у меня есть города. Что значит есть? Это ресурсы? Это ТВ какого то ресурса? Это MIGX? Это своя таблица в базе?
Учитывая что информации очень мало то и совет можно дать только общий.
Есть форма с двумя инпутами, обрабатывается ее событие change на js. Берите данные из полей, делайте запрос на отдельный php файл.
В файле получаете объект modx
docs.modx.com/current/ru/extending-modx/modx-class/loading-externally
Создаете там запрос, составив условие из полученных в этом файле данных из формы
как нибудь вот так
docs.modx.com/current/en/extending-modx/xpdo/class-reference/xpdoquery/xpdoquery.where
Что уж тут вы будете получать, зависит от того чем у вас являются «города» в программе.
Возвращаете результат, который получает ваш js и вставляет его на страницу.
Александр Мельник
03 мая 2020, 19:21
0
куда привели меня изыскания.
Смотрю код сниппета msProducts.
// Add filters by options
$joinedOptions = array();
if (!empty($scriptProperties['optionFilters'])) {
    $filters = json_decode($scriptProperties['optionFilters'], true);
    foreach ($filters as $key => $value) {
        $option = preg_replace('#\:.*#', '', $key);
        $key = str_replace($option, $option . '.value', $key);
        if (!in_array($option, $joinedOptions)) {
            $leftJoin[$option] = array(
                'class' => 'msProductOption',
                'on' => "`{$option}`.product_id = Data.id AND `{$option}`.key = '{$option}'",
            );
            $joinedOptions[] = $option;
            $where[$key] = $value;
        }
    }
}
Взял себе отдельно этот кусочек кода, скармливаю ему строку json
$scriptProperties['optionFilters']= '{"height:=":"200","OR:height:=":"900"}';
 $filters = json_decode($scriptProperties['optionFilters'], true);
    foreach ($filters as $key => $value) {
        $option = preg_replace('#\:.*#', '', $key);
                $key = str_replace($option, $option . '.value', $key);
        echo $key;
        
    }
получаю теже некорректные (на мой взгляд) данные, что и в логе
height.value:=OR.value:height:=
тоесть регулярные выражения разбирают строку не совсем верно. Однако у меня есть старая версия minishop, посмотрел там этот сниппет и код там идентичен и люди говорят что синтаксис
'optionFilters'=>'{"height:=":"200","OR:height:=":"900"}'
верен.
Как же так… Как правильно составить условие для optionFilters чтобы использовать OR AND LIKE?
Александр Мельник
03 мая 2020, 17:20
+1
заманчиво) Но два нюанса — во-первых интересно самому, если уж не выйдет, то буду думать о покупке. Ну и самое главное, сайт, куда данный функционал необходим, сильно модифицирован, там переписаны ядра как модекса, так и минишопа и 95 процентов чужих компонентов там не работают.
Александр Мельник
01 мая 2020, 21:13
0
Если что, системные настройки кеширования, а заодно и pdoTools выглядят так.

Александр Мельник
01 мая 2020, 21:03
0
Кстати не работает.
Добавление! приводит к тому, что сниппет совсем не запускается.
Тоесть делаю в getFilters.php
просто return сроки и если поставить знак! то на странице не выводится ничего, если убрать — то выводится но опять же таки — наглухо закешировано.
Александр Мельник
30 апреля 2020, 22:13
0
Да Александр, вы правы. Просто чтобы реализовать мою идею, нужно… Ну не знаю. у меня около 40 проектов. Теоретически нужно 40 серверов и я как самоучка php-програмист не готов обслуживать и нести ответственность за нормальное функционирование 40 серверов. Хотя я сейчас и администрирую 5 серверов на debian. Нужно нанимать как минимум одного dev-ops а, а он стоит в месяц как моя зарплата за полгода. Замкнутый круг.
Александр Мельник
30 апреля 2020, 21:14
0
Спасибо. Тут понимаете — я лишь программист в компании. я не могу сильно влиять на политику. Стараюсь, но не могу. И моя директорша как женщина, всем верит, всех любит. Какие там предоплаты) Нам если и платят то через 4 месяца. И те кто нас кинули сегодня — 2 года с нами бок о бок. Мы им бесплатно сделали сайт (ну они же такие няшки, зачем с них деньги брать). ох…
Александр Мельник
30 апреля 2020, 21:11
0
Вы правы, все отслеживается. Но все зависит и от уровня спеца.
Я на 5-ти сайтах, которые нас «кинули» закрыл через роботс индексацию. И уже год никто этого не обнаружил.
Александр Мельник
30 апреля 2020, 18:35
0
тю блин)) а я ставил! перед биндингом
{'!@FILE snippets/getFilters.php'|snippet}
спасибо! сейчас опробую
Александр Мельник
21 апреля 2020, 09:45
+1
Мой ответ тоже далек от профессионального.
Но наверное самое главное, это событие на которое срабатывает плагин.
Если это вообще момент инициализации modx, а placeholder у вас выставляется где то на странице, например вы результат работы какого-то снитппета выдаете в placeholder, то в этом плагине он просто еще не существует.
Но если на момент запуска плагина placeholder уже выставлен, то вы я думаю, сможете его получить через $modx->getPlaceholder('name');
Александр Мельник
21 апреля 2020, 08:57
0
спасибо, но я ориентировался на то что написано в документации. там написано
COPY the file **_build/build.config.sample.php** to **_build/build.config.php** and EDIT the properties to point at a valid database with proper credentials
тоесть прямое указание не только скопировать, но и отредактировать. В следующий раз как вы говорите.
Александр Мельник
20 апреля 2020, 23:13
0
как-то страненько это.
docs.modx.com/current/en/getting-started/installation/git
Получается при клонировании modx с репозитория, нужно затем идти и в директории _build вносить данные о подключении к базе в нескольких файлах, потом запускать transport.core.php и после этого только запускать setup
Причем при установке все равно запрашивает данные к базе, что как минимум некрасиво.
А некоторые настройки не совсем для меня однозначны.
К примеру
/* mysql */
$properties['mysql_string_dsn_test']= 'mysql:host=localhost;dbname=admin_default;charset=utf8';
$properties['mysql_string_dsn_nodb']= 'mysql:host=localhost;charset=utf8';
$properties['mysql_string_dsn_error']= 'mysql:host= localhost;dbname=admin_default';
что нужно вписать в dsn_test? dsn_nodb? dsn_error?
Александр Мельник
20 апреля 2020, 22:46
0
ааа. тут еще какой-то build запускать нужно…