Codeigniter направляет регулярное выражение с использованием тире в именах контроллеров/методов


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

Например, URL-адрес

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

Приведет к

/controller_name/method_name_which_is_long/

См.: http://codeigniter.com/forums/viewreply/696690 / что навело меня на мысль спросить:)

Author: DisgruntledGoat, 2010-03-11

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. Можно удалить этот код, если в этом нет необходимости, но это не повредит нормальному потоку.

 47
Author: sumanchalki, 2011-12-01 07:24:45

Просто возвращаюсь к этому вопросу после обновления до 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.

 20
Author: DisgruntledGoat, 2011-10-04 00:47:08

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

   $route['translate_uri_dashes'] = TRUE;

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

 8
Author: Samy Massoud, 2015-05-12 08:01:51
<?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 $маршрут['это-модуль или контроллер'] = 'это_ис_а_модуль или_контроллер';

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

 3
Author: e-mike, 2010-06-18 13:22:05

Это старый вопрос, но я хотел бы сообщить, что у 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);
    }
?>

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

 2
Author: Jason Lewis, 2011-05-08 10:24:03

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

 1
Author: Sean Vieira, 2010-03-11 20:24:42

Переопределение класса маршрутизатора - хороший подход, есть также способ заменить - на _, зарегистрировав "предсистемный" хук.

Сначала создайте крючок, добавив эти строки в свою конфигурацию/крючки.файл 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

 1
Author: André Laszlo, 2011-01-12 13:18:11

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

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

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

 0
Author: Josh, 2010-03-11 20:11:22

Вы можете использовать этот метод _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();
}
 0
Author: Sajjad Ashraf, 2014-11-27 12:15:21