Kohana 3: Как создать маршрут для серверной части? - PullRequest
1 голос
/ 14 ноября 2011

Я создал папку «backend» в / application / classes / controller / в приложении Kohana 3.2.

Итак, у меня есть структура папок, такая как:

/application
+/classes
++/controller/
+++/A_controller.php
+++/Another_controller.php
+++/backend/
++++/A_Backend_controller.php

Маршрутыв моем bootstrap.php:

Route::set('default', '(<controller>(/<action>(/<id>)))')
    ->defaults(array(
        'controller' => 'home',
        'action'     => 'index',
    ));

Route::set('backend', '<directory>(/<controller>(/<action>(/<id>)))')
->defaults(array(
        'directory' => 'backend',
        'controller' => 'home',
        'action'     => 'index',
    ));

У меня есть .htaccess, который переписывает мои URL-адреса и удаляет «index.php» из URL-адреса, так что я обычно вызываю такую ​​страницу: www.mysite.com / controller_name / action_name

Из того, что я прочитал в документации о маршруте, с написанным «внутренним» маршрутом, это должно работать: www.mysite.com/backend/controller_name/action_name

Но это не ... любая идея, почему?

Ответы [ 4 ]

2 голосов
/ 14 ноября 2011

Проблема в том, что в вашем маршруте <directory>. Это изменит значение каталога, когда Kohana попытается загрузить ваш маршрут. Ваш внутренний маршрут должен выглядеть следующим образом.

Route::set('backend', 'backend(/<controller>(/<action>(/<id>)))')
    ->defaults(array(
        'directory' => 'backend',
        'controller' => 'home',
        'action'     => 'index',
    ));

Примечание. Этот маршрут должен предшествовать стандартному маршруту по умолчанию. В противном случае Кохана никогда не доберется до вашего маршрута.

1 голос
/ 15 ноября 2011

Как уже было сказано, Уэйд, ваш бэкэнд маршрута должен предшествовать вашему маршруту по умолчанию.

Затем убедитесь, что у вас есть home.php в вашей внутренней папке с контроллером, определенным следующим образом:

class Controller_Backend_Home extends Controller {
    public function action_index(){
    }
} 
1 голос
/ 15 ноября 2011

Вы определяете два маршрута и не перегружаете регулярное выражение ни для одного сегмента.Регулярное выражение для сегмента по умолчанию [^/.,;?\n]++, поэтому каждый сегмент должен соответствовать этому регулярному выражению.

Ваш первый маршрут - это маршрут, который идет с Kohana из коробки.Он будет соответствовать 0, 1, 2 и 3 сегментам, разделенным косой чертой.Ваш второй маршрут будет соответствовать 1, 2, 3 и 4 сегментам.

Поскольку вы добавите их в таком порядке, маршрут с именем «default» не сможет соответствовать только для более чем трех сегментов, таких как uri: user / purcheses/ просмотр / 42.Если маршрут по умолчанию не соответствует URI, будет проверен следующий маршрут.В вашем случае маршрут с именем «backend».

Если вы поменяете местами порядок двух маршрутов, то маршрут «backend» будет первым и потерпит неудачу только для 0 или более 4 сегментов.С 0 сегментами маршрут 'default' будет соответствовать ему, а с 5 или более сегментами будет выдано Http_Exception_404.Но когда вы помещаете 'backend' первым, он будет направлять только к контроллерам в подкаталогах, которые, скорее всего, разбивают много страниц.

Вы можете заменить <directory> на жестко закодированное значение, добавив регулярное выражение длясоздать лямбда / маршрут обратного вызова.

По порядку:

Route::set('backend', 'backend(/<controller>(/<action>(/<id>)))')
->defaults(array(
        'directory' => 'backend',
        'controller' => 'home',
        'action'     => 'index',
    ));

Route::set('backend', '<directory>(/<controller>(/<action>(/<id>)))', array('foo|bar|backend'))
->defaults(array(
        'directory' => 'backend',
        'controller' => 'home',
        'action'     => 'index',
    ));

// not tested
Route::set('nested', function($uri, $directory = '')
{
    if ( ! $segments = explode('/', $uri))
        return;

    // get a multidimensional array of the Cascading File System with classes/controller as the root
    $list = Kohana::list_files('classes/controller');

    foreach($segments AS $segment)
    {
        if ( ! isset($list['classes/controller/'.$directory.$segment]))
            break;

        // we found a new existing directory, append it
        $directory .= array_shift($segments).DIRECTORY_SEPARATOR;

        // reduce $list to the remaining possible paths
        $list = $list[rtrim('classes/controller/'.$directory, DIRECTORY_SEPARATOR)];
    }

    if ( ! empty($directory) AND $params = Route::get('default')->matches(implode('/', $segments)))
    {
        $params['directory'] = rtrim($directory, DIRECTORY_SEPARATOR);

        return $params;
    }
},
    // this is used for reverse routing
    '<directory>(/<controller>(/<action>(/<id>)))')
->defaults(array(
        'controller' => 'dashboard',
        'action'     => 'index',
    ));
0 голосов
/ 14 ноября 2011

Это то, что я использую в одном из моих приложений

Route::set('default', 'admin/<controller>(/<action>(/<id>))')
    ->defaults(array(
            'directory'  => 'admin',
            'action'     => 'index',
    ));

Route::set('user', '(<controller>(/<action>(/<id>)))')
    ->defaults(array(
            'controller' => 'user',
            'action'     => 'index',
    ));

Как это будет работать?

  • Согласно Kohana, маршрут, указанный первым, получает наивысший приоритет.
  • Если он не может найти соответствия для какого-либо маршрута, он возвращается к default route

Во-первых, если мы хотим работать со структурой каталогов, мы должны сначала перечислить эти маршруты на основе каталогов. Если вы посмотрите, если мы должны были поставить маршрут user в списке первым, он будет выбран для любого шаблона URL, например: http://example.com/directory/controller/action.

Чтобы избежать такого сценария, нам нужно перечислить такие маршруты после маршрута directory based. Да, это странно. Но так работает кохана. Я желаю Кохане улучшить это поведение.

Обновление Попробуйте отладку с помощью Лямбда / логика маршрута обратного вызова . Это может объяснить все.

Route::set('testing', function($uri)
{
    if ($uri == 'foo/bar') // check the prefix for "backend"
        return array(
            'controller' => 'welcome',
            'action'     => 'foobar',
        );
    },
    'foo/bar'
);
...