Фильтр опций в товаре с переходом по ссылке
Вывод всех параметров опций в товаре и переход на соседний товар в разделе при выборе опции.

Сниппет для получения данных опций из раздела, на основе Настроек опций в самом разделе.
<?php
if (empty($parent)){$parent = $modx->resource->get('parent');}
if (empty($id)){$id = $modx->resource->get('id');}
/* получаем настройки и названия опций от родителя-каталога */
$sql = $modx->query("SELECT catopt.* , mo.*
FROM {$modx->getTableName('msCategoryOption')} as catopt
inner JOIN {$modx->getTableName('msOption')} as mo
on mo.id = catopt.option_id
WHERE catopt.category_id = ". $parent." ORDER BY catopt.rank");
$options = $sql->fetchAll(PDO::FETCH_ASSOC);
$ids_opt = [];
foreach ($options as $option) {
$ids_opt[] = $option['id'];
}
/* получаем все значения id товаров в этом каталоге */
$sql = $modx->query("SELECT res.id, res.uri
FROM {$modx->getTableName('modResource')} as res
WHERE res.deleted = 0 AND res.published = 1 AND res.parent = ".$parent);
$resourses = $sql->fetchAll(PDO::FETCH_ASSOC);
$ids_res = [];
foreach ($resourses as $idr) {
$ids_res[] = $idr['id'];
}
if ($id > 0){
/* получение всех опций у текущего товара */
$sql = $modx->query("SELECT opt.key, opt.value
FROM {$modx->getTableName('msProductOption')} as opt
WHERE opt.product_id IN (".$id.") AND opt.value is not NULL AND opt.value not like 'undefined' GROUP BY opt.value ORDER BY opt.key ASC, floor(opt.value) ASC");
$res = $sql->fetchAll(PDO::FETCH_ASSOC);
$res_opt = [];
foreach ($res as $v){
$res_opt[$v['key']] = $v['value'];
}
}
/* получение списка опций всех товаров в каталоге */
$sql = $modx->query("SELECT opt.key, opt.value
FROM {$modx->getTableName('msProductOption')} as opt
WHERE opt.product_id IN (".implode($ids_res, ',').") AND opt.value is not NULL GROUP BY opt.value ORDER BY opt.key ASC, floor(opt.value) ASC");
$opt_values = $sql->fetchAll(PDO::FETCH_ASSOC);
$opt_value = [];
foreach ($opt_values as $opt_v) {
if($opt_v['value'] == $res_opt[$opt_v['key']]){
$opt_value[$opt_v['key']][] = ['value' => $opt_v['value'], 'checked' => 'checked'];
}else{
$opt_value[$opt_v['key']][] = ['value' => $opt_v['value']];
}
}
/* получаем зависимость параметров */
if (count($res_opt) > 1){
$subject_res = [];
$select = '';
$sql='';
foreach ($res_opt as $res_key => $res_val){
$select = " SELECT {$res_key}.`key`, {$res_key}.`value`";
$from = " FROM {$modx->getTableName('msProductOption')} as {$res_key}";
$join = '';
$and = '';
foreach ($options as $key_opt){
if ($key_opt['key'] !== $res_key){
$join .= " inner join {$modx->getTableName('msProductOption')} as {$key_opt['key']} on {$key_opt['key']}.product_id = {$res_key}.product_id AND {$key_opt['key']}.`key` like '{$key_opt['key']}'";
$and .= " AND {$key_opt['key']}.`value` like '{$res_opt[$key_opt['key']]}' ";
}
}
$where = " WHERE {$res_key}.product_id IN (".implode($ids_res, ',').")";
$sql .= $select . $from . $join . $where. $and .' UNION';
}
$sql = rtrim($sql, 'UNION');
$modx->log(1,print_r($sql,1));
$sql = $modx->query($sql);
$subject = $sql->fetchAll(PDO::FETCH_ASSOC);
//$modx->log(1,print_r($subject,1));
foreach ($subject as $v){
$subject_res[$v['key']][] = $v['value'];
$subject_res[$v['key']] = array_unique($subject_res[$v['key']]);
}
foreach ($opt_value as $opt_k => $opt_p) {
foreach($opt_p as $i => $opt_v){
$opt_value[$opt_k][$i]['disabled'] = 'disabled';
foreach($subject_res[$opt_k] as $sub_val){
if ($sub_val == $opt_v['value']){
$opt_value[$opt_k][$i]['disabled'] = '';
}
}
}
}
}
/* добавляем значения опций в опции */
foreach ($options as $key => $option){
$options[$key]['values'] = $opt_value[$option['key']];
}
/** @var pdoTools $pdoTools */
$pdoTools = $modx->getService('pdoTools');
/* выводим массив в чанк */
$output = '';
if ($tpl == ''){
echo '<pre>';
print_r($options);
echo '</pre>';
}else{
$output .= $pdoTools->getChunk($tpl, ['options'=>$options, 'res_option'=>$res_opt, 'subject'=>$subject_res ]);
}
return $output;
Чанк вывода опций с указанием опций самого товара и доступных вариаций, и обработки результатов выбора.
{*$options|print}
{$res_option|print*}
{*$subject|print*}
{if $options|len > 0}
{foreach $options as $opt}
<fieldset id="{$opt.key}" class="product-filtrs">
<h4 class="pb-1">{$opt.caption}</h4>
<div class="row-flex pb-2">
{foreach $opt.values as $k => $param}
{if $param['value']?}
<input type="radio" value="{$param['value']}" name="{$opt.key}" id="{$opt.key~$k}" {$param['checked']} {$param['disabled']} class="radio-option">
<label for="{$opt.key~$k}" class="radio-label">{$param['value']}</label>
{/if}
{/foreach}
</div>
</fieldset>
{/foreach}
<script>
$(document).on('change', '.radio-option', function() {
let query = { };
let tvfields = { };
query['parent'] = {$_modx->resource.parent};
$('.radio-option:checked').each(function(index, val){
tvfields[$(val).attr('name')] = $(val).val();
});
query['tvfields'] = tvfields;
$.ajax({
type: "POST",
url:'/assets/components/ajax/resource.php',
data:{ action:'gethref', query: JSON.stringify(query)}
}).done(function(response){
if (response) {
document.location.href = response;
};
});
});
</script>
{/if}
Получение ссылки на товар на основе переданных параметров через ajax
<?php
define('MODX_API_MODE', true);
// Если запрос не AJAX или не передано действие, выходим
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || empty($_REQUEST['action'])) {exit('error');}
require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/index.php';
$modx->getService('error', 'error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');
$modx->error->message = null;
$action = $_REQUEST['action'];
$data = false;
switch ($action) {
case 'gethref':
$query = json_decode($_REQUEST['query']);
$TVfields = $query->tvfields;
$parent = $query->parent;
$select = "SELECT content.`id`, content.uri FROM {$modx->getTableName('modResource')} as content";
foreach ($TVfields as $key=>$value){
$select .= " inner join {$modx->getTableName('msProductOption')} as $key on $key.product_id = content.id AND $key.`key` = '$key' AND $key.`value` like '%".$value."%'";
}
$select .= " WHERE content.parent = " . $parent;
$sql = $modx->query($select);
if ($rezult = $sql->fetchAll(PDO::FETCH_ASSOC)){
//$modx->log(1, print_r($TVfields,1));
$data = $rezult['0']['uri'];
}
}
@session_write_close();
exit($data);
Комментарии ()