все просто

Фильтр опций в товаре с переходом по ссылке

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

Сниппет для получения данных опций из раздела, на основе Настроек опций в самом разделе.

<?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);

Комментарии ()