Codeigniter Routes regex – использование тире в именах контроллеров / методов

Я ищу маршрут с одной строкой, чтобы маршрутизировать пунктирные имена контроллеров и методов на фактические подчеркнутые имена контроллеров и методов.

Например, URL

/controller-name/method-name-which-is-long/ 

будет направлять

 /controller_name/method_name_which_is_long/ 

см .: http://codeigniter.com/forums/viewreply/696690/, который дал мне идею спросить 🙂

Это тоже мое требование, и я использовал маршруты, такие как

 $route['logued/presse-access'] = "logued/presse_access"; 

В моем предыдущем проекте мне нужно было создать 300-400 правил маршрутизации, большинство из которых связано с тире, чтобы подчеркнуть преобразование.

Для моего следующего проекта я охотно хочу этого избежать. Я сделал быстрый взлом и протестировал его, хотя и не использовал ни на одном сервере, его работа для меня. Сделайте следующее ..

Убедитесь, что subclass_prefix выглядит следующим образом в вашей системе / application / config / config.php

 $config['subclass_prefix'] = 'MY_'; 

Затем загрузите файл с именем MY_Router.php в каталог system / application / libraries.

 <?php class MY_Router extends CI_Router { function set_class($class) { //$this->class = $class; $this->class = str_replace('-', '_', $class); //echo 'class:'.$this->class; } function set_method($method) { // $this->method = $method; $this->method = str_replace('-', '_', $method); } function _validate_request($segments) { // Does the requested controller exist in the root folder? if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).EXT)) { return $segments; } // Is the controller in a sub-folder? if (is_dir(APPPATH.'controllers/'.$segments[0])) { // Set the directory and remove it from the segment array $this->set_directory($segments[0]); $segments = array_slice($segments, 1); if (count($segments) > 0) { // Does the requested controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).EXT)) { show_404($this->fetch_directory().$segments[0]); } } else { $this->set_class($this->default_controller); $this->set_method('index'); // Does the default controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT)) { $this->directory = ''; return array(); } } return $segments; } // Can't find the requested controller... show_404($segments[0]); } } 

Теперь вы можете свободно использовать URL-адрес, например http://example.com/logued/presse-access, и он вызовет правильный контроллер и функцию, автоматически преобразуя тире в знак подчеркивания.

Изменить: вот наше решение Codeigniter 2, которое переопределяет новые функции CI_Router:

 <?php class MY_Router extends CI_Router { function set_class($class) { $this->class = str_replace('-', '_', $class); } function set_method($method) { $this->method = str_replace('-', '_', $method); } function set_directory($dir) { $this->directory = $dir.'/'; } function _validate_request($segments) { if (count($segments) == 0) { return $segments; } // Does the requested controller exist in the root folder? if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).'.php')) { return $segments; } // Is the controller in a sub-folder? if (is_dir(APPPATH.'controllers/'.$segments[0])) { // Set the directory and remove it from the segment array $this->set_directory($segments[0]); $segments = array_slice($segments, 1); while(count($segments) > 0 && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])) { // Set the directory and remove it from the segment array $this->set_directory($this->directory . $segments[0]); $segments = array_slice($segments, 1); } if (count($segments) > 0) { // Does the requested controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).'.php')) { if ( ! empty($this->routes['404_override'])) { $x = explode('/', $this->routes['404_override']); $this->set_directory(''); $this->set_class($x[0]); $this->set_method(isset($x[1]) ? $x[1] : 'index'); return $x; } else { show_404($this->fetch_directory().$segments[0]); } } } else { // Is the method being specified in the route? if (strpos($this->default_controller, '/') !== FALSE) { $x = explode('/', $this->default_controller); $this->set_class($x[0]); $this->set_method($x[1]); } else { $this->set_class($this->default_controller); $this->set_method('index'); } // Does the default controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) { $this->directory = ''; return array(); } } return $segments; } // If we've gotten this far it means that the URI does not correlate to a valid // controller class. We will now see if there is an override if ( ! empty($this->routes['404_override'])) { $x = explode('/', $this->routes['404_override']); $this->set_class($x[0]); $this->set_method(isset($x[1]) ? $x[1] : 'index'); return $x; } // Nothing else to do at this point but show a 404 show_404($segments[0]); } } 

Теперь нужно разместить этот файл, например application / core / MY_Router.php, и убедиться, что он имеет subclass_prefix, как $config['subclass_prefix'] = 'MY_'; в приложении / config / config.php

В метод _validate_request() добавлено несколько дополнительных строк кода:

 while(count($segments) > 0 && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])) { // Set the directory and remove it from the segment array $this->set_directory($this->directory . $segments[0]); $segments = array_slice($segments, 1); } 

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

Вернемся к этому вопросу после обновления до CodeIgniter 2. Вот решение, которое более надежное, чем принятый ответ, потому что оно сохранится при обновлении ядра CodeIgniter.

 <?php class MY_Router extends CI_Router { public function set_class($class) { parent::set_class($this->_repl($class)); } public function set_method($method) { parent::set_method($this->_repl($method)); } public function _validate_request($segments) { if (isset($segments[0])) $segments[0] = $this->_repl($segments[0]); if (isset($segments[1])) $segments[1] = $this->_repl($segments[1]); return parent::_validate_request($segments); } private function _repl($s) { return str_replace('-', '_', $s); } } 

Он должен быть сохранен как application/core/MY_Router.php . Теперь вы можете иметь имена Controller и Method с подчеркиваниями в них, такими как Abc_Def (в файле abc_def.php ) и ссылаться на них с помощью URL /abc-def .

На самом деле это родной теперь в Codeigniter 3 Просто сделайте это в файле маршрутов

  $route['translate_uri_dashes'] = TRUE; 

И он сделает это для контроллеров и методов автоматически.
Пожалуйста, проголосуйте за этот ответ, поскольку он самый последний

 <?php class MY_Router extends CI_Router { function _set_request($segments = array()) { parent::_set_request(str_replace('-', '_', $segments)); } } ?> 

Поместите этот файл MY_Router.php внутрь / application / libraries (CI1) или / application / core (CI2). Помните, что это будет влиять на все сегменты, а не только на модуль, контроллер и метод.

Альтернативой этому является добавление каждого сегмента в router.php $ route ['this-is-a-module-or-controler'] = 'this_is_a_module_or_controller';

Как вы можете видеть, метод расширения будет проще в использовании. Вы можете выбрать, чтобы функция также обрабатывала только первые два или три сегмента, чтобы другие сегменты не были затронуты заменой _.

Это старый вопрос, но я хотел бы опубликовать, что у e-mike было отличное решение этой проблемы, и намного проще.

 <?php public function _set_request($segments){ // Fix only the first 2 segments for($i = 0; $i < 2; ++$i){ if(isset($segments[$i])){ $segments[$i] = str_replace('-', '_', $segments[$i]); } } // Run the original _set_request method now, giving it our newly replaced segments parent::_set_request($segments); } ?> 

Надеюсь, это поможет кому-то еще с этой проблемой.

Я считаю, что то, что вы ищете, это либо предварительная система, либо крюк предварительного контроллера, который возьмет запрошенный URI и обновит его.

Переопределение класса Router – отличный подход, есть также способ замены – посредством _ путем регистрации «pre-system» hook.

Сначала создайте крючок, добавив эти строки в файл config / hooks.php:

 $hook['pre_system'] = array( 'class' => '', 'function' => 'prettyurls', 'filename' => 'myhooks.php', 'filepath' => 'hooks', 'params' => array() ); 

Теперь создайте файл «myhooks.php» в папке «application / hooks» и добавьте эту функцию (не забудьте открыть тег PHP, если это первый крючок):

 <?php function prettyurls() { if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') { $newkey = str_replace('-','_',key($_GET)); $_GET[$newkey] = $_GET[key($_GET)]; unset($_GET[key($_GET)]); } if (isset($_SERVER['PATH_INFO'])) $_SERVER['PATH_INFO'] = str_replace('-','_',$_SERVER['PATH_INFO']); if (isset($_SERVER['QUERY_STRING'])) $_SERVER['QUERY_STRING'] = str_replace('-','_',$_SERVER['QUERY_STRING']); if (isset($_SERVER['ORIG_PATH_INFO'])) $_SERVER['ORIG_PATH_INFO'] = str_replace('-','_',$_SERVER['ORIG_PATH_INFO']); if (isset($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = str_replace('-','_',$_SERVER['REQUEST_URI']); } с <?php function prettyurls() { if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') { $newkey = str_replace('-','_',key($_GET)); $_GET[$newkey] = $_GET[key($_GET)]; unset($_GET[key($_GET)]); } if (isset($_SERVER['PATH_INFO'])) $_SERVER['PATH_INFO'] = str_replace('-','_',$_SERVER['PATH_INFO']); if (isset($_SERVER['QUERY_STRING'])) $_SERVER['QUERY_STRING'] = str_replace('-','_',$_SERVER['QUERY_STRING']); if (isset($_SERVER['ORIG_PATH_INFO'])) $_SERVER['ORIG_PATH_INFO'] = str_replace('-','_',$_SERVER['ORIG_PATH_INFO']); if (isset($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = str_replace('-','_',$_SERVER['REQUEST_URI']); } 

Вам, вероятно, потребуется отредактировать файл config / config.php, чтобы включить перехваты (вокруг строки 91 для меня):

 $config['enable_hooks'] = TRUE; 

Этот ответ разорван с http://codeigniter.com/forums/viewthread/124396/#644012

Я не уверен, что вы можете сделать это с помощью маршрута …

Однако где-то в основных библиотеках Codeigniter (возможно, Router или URI) будет что-то, что преобразует подчеркнутый uris в имя класса camelcase.

Я быстро посмотрел и не смог его найти, но если вы это сделаете, просто скопируйте эту библиотеку в папку приложений / библиотек и измените ее там.

Вы можете использовать этот метод _remap () для обработки такого поведения. Поместите этот метод в свои контроллеры или создайте основной контроллер и поместите его.

 public function _remap($method, $params = array()){ if(method_exists($this, $method)){ return call_user_func_array(array($this, $method), $params); }else{ $method = str_replace("-", "_", $method); if(method_exists($this, $method)){ return call_user_func_array(array($this, $method), $params); } } show_404(); }