Codeigniter направляет регулярное выражение с использованием тире в именах контроллеров/методов
Я ищу маршрут в одну строку, чтобы направить пунктирные имена контроллеров и методов к фактическим подчеркнутым именам контроллеров и методов.
Например, URL-адрес
/controller-name/method-name-which-is-long/
Приведет к
/controller_name/method_name_which_is_long/
См.: http://codeigniter.com/forums/viewreply/696690 / что навело меня на мысль спросить:)
9 answers
Это тоже в точности мое требование, и я использовал такие маршруты, как
$route['logued/presse-access'] = "logued/presse_access";
В моем предыдущем проекте мне нужно было создать 300-400 правил маршрутизации, большинство из них связано с преобразованием тире в подчеркивание.
Для моего следующего проекта я очень хочу избежать этого. Я сделал несколько быстрых взломов и протестировал его, хотя не использовал ни на одном живом сервере, он работает на меня. Выполните следующие действия..
Убедитесь, что в вашем файле subclass_prefix указано следующее system/application/config/config.php
$config['subclass_prefix'] = 'MY_';
Затем загрузите файл с именем MY_Router.php в каталоге system/application/библиотеки.
<?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_';
в application/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
. Теперь вы можете использовать имена контроллеров и методов с подчеркиванием, например 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 внутри /приложения/библиотеки (CI1) или /приложения/ядра (CI2) Помните, что это повлияет на все сегменты, а не только на модуль, контроллер и метод.
Альтернативой этому расширению является добавление каждого сегмента в router.php $маршрут['это-модуль или контроллер'] = 'это_ис_а_модуль или_контроллер';
Как вы можете видеть, метод расширения будет проще в использовании. Вы можете выбрать, чтобы функция также обрабатывала только первые два или три сегменты, чтобы другие сегменты не были затронуты заменой _.
Это старый вопрос, но я хотел бы сообщить, что у 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 и обновит его.
Переопределение класса маршрутизатора - хороший подход, есть также способ заменить - на _, зарегистрировав "предсистемный" хук.
Сначала создайте крючок, добавив эти строки в свою конфигурацию/крючки.файл php':
$hook['pre_system'] = array(
'class' => '',
'function' => 'prettyurls',
'filename' => 'myhooks.php',
'filepath' => 'hooks',
'params' => array()
);
Теперь создайте ‘Мои крючки".файл php’ в папке "приложение/крючки" и добавьте эту функцию (не забудьте открыть тег 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']);
}
Вероятно, вам потребуется отредактировать свой‘config/config.php ’файл для включения крючков (вокруг строка 91 для меня):
$config['enable_hooks'] = TRUE;
Этот ответ вырван из http://codeigniter.com/forums/viewthread/124396/#644012
Я не уверен, что вы могли бы сделать это с помощью маршрута...
Однако где-то в библиотеках ядра Codeigniter (возможно, маршрутизатор или URI) будет что-то, что преобразует подчеркнутые uri в имя класса 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();
}