Я ищу маршрут с одной строкой, чтобы маршрутизировать пунктирные имена контроллеров и методов на фактические подчеркнутые имена контроллеров и методов.
Например, 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(); }