2010-03-11 2 views
25

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

Например URL

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

бы путь к

/controller_name/method_name_which_is_long/ 

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

ответ

47

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

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

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

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

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

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

Затем загрузить файл с именем MY_Router.php в системе/приложение каталога/библиотеки.

<?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 и он будет вызывать правильный контроллер и функцию автоматического преобразования тира подчеркивания.

Edit: Вот наше решение 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]); 
    } 
} 

Теперь нужно поместить этот файл как приложение/ядро ​​/ 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-адресу.Можно удалить этот код, если он не нужен, но он не наносит вреда нормальному потоку.

+3

+1 Это решение, это почти то же самое, что и для правильного направления аргументов командной строки на методы контроллера. – Benoit

+0

Я пробовал следовать этому решению с помощью 2.0 build no no avail - может ли кто-нибудь дать какое-либо представление? –

+1

FYI нашел решение, используя крючки здесь - http://codeigniter.com/forums/viewthread/124396/#644012 –

0

Я не уверен, если вы могли бы сделать что с маршрутом ...

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

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

1

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

3
<?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 $ route ['this-is-a-module-or-controler'] = 'this_is_a_module_or_controller';

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

+0

Я пробовал это, и это нормально для быстрого исправления, но для уточнения - он * изменяет все сегменты, чтобы использовать знак подчеркивания * вместо тире. Поэтому '/ my-controller' перейдет в' my_controller', а также 'ctrl/func/my-data' преобразует данные в' my_data', что может сломать многие ваши страницы (это было с моим). Принятый ответ гораздо более надежный. – DisgruntledGoat

+0

Этот ответ на самом деле намного проще, и его легко настроить только для изменения первых двух элементов в массиве сегментов. 'для ($ I = 0; $ г <2; ++ $ I) { \t, если (IsSet ($ сегменты [$ я])) { сегменты \t \t $ [$ я] = str_replace ('-' , '_', $ segment [$ i]); \t} } родитель :: _ set_request ($ сегментов); ' –

1

Переопределение класса маршрутизатора - отличный подход, существует также способ замены - посредством _ путем регистрации «предсистемного» крючка.

Сначала создайте крюк, добавив следующие строки в файл конфигурации «/ hooks.php»:

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

Теперь создайте файл «myhooks.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

2

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

<?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); 
    } 
?> 

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

+0

Но это не будет работать, если контроллеры размещены в подкаталоге внутри каталога контроллеров, как внутри контроллеров/админ/как первые 2 сегмента станут админ и имя контроллера. – sumanchalki

20

Только вернувшись к этому вопросу после обновления до 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.

+0

Принял меня две секунды, чтобы добавить это, и он отлично работает. Благодаря! – Peter

+0

Простой и приятный. Но он не может заставить его работать для Codeigniter 3. Этот маршрутизатор, кажется, совсем не вызван на общем сервере хостинга. – Ashis

+0

@Ashis согласно [CI3 docs] (http://www.codeigniter.com/userguide3/general/core_classes.html), расширение основных классов работает так же, как и раньше. Вы можете посмотреть исходный класс CI_Router, чтобы убедиться, что он по-прежнему совместим с переопределением 'MY_Router'. – DisgruntledGoat

0

Вы можете использовать этот метод _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(); 
} 
8

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

$route['translate_uri_dashes'] = TRUE; 

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

+0

привет, почему это не работает? –

+0

@RejoanulAlam Вам необходимо использовать последнюю версию воспламенителя кода (3 и выше). –

+1

Проблема заключается в том, что она работает в обоих форматах. 'http: // localhost/project/имя_контроля/имя_пользователя' &' http: // localhost/project/controller-name/method-name' –

Смежные вопросы