3.0 HTML-маршрут Cakephp только

Я хотел бы направить URL-адреса, которые имеют следующий шаблон;

http://mywebsite.com/en/url.html

Код ниже работает.

Router::prefix ( 'en', function ($routes) {
    $routes->extensions ( [ 
            'html' 
    ] );
    $routes->connect ( '/:page', [ 
            'controller' => 'Pages',
            'action' => 'view',
    ]
    , [ 
            'pass' => [ 
                    'page' 
            ] 
    ] );
    $routes->fallbacks ( 'InflectedRoute' );
} );

Проблема возникает для контроллеров, не имеющих расширения html. Например

http://mywebsite.com/en/controller/

Есть ли способ ограничить

$routes->connect ( '/:page', [ 
        'controller' => 'Pages',
        'action' => 'view',
]

на страницы, которые заканчиваются расширением .html?


person MontrealDevOne    schedule 21.12.2014    source источник


Ответы (2)


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

Я бы сказал, что лучшим выбором будет пользовательский класс маршрута, который может не только ограничивать совпадающие входящие URL-адреса (Route::parse()), но и обратную маршрутизацию (Route::match()).

Вы можете просто протестировать расширение URL-адреса (массива) против расширений, определенных через RouteBuilder::extensions(), чтобы требовалось одно из анализируемых расширений, вот очень простой пример:

src/Routing/Route/MyCustomRoute.php

namespace App\Routing\Route;

use Cake\Routing\Route\Route;

class MyCustomRoute extends Route {

    public function parse($url) {
        list(, $ext) = $this->_parseExtension($url);
        if(!in_array($ext, $this->extensions())) {
            return false;
        }
        return parent::parse($url);
    }

    public function match(array $url, array $context = []) {
        if(!isset($url['_ext']) || !in_array($url['_ext'], $this->extensions())) {
            return false;
        }
        return parent::match($url, $context);
    }

}

config/routes.php

// ...

$routes->connect('/:page', [
    'controller' => 'Pages',
    'action' => 'view',
], [
    'routeClass' => '\App\Routing\Route\MyCustomRoute',
    'pass' => ['page']
]);

// ...

Это приведет к тому, что только URL-адреса с расширениями будут анализироваться, и только массивы URL-адресов с предоставленным расширением будут сопоставляться, т.е.

/en/page.html
['controller' => 'Pages', 'action' => 'view', '_ext' => 'html']

будет работать, пока

/en/page
/en/page.xml
['controller' => 'Pages', 'action' => 'view']
['controller' => 'Pages', 'action' => 'view', '_ext' => 'xml']

не будет.

Для получения дополнительной информации см.

person ndm    schedule 22.12.2014

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

Router::prefix ( 'en', function ($routes) { $routes->extensions ( [ 'html' ] ); $routes->connect ( '/:page', [ 'controller' => 'Pages', 'action' => 'view', ] , [ 'page' => '[0-9a-z]+', 'pass' => [ 'page' ] ] ); $routes->fallbacks ( 'InflectedRoute' ); } );

РЕДАКТИРОВАТЬ: приведенное выше решение на самом деле не работает (см. комментарий ndm). Мне не удалось сделать то, что вы ищете, с системой маршрутизации. Я предлагаю проверить расширение непосредственно в вашем контроллере и выдать ошибку 404, если оно не соответствует «html».

person PGBI    schedule 21.12.2014
comment
Это не будет делать то, что ищет OP, не указывайте расширение, и вы увидите, что маршрут будет работать нормально. Это приведет к тому, что маршрут не будет совпадать в случае предоставления расширения, отличного от .html, потому что в этом случае расширение будет частью элемента :page, который не пройдет проверку регулярного выражения, поскольку не допускает точек. - person ndm; 22.12.2014