Доброго всем времени суток!
Есть проблема, я описывал ее здесь Проблема активного меню с custom_rewrite
Вкратце:
создаем в меню пункт Вход, ставим тип "ссылка", сама ссылка вот такая /login.
Теперь у нас по клику по пункту меню Вход — можно зайти на сайт.
Кликаем по ней...
Но пункт меню ВХОД не стал активным!
Налицо ошибка в разборе меню, т.е. ссылки вида /login, /passremind b прочие не обрабатываются!
Вы скажете да зачем нам это нужно, у нас эти ссылки висят отдельно. Да, на самом деле, смысла вносить изменения ради этих ссылок нет никакого.
Смысл есть, если мы будем использовать custom_rewrite для своихнизменных важных целей. Например, сделать так, чтобы урл контента в каком-либо компоненте был не пятнадцать слов а два
Итак поехали.
сегодня правим файл cms.php
добавляем в начале файла строку
там закешируем правила rewrite
берем функцию loadMenuStruct (загрузка меню в память)
меняем цикл
на
это мы посчитали "настоящую" ссылку в меню
добавляем новую функцию -
А теперь в функции menuID() меняем цикл foreach
на
теперь меню работает правильно
делалось под 1.8 для 1.9 думаю будет аналогично
решение не претендует на красоту, но общая идея понятна
а по поводу "зачем все это нужно" я расскажу в следующих постах
Есть проблема, я описывал ее здесь Проблема активного меню с custom_rewrite
Вкратце:
создаем в меню пункт Вход, ставим тип "ссылка", сама ссылка вот такая /login.
Теперь у нас по клику по пункту меню Вход — можно зайти на сайт.
Кликаем по ней...
Но пункт меню ВХОД не стал активным!
Налицо ошибка в разборе меню, т.е. ссылки вида /login, /passremind b прочие не обрабатываются!
Вы скажете да зачем нам это нужно, у нас эти ссылки висят отдельно. Да, на самом деле, смысла вносить изменения ради этих ссылок нет никакого.
Смысл есть, если мы будем использовать custom_rewrite для своих
Итак поехали.
сегодня правим файл cms.php
добавляем в начале файла строку
private $rules;
берем функцию loadMenuStruct (загрузка меню в память)
меняем цикл
while ($item = $inDB->fetch_assoc($result)){ $this->menu_struct[$item['id']] = $item; }
while ($item = $inDB->fetch_assoc($result)){ $this->menu_struct[$item['id']] = $item; $realink='/'.$this->detectorMenuURI($item['link']); $this->menu_struct[$item['id']]['realink'] = $realink; }
добавляем новую функцию -
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private function detectorMenuURI($muri){ $uri = $muri; if (!$this->rules) { //подключаем список rewrite-правил $this->includeFile('url_rewrite.php'); //получаем правила $rules = rewrite_rules(); } } //подключаем список пользовательских rewrite-правил $this->includeFile('custom_rewrite.php'); //добавляем к полученным ранее правилам пользовательские } } if ($rules){ $this->rules=$rules;} } else { $rules=$this->rules; } $found = false; if ($rules){ //перебираем правила foreach($rules as $rule_id=>$rule) { //небольшая валидация правила if (!$rule['source'] || !$rule['target'] || !$rule['action']) { continue; } //проверяем совпадение выражения source с текущим uri //перебираем совпавшие сегменты и добавляем их в target //чтобы сохранить параметры из $uri в новом адресе foreach($matches as $key=>$value){ if (!$key) { continue; } } } //действие по-умолчанию: rewrite if (!$rule['action']) { $rule['action'] = 'rewrite'; } //выполняем действие switch($rule['action']){ case 'rewrite' : $uri = $rule['target']; $found = true; break; case 'redirect' : $this->redirect($rule['target']); break; case 'redirect-301' : $this->redirect($rule['target'], '301'); break; case 'alias' : $this->includeFile($rule['target']); $this->halt();break; } } if ($found) { break; } } } return $uri; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
foreach($menu as $item){ if (!$item['link']) { continue; } //полное совпадение ссылки и адреса? if ($uri == $item['link']){ $menuid = $item['id']; $is_strict = true; //полное совпадение break; } //частичное совпадение ссылки и адреса (по началу строки)? if ($uri_first_part == $item['link']){ $menuid = $item['id']; break; } }
foreach($menu as $item){ if (!$item['link']) { continue; } //полное совпадение ссылки и адреса? if ($uri == $item['link']){ $menuid = $item['id']; $is_strict = true; //полное совпадение break; } //////////////// Определяем правильную ссылку для пункта меню if ($uri == $item['realink']){ $menuid = $item['id']; $is_strict = true; //полное совпадение break; } ///////////////////////////////////////////////////////////////////////////// //частичное совпадение ссылки и адреса (по началу строки)? if ($uri_first_part == $item['link']){ $menuid = $item['id']; break; } //////////////// Определяем правильную ссылку для пункта меню ///////////// //частичное совпадение ссылки и адреса (по началу строки)? if ($uri_first_part == $item['realink']){ $menuid = $item['id']; break; } ////////////////////////////////////////////////////////////////////////////// }
делалось под 1.8 для 1.9 думаю будет аналогично
решение не претендует на красоту, но общая идея понятна
а по поводу "зачем все это нужно" я расскажу в следующих постах

не понял про что это=)
http://сайт.ру/категория1/категория2/категория3/.../объект.html
а просто
http://сайт.ру/категория/объект.html вне зависимости от вложенности
это просто пример, через custom_rewrite много интересного сделать можно
После пункта "добавляем новую функцию"
Перестает вообще открываться сайт, происходит редирект - http://сайт.ру/сайт.ру/
Есть, правда, вероятность, что версию неполноценную выкачал (критерий был - utf-8). Кто-нить, дайте сцыль на .htaccess правильный? А то у меня такое впечатление, что в транках он левый.
функция detectorMenuURI() - на самом деле это просто подправленная копия detectURI - сделано для ускорения работы
можно использовать оригинальный detectURI - но тогда при каждом клике будет пересчитываться список uri
соотв-но при изменении списка в custom_rewrite нужно как-то сбрасывать закэшированное значение
private function detectorMenuURI($muri){ $uri = $muri; $uri = ltrim($uri, '/'); $rules = array(); $folder = rtrim($uri, '/'); if (strstr($uri, "?") && !preg_match('/^admin\/(.*)/i', $uri) && !strstr($uri, 'go/url=')){ $query_str = substr($uri, strpos($uri, "?")+1); $uri = substr($uri, 0, strpos($uri, "?")); parse_str($query_str, $temp_request); $_REQUEST = array_merge($_REQUEST, $temp_request); } if (in_array($folder, array('admin', 'install', 'migrate', 'index.php'))) { return; } //специальный хак для поиска по сайту, для совместимости со старыми шаблонами if (strstr($_SERVER['QUERY_STRING'], 'view=search')){ $uri = 'search'; } if (!$this->rules) { if(file_exists(PATH.'/url_rewrite.php')) { //подключаем список rewrite-правил self::includeFile('url_rewrite.php'); if(function_exists('rewrite_rules')){ //получаем правила $rules = rewrite_rules(); } } if(file_exists(PATH.'/custom_rewrite.php')) { //подключаем список пользовательских rewrite-правил self::includeFile('custom_rewrite.php'); if(function_exists('custom_rewrite_rules')){ //добавляем к полученным ранее правилам пользовательские $rules = array_merge($rules, custom_rewrite_rules()); } } if ($rules){ $this->rules=$rules;} } else { $rules=$this->rules; } $found = false; if ($rules){ //перебираем правила foreach($rules as $rule_id=>$rule) { //небольшая валидация правила if (!$rule['source'] || !$rule['target'] || !$rule['action']) { continue; } //проверяем совпадение выражения source с текущим uri if (preg_match($rule['source'], $uri, $matches)){ //перебираем совпавшие сегменты и добавляем их в target //чтобы сохранить параметры из $uri в новом адресе foreach($matches as $key=>$value){ if (!$key) { continue; } if (strstr($rule['target'], '{'.$key.'}')){ $rule['target'] = str_replace('{'.$key.'}', $value, $rule['target']); } } //действие по-умолчанию: rewrite if (!$rule['action']) { $rule['action'] = 'rewrite'; } //выполняем действие switch($rule['action']){ case 'rewrite' : $uri = $rule['target']; $found = true; break; case 'redirect' : $this->redirect($rule['target']); break; case 'redirect-301' : $this->redirect($rule['target'], '301'); break; case 'alias' : self::includeFile($rule['target']); $this->halt();break; } } if ($found) { break; } } } return $uri; }public function menuId(){ //если menu_id был определен ранее, то вернем и выйдем if ($this->menu_id) { return $this->menu_id; } $view = self::request('view', 'str', ''); if ($this->is_content){ $uri = substr($this->uri, strlen('content/')); } else { $uri = $this->uri; } $uri = '/'.$uri; //флаг, показывающий было совпадение URI и ссылки пунта меню //полным или частичным $is_strict = false; //главная страница? $menuid = ($uri == '/' ? 1 : 0); if ($menuid == 1) { $this->is_menu_id_strict = 1; return $menuid; } //перевернем массив меню чтобы перебирать от последнего пункта к первому $menu = array_reverse($this->menu_struct); //перебираем меню в поисках текущего пункта foreach($menu as $item){ if (!$item['link']) { continue; } // uri с учетом имени хоста $full_uri = HOST . $uri; //полное совпадение ссылки и адреса? if ($uri == $item['link'] || $full_uri == $item['link']){ $menuid = $item['id']; $is_strict = true; //полное совпадение break; } //////////////// Определяем правильную ссылку для пункта меню if ($uri == $item['realink']){ $menuid = $item['id']; $is_strict = true; //полное совпадение break; } //частичное совпадение ссылки и адреса (по началу строки)? $uri_first_part = substr($uri, 0, strlen($item['link'])); if ($uri_first_part == $item['link']){ $menuid = $item['id']; break; } //////////////// Определяем правильную ссылку для пункта меню ///////////// //частичное совпадение ссылки и адреса (по началу строки)? $uri_first_part = substr($uri, 0, strlen($item['realink'])); if ($uri_first_part == $item['realink']){ $menuid = $item['id']; break; } } $this->menu_id = $menuid; $this->is_menu_id_strict = $is_strict; return $menuid; }После
НО:
второе решение, также как и мое содержит один нюанс -
есть два пункта меню
1) /catalog/1001
2) /catalog
при клике на первое - активным становится второе. решается сначала перебором полных путей, а затем, если не найдено перебор частичных путей.
вот теперь меня метод menuID() устраивает полностью )))
Можете скинуть сам файл cms.php для 1.9?
Спасибо!
ссылка статьи была host/statya
ссылка категории host/kategoriya
ссылка подкатегории host/podkategoriya