Не зарегистрирован
Вход
Забыли пароль?
Регистрация
Подписаться
Сэкономьте время — перед вопросом на форуме узнайте, как найти ответ быстрее
По техническим проблемам необходимо обращаться в Консультационный центр

Поиск по форуму: 

Приглашаем в блог Amiro.CMS. Регулярные обзоры, опыт, решения, практикумы.

Форум  ->   Разработка плагинов, вопросы по API  ->  ЧПУ для фильтра

Раздел для разработчиков. Обсуждение создания плагинов, вопросы и пожелания по API Amiro.CMS

Добавлено: 28.01.17 11:45:40 #1



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

Запросил в тех поддержке как сделать чпу при фильтрации товаров допустим по производителю, дали такой ответ:

Потребуется доработка роутера в обработчике событии custom_on_system_start как это делается, например, в модуле http://www.amiro.ru/market/catalog/free/sokraschenie-ssylok-296
Простой пример работы с событием custom_on_system_start, реализующий ЧПУ для фильтра типа //site.addr/kat/param1/value1/param2/value2/... -

define('AMI_FIRE_ON_SYSTEM_START', TRUE);
AMI_Event::addHandler('custom_on_system_start', 'customStartHandler', AMI_Event::MOD_ANY);

function customStartHandler($name, array $aEvent, $handlerModId, $srcModId){
    if(strpos($_SERVER['REQUEST_URI'], '/kat/') === 0) {
        $parts = explode('/', $_SERVER['REQUEST_URI']);

        // prepare search query params
        $params = array(
            'pf' => 1,
            'flt_force_values' => 1,
            'action' => 'search',
            'search_subcats' => 1
        );
        for($i = 0; $i < count($parts) - 1; $i++) {
            if(preg_match('/cst([0-9]+)/ui', $parts[$i], $matches)) {
                  $params['ext_custom_' . $matches[1]] = $parts[$i + 1];
            }
        }

        // build query string
        $_SERVER['QUERY_STRING'] = $GLOBALS['ROOT_PATH_WWW'] . '/katalog?';
        foreach($params as $name => $value) {
            $_SERVER['QUERY_STRING'] .= '&' . $name . '=' . $value;
        }

        // force to use QUERY_STRING instead of REQUEST_URI
        unset($_SERVER['REQUEST_URI']);
    }
    return $aEvent;
}

И дополнительно изменить ссылки на сортировку, и параметры robots на сгенерированной странице перед выдачей - 

AMI_Event::addHandler('v5_on_apply_data', 'cstFinalizeLinks', AMI_Event::MOD_ANY);
function cstFinalizeLinks($name, array $aEvent, $handlerModId, $srcModId) {
    if($aEvent['type'] != 'page_finalize') {
        return $aEvent;
    }
    // $aPageInfo = AMI_Registry::get('page'); // массив с информацией о странице
    $aEvent['aData'] = preg_replace('...', '...', $aEvent['aData']); // в $aEvent['aData'] сгенерированный системой код страницы перед выдачей
    return $aEvent;
}


вставляю этот код в /_local/common_functions.php или в /_local/front_functions.php у меня сайт "летит", отображает только "Работает на Amiro.CMS" на белом фоне и ничего больше, в чем может быть причина?



Добавлено: 01.02.17 14:59:25 #2



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

причину по которой ложился сайт нашли
preg_replace('...', '...', $aEvent['aData'])


подскажите как можно подменить url
http://business.amiro.ru/katalog?=&action=search&catid=0&ext_custom_13=Alex&flt_force_values=1

на сгенерированный допустим такой:
http://business.amiro.ru/katalog/Alex



Добавлено: 01.02.17 20:46:50 #3



Регистрация: 26.05.08
Сообщений: 984


Обратиться по имени

Регулярка вот:

/ext_custom_13=(\w*)/ui



Добавлено: 02.02.17 12:36:01 #4



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

Евгений Лапин, За регулярку спасибо, но что конкретно нужно заменять? может есть какой нибудь пример, ткните пожалуйста если есть. Через поиск ничего подходящего не нашел.



Добавлено: 02.02.17 18:51:03 #5



Регистрация: 26.05.08
Сообщений: 984


Обратиться по имени

Судя по примеру, который дала СТП, заменять нужно в элементе суперглобального массива $_SERVER['QUERY_STRING']



Добавлено: 05.02.17 09:37:41 #6



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

Евгений Лапин, Здравствуйте! Пытался проверить что храниться в $_SERVER['QUERY_STRING'] с помощью phpinfo(); получается там пусто:

_SERVER["QUERY_STRING"]	no value
_SERVER["REQUEST_URI"]	/katalog/namekategory1?&catid=90001&ext_custom_13=name-proizvoditel&pf=1&flt_force_values=1&action=search&search_subcats=1


или через
parse_str($_SERVER['QUERY_STRING'], $result);
print_r($result);
тоже пустой массив

UPD:
переделал первую часть так:

function customStartHandler($name, array $aEvent, $handlerModId, $srcModId){
    //if(strpos($_SERVER['REQUEST_URI'], 'katalog?&') === 0) {
	if(strpos($_SERVER['REQUEST_URI'], '/katalog') === 0) {
        $parts = explode('/', $_SERVER['REQUEST_URI']);

        // prepare search query params
        $params = array(
            'pf' => 1,
            'flt_force_values' => 1,
            'action' => 'search',
            'search_subcats' => 1
        );
        for($i = 0; $i < count($parts) - 1; $i++) {
            if(preg_match('/ext_custom_13=(\w*)/ui', $parts[$i], $matches)) {
                  $params['ext_custom_' . $matches[1]] = $parts[$i + 1];
            }
        }

        // build query string
        $_SERVER['QUERY_STRING'] = $GLOBALS['ROOT_PATH_WWW'] . 'katalog';
        foreach($params as $name => $value) {
            $_SERVER['QUERY_STRING'] .= '&' . $name . '=' . $value;
        }

        // force to use QUERY_STRING instead of REQUEST_URI
        unset($_SERVER['REQUEST_URI']);
    }
	
    return $aEvent;
}


теперь вроде отрабатывает
//$_SERVER['QUERY_STRING']
Array ( [0] => [1] => katalog [2] => namekategory1?&ext_custom_13=name-proizvoditel&pf=1&flt_force_values=1&action=search&search_subcats=1 )
почему тут первый элемент пустой?

//$_SERVER['REQUEST_URI']
Array ( )

UPD:
переделал так:

define('AMI_FIRE_ON_SYSTEM_START', TRUE);
AMI_Event::addHandler('custom_on_system_start', 'customStartHandler', AMI_Event::MOD_ANY);

function customStartHandler($name, array $aEvent, $handlerModId, $srcModId){
    //if(strpos($_SERVER['REQUEST_URI'], 'katalog?&') === 0) {
	if(strpos($_SERVER['REQUEST_URI'], '/katalog') === 0) {
        $parts = explode('/', $_SERVER['REQUEST_URI']);

        // prepare search query params
        $params = array(
            'pf' => 1,
            'flt_force_values' => 1,
            'action' => 'search',
            'search_subcats' => 1
        );
        for($i = 0; $i < count($parts); $i++) {
            if(preg_match('/ext_custom_([0-9]+)/ui', $parts[$i], $matches)) {
                  $params['ext_custom_' . $matches[1]] = $parts[$i];
            }
        }

        // build query string
        $_SERVER['QUERY_STRING'] = $GLOBALS['ROOT_PATH_WWW'] . 'katalog';
        foreach($params as $name => $value) {
            $_SERVER['QUERY_STRING'] .= '&' . $name . '=' . $value;
        }

        // force to use QUERY_STRING instead of REQUEST_URI
        unset($_SERVER['REQUEST_URI']);
    }
	
    return $aEvent;
}


получаю так:
$rttr = (string)$_SERVER['QUERY_STRING'];
echo $rttr;


вот это:

sitename.ru/katalog&pf=1&flt_force_values=1&action=search&search_subcats=1&ext_custom_13=namekategory1?&ext_custom_13=NAME-PROIZVODITEL&pf=1&flt_force_values=1&action=search&search_subcats=1

и всетаки непонятно как в адресной строке получить то что получится в $_SERVER['QUERY_STRING'] ???




Добавлено: 20.02.17 16:18:54 #7



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

При нажатии на кнопку найти формируется например такой URL

sitename.ru/katalog/namekategory?&ext_custom_13=NAME-PROIZVODITEL&pf=1&flt_force_values=1&action=search&search_subcats=1

как мне получить вместо него это: sitename.ru/ext_custom_13/NAME-PROIZVODITEL

делаю так:

      
$pgtyp = AMI::getResource('env/template_sys')->getGlobalVar('BODY_TYPE');
if($pgtyp == 'body_search'){  
        preg_match('/ext_custom_([0-9]+)/ui', $_SERVER['REQUEST_URI'], $matches);
        $maon = $matches[0]; 
 
        preg_match('/ext_custom_([0-9]+)=(.*?)&/', $_SERVER['REQUEST_URI'], $match);
        $matu = $match[1];
 
        $rru = (string)$maon.'/'.$matu;
 
        header('Location: '.$GLOBALS['ROOT_PATH_WWW'].''.$rru);
}


но это получается только со страницы поиска работает, и то не всегда

по прямой если зайти на sitename.ru/ext_custom_13/NAME-PROIZVODITEL то фильтр отрабатывает, с этим вроде разобрался, а вот именно чтоб из фильтра выдать немогу. .



Добавлено: 21.02.17 12:12:37 #8



Регистрация: 22.10.12
Сообщений: 73


Обратиться по имени

как мне получить вместо него это: sitename.ru/ext_custom_13/NAME-PROIZVODITEL

Например есть parse_url ( http://php.net/manual/ru/function.parse-url.php ), получить список параметров и перестроить нужным образом.

а вот именно чтоб из фильтра выдать немогу. .

Ссылка при отправке фильтра строится на клиенте, нужно переопределять локально функцию AMI.Form.Filter.submit.



Добавлено: 28.02.17 11:54:47 #9



Регистрация: 19.01.15
Сообщений: 102


Обратиться по имени

Dmitry Kornilov,
Получилось.
вставил функцию в верхний блок через менеджер сайта заменил там знаки ? и = на / и сделал проверку по полям для определения что искать

в общем вот:

<script>
$(document).ready(function(){
    if (!AMI.Form)
    AMI.Form = {};
AMI.Form.Filter = {
    search_method : "action", // name search method (for GET request)
    search_text_name : "search_text", // name of input with text from search line
    submit_script_name : "submit_url", // name of hidden input, its value is: host + default script name
    subcategories_flag_name : "search_subcats", // server logic: if (search_subcats==1) then use current category as top level category for search
    search_from_current_category : true, // by default search is working from current category. can be changed by setSearchMode() method
    category_id_name : 'catid', // name of catid parameter
    
    mode : "filter", // Default mode. Only current category (and may be its subcategories too) used. Can be changed to "search"
    
    /**
     * Checks and submit FilterForm
     *
     * Actually, submit will be cancelled, all form fields will be placed in uri
     * @SubmittedForm - form to be parsed and submitted
     * @offset - related to page. If undefined, offset will be dropped.
     */
    submit : function(SubmittedForm, offset)
    {
        var el, val;
        
        // Create the submit URL
        var submit_url = '';
        
        // Cycle over all form textfields, checkboxes, radios, etc.
        for ( var i = 0 ; i <= SubmittedForm.length - 1 ; i++ )
        {
            el = SubmittedForm.elements;
            elName = el.name;
            if (el.type == 'checkbox') // input type checkbox
            {
                if (el.checked)
                {
                    if ((fpos = el.name.indexOf("_flag_")) >= 0)
                    {
                        flagMapAdd(el.name.substr(0, fpos), parseInt(el.name.substr(fpos+6)), 0);
                    }
                    else if (el.value != '')
                    {
                        submit_url += '/'+elName+'/'+encodeURIComponent(el.value);
                    }
                    
                    // subcategories flag
                    if (elName == this.subcategories_flag_name)
                    {
                        this.subcategories_flag_string = '/' + elName + '/1';
                    }
                }
                else // unchecked
                {
                    if ((fpos = el.name.indexOf("_flag_")) >= 0) {
                        flagMapAdd(el.name.substr(0, fpos), parseInt(el.name.substr(fpos+6)), 1);
                    } else {
                        //if (el.name.indexOf("[]") <= 0) /* do not process array items */
                        // submit_url += '&'+elName+'=';
                    }
                }
            }
            if (el.type == 'select-one')
            {

                if ((fpos = el.name.indexOf("_flag")) >= 0)
                {
                    flagMapAdd(el.name.substr(0, fpos), parseInt(el.value), 0);
                }
                else if (el.value != '')
                {
                    submit_url += '/'+elName+'/'+encodeURIComponent(el.value);
                }
            }
            if (el.type == 'select-multiple')
            {
                fpos = el.name.indexOf("_flag");
                for (k = 0; k < el.length; k++) {
                    if (el.options[k].selected) {
                        if (fpos >= 0) {
                            flagMapAdd(el.name.substr(0, fpos), parseInt(el.options[k].value), 0);
                        } else {
                            submit_url += '/'+encodeURIComponent(elName)+'/'+encodeURIComponent(el.options[k].value);
                        }
                    }
                }
            }
            if (el.type == 'radio')
            {
                if (el.checked)
                {
                    if ((fpos = el.name.indexOf("_flag")) >= 0) {
                        flagMapAdd(el.name.substr(0, fpos), parseInt(el.value), 0);
                    } else {
                        submit_url += '/'+elName+'/'+encodeURIComponent(el.value);
                    }
                }
            }
            if ( el.type == 'text' || el.type == 'hidden' )
            {
                var preserve_category_id = !((!this.search_from_current_category) && (el.name == this.category_id_name));
                var this_isnt_reserved_name = (el.name != this.search_method && el.name != this.search_text_name && el.name != this.submit_script_name && el.name != 'offset');
                if ( this_isnt_reserved_name && preserve_category_id && el.value != '' ) // prevent duplicating special fields
                    submit_url += '/' + elName + '/' + encodeURIComponent(el.value);
                if (offset)
                    submit_url += '&offset=' + offset;
            }
        }
        
        submit_url += '/' + this.search_method + '/' + this.getSearchMethodName( SubmittedForm, this.search_method );
        
        if (typeof this.subcategories_flag_string != 'undefined')
            submit_url += this.subcategories_flag_string;

        for(i = 0; i < flagMaps.length; i++) {
            if(flagNames) {
                submit_url += '/'+flagNames+'/0x'+arrToHex(flagMaps);
            }
        }

        var search_text_value = this.getSearchText( SubmittedForm, this.search_text_name );
        
        if (search_text_value != '')
            submit_url += '/' + this.search_text_name + '/' + encodeURIComponent(search_text_value);
        //ПРОВЕРКА ПО ПОЛЯМ
        var lenec = submit_url.split("ext_custom_").length - 1,
        	leneca = submit_url.split("price_").length - 1,
        	shrt = submit_url.split("search_text").length - 1,
        	stur = '##www_root##';
        if (lenec == 1 && leneca == 0 && shrt == 0){ // для свойств
           var  splid = /ext_custom_([0-9]+)\/(.*?)\//.exec(submit_url)[0],
        	splid=splid.replace(/%20/g, '_');//заменить пробел на нижний прочерк
            submit_url = stur + splid; 
        }
        else if (leneca == 1 && lenec == 0 && shrt == 0){ // для цен
           var  splid = /price_(.*?)\/(.*?)\//.exec(submit_url)[0],
        	splid=splid.replace(/%20/g, '_');
            submit_url = stur + splid;  
        }
        else if (shrt == 1 && leneca == 0 && lenec == 0){ // для поиска
           var  splid =  /search_text\/(\w*)/ui.exec(submit_url)[0],
        	splid=splid.replace(/%20/g, '_');
            submit_url = stur + splid;  
        }
        else{
            
            var cusstu = stur.slice(0, -1);// обрезаем слеш в конце
            submit_url = cusstu + submit_url;

        }
       
        //submit_url = this.getScriptName(SubmittedForm) + '?' + submit_url;
        window.location.href = submit_url;
 		return false;

    },
    
    /**
     * Submit form and set to input with name "letter" value @letter
     */
    submitWithLetter : function(letter)
    {
        if (this.main_form_name)
        {
            var forms = document.forms;
            var i = 0;
            // Finding main filter form
            while ( i <= document.forms.length - 1 && document.forms.name != this.main_form_name )
            {
                i++;
            }
            // If we find main form and there is an input type hidden with name 'letter'
            if ( document.forms && document.forms.letter )
            {
                document.forms.letter.value = letter;
                this.submit( document.forms );
            }
        }
    },
    
    /**
     * @varName - name of form field should be looked (e.g. "action")
     * @returns name of action, i.e. search method name. Not connected with form attr "action"!
     */
    getSearchMethodName : function ( SubmittedForm, varName )
    {
        // only slow search method finding items in all subcategories (fast method include only first level of subcats)
        if (SubmittedForm.search_subcats && SubmittedForm.search_subcats.checked)
        {
            this.setSlowSearchMethod();
            return this.searchMethodName;
        }
        
        if ( this.searchMethodName )
            return this.searchMethodName;
        
        this.setSlowSearchMethod(); // Slow method by default - for Enter submit form in IE
        return this.searchMethodName;
    },
    
    /**
     * Extracts varName from SubmittedForm. Input type text has priority over type hidden. Next input has proiroty over previous.
     *
     * @SubmittedForm - form to be submitted
     * @returns - search text (text from search line of current or previous request)
     */
    getSearchText : function ( SubmittedForm, varName )
    {
        var searchText = '';
        var missHidden = false;
        
        for ( var i = 0 ; i <= SubmittedForm.length - 1 ; i++ )
        {
            if ( SubmittedForm.elements.type == 'text' && SubmittedForm.elements.name == varName )
            {
                missHidden = true;
                searchText = SubmittedForm.elements.value;
            }
            if ( SubmittedForm.elements.type == 'hidden' && SubmittedForm.elements.name == varName && SubmittedForm.elements.value != '' )
            {
                if ( !missHidden )
                    searchText = SubmittedForm.elements.value;
            }
        }
        
        return searchText;
    },
    
    /**
     * Set current search method
     */
    setSearchMethodName : function ( name )
    {
        this.searchMethodName = name;
    },
    
    /**
     * Set "rsrtme" (resort me) method as current.
     *
     * Method "rsrtme" finding items only in current category and first level subcategories.
     */
    setFastSearchMethod : function ()
    {
        this.setSearchMethodName( 'rsrtme' );
    },
    
    /**
     * Set "search" (resort me) method as current.
     *
     * Method "search" finding items in current category and all subcategories
     */
    setSlowSearchMethod : function ()
    {
        this.setSearchMethodName( 'search' );
    },
    
    /**
     * Get the submit script name (first part of get request, like action attr of form)
     *
     * There are two ways: 1. Current uri; 2. Default, top level category uri.
     */
    getScriptName : function (SubmittedForm)
    {
        for ( var i = 0 ; i <= SubmittedForm.length - 1 ; i++ )
        {
            if ( SubmittedForm.elements.name == this.submit_script_name )
                this.submit_script_value = SubmittedForm.elements.value;
        }
        
        var link_without_get_params = window.location.href.slice( 0, window.location.href.indexOf('\?123') );
        
        if ( link_without_get_params.indexOf(this.submit_script_value) == -1 || !this.search_from_current_category ) // if we are not in catalog or there is flag, indicating to search from top level category
            return this.submit_script_value;        
        else // we are somewhere in catalog and there is no need to serach from top level category
            return document.location.pathname;
    },
    
    /**
     * Setting search mode, when all catalog is used for search (top level category), and slow search method applied
     *
     * @search_from_current_category - bool flag. if true - search is working from current category, if false - from top level category
     */
    setSearchMode : function (search_from_current_category)
    {
        if (typeof search_from_current_category === "boolean")
            this.search_from_current_category = search_from_current_category;
        this.setSlowSearchMethod(); // Slow search method? for subcategories search
        this.subcategories_flag_string = '&' + this.subcategories_flag_name + '=1'; // it is needed for searching in not top level category (bad server logic)
        this.mode = 'search';
    }
}
});
</script>


и код для common_function.php который принимает то что отправил предыдущий скрипт:

define('AMI_FIRE_ON_SYSTEM_START', TRUE);
AMI_Event::addHandler('custom_on_system_start', 'customStartHandler', AMI_Event::MOD_ANY);

function customStartHandler($name, array $aEvent, $handlerModId, $srcModId){
    $aPageInfo = AMI_Registry::get('page'); 
	$stec = strpos($_SERVER['REQUEST_URI'], '/ext_custom_');
	$stpr = strpos($_SERVER['REQUEST_URI'], '/price_');
	$stser = strpos($_SERVER['REQUEST_URI'], '/search_');
	$pf = strpos($_SERVER['REQUEST_URI'], '/pf');
    if($stec === 0 || $stpr === 0 || $stser === 0 || $pf === 0) {// /kat/
        $parts = explode('/', $_SERVER['REQUEST_URI']);

        // prepare search query params
        $params = array(
            'pf' => 1,
            'flt_force_values' => 1,
            'action' => 'search',
            'search_subcats' => 1
        );
	// разбираем обратно, меняем нижнее подчеркивание на %20
        for($i = 0; $i < count($parts) - 1; $i++) {
            if(preg_match('/ext_custom_([0-9]+)/ui', $parts[$i], $matches)) {
				$par = str_replace('_', '%20', $parts[$i + 1]);
                $params['ext_custom_' . $matches[1]] = $par;
            }
			if(preg_match('/price_([A-z]+)/ui', $parts[$i], $matches)) {
				$par = str_replace('_', '%20', $parts[$i + 1]);
                $params['price_' . $matches[1]] = $par;	
            }
			if(preg_match('/search_([A-z]+)/ui', $parts[$i], $matches)) {
				$par = str_replace('_', '%20', $parts[$i + 1]);
                $params['search_' . $matches[1]] = $par;	
            }

        }

        // build query string
        $_SERVER['QUERY_STRING'] = $GLOBALS['ROOT_PATH_WWW'] . 'katalog?'; 
        foreach($params as $name => $value) {
            $_SERVER['QUERY_STRING'] .= '&' . $name . '=' . $value;
        }


	
		
		// force to use QUERY_STRING instead of REQUEST_URI
        unset($_SERVER['REQUEST_URI']);
    }


    return $aEvent;
}


самое главное это работает.

В будущем еще планирую транслитерацию прикрутить.

Если есть какие то замечания или предложения по оптимизации буду только рад.



Добавлено: 26.12.17 15:21:26 #10




Регистрация: 21.12.17
Сообщений: 1


Обратиться по имени

Спасибо за подсказку)



Лучшие гаджеты - https://upee.ru/


Создать новую тему

Всего тем: 6587
Всего сообщений: 27617
Всего зарегистрированных пользователей: 47790
Последний зарегистрированный пользователь: karimova