smarteq
@smarteq
Web developer, System administrator

Русскоязычные ЧПУ в CodeIgniter?

Всем здравствуйте!



Сразу хочу сказать что ЧПУ вида site.tld/Ололо и site.tld/Атата я делать умею и про вот это: code-igniter.ru/forum/post18174.html (не сочтите за рекламу ресурса, я к нему не имею никакого отношения) тоже в курсе. У меня более сложный случай.



Мне нужны ЧПУ вида site.tld/сказки/сказка-про-белого-бычка site.tld/повести/повесть-временных-лет site.tld/романы/поднятая-целина (само собой все это было взято от балды для примера чтобы показать закономерность).





Если я в роутах вписываю что-то вроде:

$route['сказки'] = «skazki»;



в skazki.php корректно работает только index. Я пытаюсь с помощью $this->uri->segment(n) вытащить «сказка-про-белого-бычка», не работает. Пробовал так:



$route['сказки'] = «skazki/show»;

и так

$route['сказки:/any'] = «skazki»;



в любом случае выбрасывает на 404 страницу.



В принципе этого достаточно если урлы формировать так:

вида site.tld/сказки/?q=сказка-про-белого-бычка и в контроллере внутри index`а ловить через $_GET['q'].



Можно пойти по этому пути глубже и включить $config['enable_query_strings'] и как пишет документация index.php?c=controller&m=method а дальше нагло и цинично с помощью mod_rewrite.



1) Может быть в роутах нужно какую-то правильную регулярку чтобы работало как задумано или я что-то недопонимаю с настройкой роутов в CI?



2) Если всетаки лучше ловить через ?q=… помогите с апачевским правилом реврайта) Честно — мод_реврайт это «боль моя дырка задница» (с) Борат



3) Если не 1 и не 2 — чем плохим грозит мне использование 3-го пункта? В принципе под него и реврайт правило я представляю какое будет, но не представляю архитектурно каких органичений ждать от этого решения. И может быть это даже лучше чем костыль, о котором спрашиваю в вопросе 2?



Заранее благодарю)



Добавлено на следующий день:

рейтинг -5, кто-то минусанул в карму, ИЧСХ ни одного вообще никакого ответа. Обидно даже…



Добавлено спустя еще день:

Всем спасибо кто отвечал, минусовал, плюсовал, в итоге я разобрался!




Меня сгубила невдумчивость в процессе чтения мануалов.

Ларчик открывался проще чем я думал:



В роуты:

$route['сказки/(:any)'] = &quot;skazki/show/$1&quot;;<br/>




В контроллер:

$need = $this-&gt;uri-&gt;segment(2, 0);<br/>

прекрасно вытаскивает то, что было нужно, т.е. в данном примере в $need будет 'сказка-про-белого-бычка' в закодированном виде. Что с ней делать это уже другая история.



Вобщем вопрос считаю закрытым. Надеюсь это поможет всем кто с ним столкнулся. Третьим комментарием кстати приведен вполне работоспособный код.
  • Вопрос задан
  • 5146 просмотров
Пригласить эксперта
Ответы на вопрос 3
blazer
@blazer
можно перенаправлять все запросы с русскими буквами на контроллер, который их будет разбирать

$route['([-_.,a-z0-9а-я/]+)'] = "router/$1";

да, и еще нужно расширить модуль Routes, т.к. там по умолчанию нет поддержки UTF. Сохраняем следующее в application/core/MY_Router.php

<?php

class MY_Router extends CI_Router
{

/**
* Parse Routes
*
* This function matches any routes that may exist in
* the config/routes.php file against the URI to
* determine if the class/method need to be remapped.
*
* @access private
* @return void
*/
function _parse_routes()
{
// Turn the segment array into a URI string
$uri = implode('/', $this->uri->segments);

// Is there a literal match? If so we're done
if (isset($this->routes[$uri]))
{
return $this->_set_request(explode('/', $this->routes[$uri]));
}

// Loop through the route array looking for wild-cards
foreach ($this->routes as $key => $val)
{
// Convert wild-cards to RegEx
$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
// ADDED STRING
$uri = urldecode($uri);
// Does the RegEx match?
if (preg_match('#^'.$key.'$#ui', $uri))
{
// Do we have a back-reference?
if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#ui', $val, $uri);
}

return $this->_set_request(explode('/', $val));
}
}

// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
$this->_set_request($this->uri->segments);
}

}

?>
Ответ написан
Kindman
@Kindman
Если mod_rewrite пугает, то самое простое это ErrorDocument.
В файле .htaccess пишем:
ErrorDocument 404 /404.php
а, вот с этим файликом можно поиграться:
404.php
<?php
function robots($host)
    {
    header("$_SERVER[SERVER_PROTOCOL] 200 OK");
    header("Content-Type: text/plain");
    $host=strtolower($host);
    echo "Host: $host\r\n";
    exit();
    }

function favicon($old=false)
    {
    header("$_SERVER[SERVER_PROTOCOL] 200 OK");
    if ($old) header("Content-Type: image/x-icon"); else
      header("Content-Type: image/vnd.microsoft.icon");
    // "image/ico", "image/icon", "text/ico", "application/ico" => ERRORS!!
    $favicon
     ="AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAA"
     ."AAAwAAAAAAAAAAAAAAAAAAAAAAAAAAEAgQA/IIEAPTy5AD8+vQA/P"
     ."r8AAQC/AD89uwA/P78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
     ."AAAAAAAAAAAABEREQAAAAAREXIREQAAAREXNzcREAAREXd3d3cRAB"
     ."EXd3d3d3EBERd3d3dhERERd3cXcRERERF3cRd3EREVVXdVd3d1VVV"
     ."Vd1V3d3VVVVV3VXd3d1VQVVdVd3d3VQBVd1V3d3VVAAV3VXd3dVAA"
     ."AFVVVHd1AAAAAFVVVQAAD4HzsA4Ac7AMADAACAAQAAgAEAAAAAAAA"
     ."AAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAOAHAAD4HwAA";
    echo base64_decode($favicon);
    }

if (strpos($REQUEST_URI,"robots.txt"))
  robots($HTTP_HOST);

if (strpos($REQUEST_URI,"favicon.ico"))
  favicon(true);// favicon();

echo "<xmp>";
print_r($GLOBALS);
он отдает «грамотный» robots.txt и симпатичненькую «фавиконку» favicon.ico
На все остальные страницы он печатает дамп переменных среды PHP.
Как обрабатывать значения переменных — дело вкуса.
По крайней мере, все русско-язычные чпу-шки будут гарантированно проходить через этот скрипт.
Разумеется этот скрипт можно (и нужно) допилить до кондиции под собственные задачи.
Ответ написан
MpaK999
@MpaK999
Буду!
1. расширьте или перепешите в core/Router.php метод
function _parse_routes() чтобы в preg_match понимал unicode /u добавить
2. в файле config/config.php
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
расширьте символами кирилицы в вашей кодировке

Но в целом это очень хреновая идея, очень.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы