O roteamento fornece ferramentas que mapeiam URLs para ações do controlador. Ao definir rotas, você pode separar como o aplicativo
é implementado e como os URLs são estruturadas.
O roteamento no CakePHP também abrange a idéia de roteamento reverso, onde uma matriz de parâmetros pode ser transformada em uma
string de URL. Ao usar o roteamento reverso, você pode redimensionar a estrutura de URL do seu aplicativo sem precisar atualizar
todo o seu código.
Tour Rápido
Esta seção ensinará a você, como exemplo, os usos mais comuns do CakePHP Router. Normalmente, você deseja exibir algo como uma
página de destino e adicionar isso ao seu arquivo routes.php:
use Cake\Routing\Router;
// Usando o construtor de rota com escopo.
Router::scope('/', function ($routes) {
$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
});
// Usando o método estático.
Router::connect('/', ['controller' => 'Articles', 'action' => 'index']);
O Router
fornece duas interfaces para conectar rotas. O método estático é uma interface compatível com versões anteriores,
enquanto os construtores com escopo oferecem uma sintaxe mais concisa ao criar várias rotas e melhor desempenho.
Isso executará o método de índice no ArticlesController
quando a página inicial do seu site for visitada. Às vezes, você
precisa de rotas dinâmicas que aceitem vários parâmetros; esse seria o caso, por exemplo, de uma rota para visualizar o conteúdo
de um artigo:
$routes->connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);
A rota acima aceitará qualquer URL semelhante a /articles/15
e invocará o método view (15)
no ArticlesController
.
Porém, isso não impedirá que as pessoas tentem acessar URLs semelhantes a /articles/foobar
. Se desejar, você pode restringir
alguns parâmetros para estar em conformidade com uma expressão regular:
$routes->connect(
'/articles/:id',
['controller' => 'Articles', 'action' => 'view'],
)
->setPatterns(['id' => '\d+'])
->setPass(['id']);
// Antes de 3.5, use o array de opções
$routes->connect(
'/articles/:id',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
)
O exemplo anterior alterou o marcador de estrelas por um novo espaço reservado para :id
. O uso de espaços reservados nos
permite validar partes da URL; nesse caso, usamos a expressão regular \d+
para que apenas os dígitos correspondam.
Finalmente, pedimos ao roteador para tratar o espaço reservado id
como um argumento de função para o método view()
especificando a opção pass
. Mais sobre o uso dessa opção posteriormente.
O roteador do CakePHP também pode reverter as rotas de correspondência. Isso significa que, a partir de uma matriz que contém parâmetros correspondentes, é capaz de gerar uma string de URL:
use Cake\Routing\Router;
echo Router::url(['controller' => 'Articles', 'action' => 'view', 'id' => 15]);
// Saída
/articles/15
As rotas também podem ser rotuladas com um nome exclusivo, isso permite que você as referencie rapidamente ao criar links, em vez de especificar cada um dos parâmetros de roteamento:
// Em routes.php
$routes->connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
use Cake\Routing\Router;
echo Router::url(['_name' => 'login']);
// Saída
/login
Para ajudar a manter seu código de roteamento DRY, o roteador tem o conceito de “escopos”. Um escopo define um segmento de caminho comum e, opcionalmente, rotea os padrões. Todas as rotas conectadas dentro de um escopo herdarão o caminho/padrão de seus escopos de encapsulamento:
Router::scope('/blog', ['plugin' => 'Blog'], function ($routes) {
$routes->connect('/', ['controller' => 'Articles']);
});
A rota acima combinaria com /blog/
e enviaria para Blog\Controller\ArticlesController::index()
.
O esqueleto do aplicativo vem com algumas rotas para você começar. Depois de adicionar suas próprias rotas, você poderá remover as rotas padrão se não precisar delas.
Conectando Rotas
-
Cake\Routing\Router::connect($route, $defaults = [], $options = [])
Para manter seu código DRY você deve usar “escopos de roteamento”. Os escopos de roteamento não apenas permitem que você mantenha seu código DRY, eles também ajudam o Router a otimizar sua operação. O método padrão é o escopo /
. Para criar um escopo e conectar algumas rotas, usaremos o método scope()
:
// Em config/routes.php
use Cake\Routing\Route\DashedRoute;
Router::scope('/', function ($routes) {
// Conecte as rotas de fallback genéricas.
$routes->fallbacks(DashedRoute::class);
});
O método connect()
leva até três parâmetros: o modelo de URL que você deseja corresponder, os valores padrão para seus elementos de rota e as opções para a rota. As opções freqüentemente incluem regras de expressões regulares para ajudar o roteador a combinar elementos na URL.
O formato básico para uma definição de rota é:
$routes->connect(
'/url/template',
['default' => 'defaultValue'],
['option' => 'matchingRegex']
);
O primeiro parâmetro é usado para informar ao roteador que tipo de URL você está tentando controlar. A URL é uma string delimitada por uma barra normal, mas também pode conter um curinga (*) ou Elementos de Rota. O uso de um curinga informa ao roteador que você deseja aceitar quaisquer argumentos adicionais fornecidos. As rotas sem um * correspondem apenas ao padrão de modelo exato fornecido.
Depois de especificar uma URL, use os dois últimos parâmetros de connect()
para dizer ao CakePHP o que fazer com uma solicitação, uma vez que ela corresponda. O segundo parâmetro é uma matriz associativa. As chaves da matriz devem ser nomeadas após os elementos de rota que o modelo de URL representa. Os valores na matriz são os valores padrão para essas chaves. Vejamos alguns exemplos básicos antes de começarmos a usar o terceiro parâmetro de connect()
:
$routes->connect(
'/pages/*',
['controller' => 'Pages', 'action' => 'display']
);
Esta rota é encontrada no arquivo routes.php distribuído com o CakePHP. Ele corresponde a qualquer URL que comece com /pages/
e passa para a ação display()
do PagesController
. Um pedido para /pages/products
seria mapeado para PagesController->display('products')
.
Além da estrela gananciosa /*
existe também a sintaxe da estrela /**
. Usando uma estrela dupla à direita, capturaremos o restante de uma URL como um único argumento transmitido. Isto é útil quando você quer usar um argumento que inclua um /
nele:
$routes->connect(
'/pages/**',
['controller' => 'Pages', 'action' => 'show']
);
A URL de entrada de /pages/the-example-/-e-proof
resultaria em um único argumento passado de the-example-/-e-proof
.
Você pode usar o segundo parâmetro de connect()
para fornecer quaisquer parâmetros de roteamento que sejam compostos dos valores padrão da rota
$routes->connect(
'/government',
['controller' => 'Pages', 'action' => 'display', 5]
);
Este exemplo mostra como você pode usar o segundo parâmetro de connect()
para definir parâmetros padrão. Se você criou um site que apresenta produtos para diferentes categorias de clientes, considere a possibilidade de criar uma rota. Isso permite que você crie um link para /government
em vez de /pages/display/5
.
Um uso comum para o roteamento é criar segmentos de URL que não correspondam aos seus nomes de controlador ou modelo. Digamos que em vez de acessar nosso URL regular em /users/some_action/5`, gostaríamos de poder acessá-lo por /cooks/some_action/5
. A rota seguinte cuida disso:
$routes->connect(
'/cooks/:action/*', ['controller' => 'Users']
);
Isto está dizendo ao Roteador que qualquer URL que comece com /cooks/
deve ser enviado para o UsersController
. A ação chamada dependerá do valor do parâmetro :action
. Usando Elementos de Rota, você pode criar rotas variáveis, que aceitam entrada ou variáveis do usuário. A rota acima também usa a estrela gananciosa. A estrela gananciosa indica que esta rota deve aceitar qualquer argumento de posição adicional dado. Estes argumentos serão disponibilizados no array Passando Argumentos.
Ao gerar URLs, as rotas são usadas também. Usando ['controller' => 'Users', 'action' => 'some_action', 5]
como uma URL irá gerar /cooks/some_action/5
se a rota acima for a primeira encontrada.
As rotas que conectamos até agora corresponderão a qualquer verbo HTTP. Se você estiver criando uma API REST, geralmente desejará mapear ações HTTP para diferentes métodos de controlador. O RouteBuilder
fornece métodos auxiliares que tornam mais simples a definição de rotas para verbos HTTP específicos:
// Crie uma rota que responda apenas a solicitações GET.
$routes->get(
'/cooks/:id',
['controller' => 'Users', 'action' => 'view'],
'users:view'
);
// Criar uma rota que responda apenas a solicitações PUT
$routes->put(
'/cooks/:id',
['controller' => 'Users', 'action' => 'update'],
'users:update'
);
As rotas acima mapeiam a mesma URL para diferentes ações do controlador com base no verbo HTTP usado. As solicitações GET irão para a ação “ver”, enquanto as solicitações PUT irão para a ação “atualizar”. Existem métodos auxiliares HTTP para:
GET
POST
PUT
PATCH
DELETE
OPTIONS
HEAD
Todos esses métodos retornam a instância da rota, permitindo que você aproveite os fluent setters para configurar ainda mais sua rota.
Elementos de Rota
Você pode especificar seus próprios elementos de rota e isso permite que você defina locais na URL onde os parâmetros das ações do controlador devem estar. Quando um pedido é feito, os valores para estes elementos de rota são encontrados em $this->request->getParam()
no controlador. Quando você define um elemento de rota personalizado, você pode, opcionalmente, especificar uma expressão regular - isso diz ao CakePHP como saber se a URL está formada corretamente ou não. Se você optar por não fornecer uma expressão regular, qualquer caractere que não seja /
será tratado como parte do parâmetro:
$routes->connect(
'/:controller/:id',
['action' => 'view']
)->setPatterns(['id' => '[0-9]+']);
// Antes de 3.5, use o array de opções
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+']
);
O exemplo acima ilustra como criar uma maneira rápida de visualizar modelos de qualquer controlador criando uma URL que se parece com /controllerername/:id
. A URL fornecida para connect()
especifica dois elementos de rota: :controller
e :id
. O elemento :controller
é um elemento de rota padrão do CakePHP, portanto o roteador sabe como combinar e identificar os nomes dos controladores nas URLs. O elemento :id
é um elemento de rota personalizado e deve ser esclarecido ainda mais especificando uma expressão regular correspondente no terceiro parâmetro de connect()
.
O CakePHP não produz automaticamente URLs em minúsculas e tracejadas ao usar o parâmetro :controller
. Se você precisar disso, o exemplo acima pode ser reescrito da seguinte maneira:
use Cake\Routing\Route\DashedRoute;
// Crie um construtor com uma classe de rota diferente.
$routes->scope('/', function ($routes) {
$routes->setRouteClass(DashedRoute::class);
$routes->connect('/:controller/:id', ['action' => 'view'])
->setPatterns(['id' => '[0-9]+']);
// Antes de 3.5 usar matriz de opções
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+']
);
});
A classe DashedRoute
garantirá que os parâmetros :controller
e :plugin
estejam corretamente em minúsculas e tracejados.
Se você precisar de URLs minúsculas e sublinhadas durante a migração de um aplicativo CakePHP 2.x, poderá usar a classe InflectedRoute
.
Nota
Padrões usados para elementos de rota não devem conter nenhum
grupo de captura. Em caso afirmativo, o roteador não funcionará corretamente.
Uma vez definida essa rota, solicitar /apples/5
chamaria o método view()
de ApplesController. Dentro do método view()
, você precisaria acessar o ID passado em $this->request->getParam('id')
.
Se você possui um único controlador no seu aplicativo e não deseja que o nome do controlador apareça na URL, é possível mapear todos os URLs para ações no seu controlador. Por exemplo, para mapear todos os URLs para ações do controlador home
, por exemplo, ter URLs como /demo
em vez de /home/demo
, você pode fazer o seguinte:
$routes->connect('/:action', ['controller' => 'Home']);
Se você deseja fornecer um URL que não diferencia maiúsculas de minúsculas, pode usar modificadores embutidos de expressão regular:
// Antes da 3.5, use a matriz de opções em vez de setPatterns()
$routes->connect(
'/:userShortcut',
['controller' => 'Teachers', 'action' => 'profile', 1],
)->setPatterns(['userShortcut' => '(?i:principal)']);
Mais um exemplo e você será um profissional de roteamento:
// Antes da 3.5, use a matriz de opções em vez de setPatterns()
$routes->connect(
'/:controller/:year/:month/:day',
['action' => 'index']
)->setPatterns([
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
]);
Isso está bastante envolvido, mas mostra como as rotas podem ser poderosas. O URL fornecido possui quatro elementos de rota. O primeiro é familiar para nós: é um elemento de rota padrão que diz ao CakePHP para esperar um nome de controlador.
Em seguida, especificamos alguns valores padrão. Independentemente do controlador, queremos que a ação index()
seja chamada.
Por fim, especificamos algumas expressões regulares que corresponderão a anos, meses e dias na forma numérica. Observe que parênteses (agrupamento) não são suportados nas expressões regulares. Você ainda pode especificar alternativas, como acima, mas não agrupadas entre parênteses.
Uma vez definida, essa rota corresponderá a /articles/2007/02/01
, /articles/2004/11/16
, entregando as solicitações às ações index()
de seus respectivos controladores , com os parâmetros de data em $this->request->getParam()
.
Existem vários elementos de rota que têm um significado especial no CakePHP e não devem ser usados, a menos que você queira o significado especial
controller
Usado para nomear o controlador para uma rota.
action
Usado para nomear a ação do controlador para uma rota.
plugin
Usado para nomear o plug-in em que um controlador está localizado.
prefix
Usado para Prefix Routing
_ext
Usado para File extentions routing.
_base
Defina como false
para remover o caminho base da URL gerada. Se o seu aplicativo não estiver no diretório raiz, isso poderá ser usado para gerar URLs que são “relativos ao cake”
_scheme
Configure para criar links em diferentes esquemas, como webcal ou ftp. O padrão é o esquema atual.
_host
Defina o host a ser usado para o link. O padrão é o host atual.
_port
Defina a porta se precisar criar links em portas não padrão.
_full
Se true
, a constante FULL_BASE_URL será anexada aos URLs gerados
#
Permite definir fragmentos de hash de URL.
_https
Defina como true
para converter o URL gerado em https ou false
para forçar http.
_method
Defina o verbo/método HTTP a ser usado. Útil ao trabalhar com Criando rotas RESTful.
_name
Nome da rota. Se você configurou rotas nomeadas, poderá usar esta chave para especificá-la.
Configurando opções de rota
Há várias opções de rotas que podem ser definidas individualmente. Após conectar uma rota, você pode usar seus métodos fluentes do construtor para configurar ainda mais a rota. Esses métodos substituem muitas das chaves no parâmetro $options
de connect()
:
$routes->connect(
'/:lang/articles/:slug',
['controller' => 'Articles', 'action' => 'view'],
)
// Permite requisiçes GET e POSTS.
->setMethods(['GET', 'POST'])
// Corresponder apenas no subdomínio do blog.
->setHost('blog.example.com')
// Defina os elementos da rota que devem ser convertidos em argumentos passados
->setPass(['slug'])
// Definir os padrões correspondentes para elementos de rota
->setPatterns([
'slug' => '[a-z0-9-_]+',
'lang' => 'en|fr|es',
])
// Permitir também extensões de arquivo JSON
->setExtenions(['json'])
// Defina lang como um parâmetro persistente
->setPersist(['lang']);
Passando parâmetros para ação
Ao conectar rotas usando Elementos de Rota, você pode querer que elementos roteados sejam passados por argumentos. A opção pass
lista as permissões que elementos de rota também devem ser disponibilizados como argumentos passados para as funções do controlador:
// src/Controller/BlogsController.php
public function view($articleId = null, $slug = null)
{
// Algum código aqui...
}
// routes.php
Router::scope('/', function ($routes) {
$routes->connect(
'/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks
['controller' => 'Blogs', 'action' => 'view']
)
// Define os elementos da rota no modelo de rota
// para passar como argumentos de função. O pedido é importante,
// pois isso simplesmente mapeie ":id" para $articleId em sua ação
->setPass(['id', 'slug'])
// Define um padrão que o `id` deve corresponder.
->setPatterns([
'id' => '[0-9]+',
]);
});
Agora, graças aos recursos de roteamento reverso, você pode passar a matriz de URLs como abaixo e o CakePHP saberá como formar a URL conforme definido nas rotas:
// view.php
// Isso retornará um link para /blog/3-CakePHP_Rocks
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
'id' => 3,
'slug' => 'CakePHP_Rocks'
]);
// Você também pode usar parâmetros indexados numericamente.
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
3,
'CakePHP_Rocks'
]);
Usando Rotas Nomeadas
Às vezes, você encontrará a digitação de todos os parâmetros de URL de uma rota muito detalhados ou gostaria de aproveitar as melhorias de desempenho que as rotas nomeadas possuem. Ao conectar rotas, você pode especificar uma opção _name
, essa opção pode ser usada no roteamento reverso para identificar a rota que você deseja usar:
// Conecte uma rota com um nome.
$routes->connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
// Nomear uma rota específica do verbo (3.5.0+)
$routes->post(
'/logout',
['controller' => 'Users', 'action' => 'logout'],
'logout'
);
// Gere um URL usando uma rota nomeada.
$url = Router::url(['_name' => 'logout']);
// Gere um URL usando uma rota nomeada,
// com algumas cadeias de caracteres de consulta args.
$url = Router::url(['_name' => 'login', 'username' => 'jimmy']);
Se o seu modelo de rota contiver elementos de rota como :controller
, você precisará
fornecê-los como parte das opções para Router::url()
.
Nota
Os nomes das rotas devem ser exclusivos em todo o aplicativo. O mesmo
_name
não pode ser usado duas vezes, mesmo que os nomes ocorram dentro de um
escopo de roteamento diferente.
Ao criar rotas nomeadas, você provavelmente desejará seguir algumas convenções para
os nomes das rotas. O CakePHP facilita a criação de nomes de rotas, permitindo definir
prefixos de nomes em cada escopo:
Router::scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// O nome desta rota será `api:ping`
$routes->get('/ping', ['controller' => 'Pings'], 'ping');
});
// Gere uma URL para a rota de ping
Router::url(['_name' => 'api:ping']);
// Use namePrefix com plugin()
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
// Conecta rotas.
});
// Ou com prefix()
Router::prefix('Admin', ['_namePrefix' => 'admin:'], function ($routes) {
// Conecta rotas.
});
Você também pode usar a opção _namePrefix
dentro de escopos aninhados e funciona
conforme o esperado:
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
$routes->scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// O nome desta rota será `contacts:api:ping`
$routes->get('/ping', ['controller' => 'Pings'], 'ping');
});
});
// Gere uma URL para a rota de ping
Router::url(['_name' => 'contacts:api:ping']);
As rotas conectadas nos escopos nomeados somente terão nomes adicionados se a rota também
for nomeada. As rotas sem nome não terão o _namePrefix
aplicado a elas.
Prefix Routing
-
static Cake\Routing\Router::prefix($name, $callback)
Muitos aplicativos requerem uma seção de administração na qual usuários privilegiados
podem fazer alterações. Isso geralmente é feito por meio de uma URL especial, como
/admin/users/edit/5
. No CakePHP, o roteamento de prefixo pode ser ativado usando
o método de escopo prefix
:
use Cake\Routing\Route\DashedRoute;
Router::prefix('Admin', function ($routes) {
// Todas as rotas aqui serão prefixadas com `/admin`. Também
// será adicionado o elemento de rota `'prefix' => 'Admin'`,
// que será necessário ao gerar URLs para essas rotas
$routes->fallbacks(DashedRoute::class);
});
Os prefixos são mapeados para sub-namespaces no namespace Controller
do seu aplicativo.
Por ter prefixos como controladores separados, você pode criar controladores menores e
mais simples. O comportamento comum aos controladores prefixados e não prefixados pode
ser encapsulado usando herança, Componentes ou traits. Usando o exemplo
de nossos usuários, acessar a URL /admin/users/edit/5
chamaria o método edit()
do nosso
src/Controller/Admin/UsersController.php passando 5 como o primeiro parâmetro. O arquivo
de visualização usado seria templates/Admin/Users/edit.php.
Você pode mapear a URL /admin para sua ação index()
do controlador de páginas usando a seguinte rota:
Router::prefix('Admin', function ($routes) {
// Como você está no escopo do administrador,
// não é necessário incluir o prefixo /admin
// ou o elemento de rota do administrador.
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
});
Ao criar rotas de prefixo, você pode definir parâmetros de rota adicionais usando o argumento $options
:
Router::prefix('Admin', ['param' => 'value'], function ($routes) {
// As rotas conectadas aqui são prefixadas com '/admin' e
// têm a chave de roteamento 'param' definida.
$routes->connect('/:controller');
});
Os prefixos de várias palavras são convertidos por padrão usando inflexão dasherize,
ou seja, MyPrefix
seria mapeado para my-prefix
na URL. Certifique-se de definir
um caminho para esses prefixos se você quiser usar um formato diferente, como por
exemplo, sublinhado:
Router::prefix('MyPrefix', ['path' => '/my_prefix'], function (RouteBuilder $routes) {
// As rotas conectadas aqui são prefixadas com '/my_prefix'
$routes->connect('/:controller');
});
Você também pode definir prefixos dentro dos escopos de plugins:
Router::plugin('DebugKit', function ($routes) {
$routes->prefix('Admin', function ($routes) {
$routes->connect('/:controller');
});
});
O exemplo acima criaria um modelo de rota como /debug_kit/admin/:controller
. A rota
conectada teria os elementos de rota plugin
e prefix
definidos.
Ao definir prefixos, você pode aninhar vários prefixos, se necessário:
Router::prefix('Manager', function ($routes) {
$routes->prefix('Admin', function ($routes) {
$routes->connect('/:controller/:action');
});
});
O exemplo acima, criaria um modelo de rota como /manager/admin/:controller/:action
.
A rota conectada teria o elemento de rota prefix
configurado como Manager/Admin
.
O prefixo atual estará disponível nos métodos do controlador através de
$this->request->getParam('prefix')
.
Ao usar rotas de prefixo, é importante definir a opção prefix
e usar o mesmo
formato de camelo que é usado no método prefix()
. Veja como criar esse link
usando o HTML Helper:
// Entre em uma rota prefixada.
echo $this->Html->link(
'Manage articles',
['prefix' => 'Manager/Admin', 'controller' => 'Articles', 'action' => 'add']
);
// Deixe um prefixo
echo $this->Html->link(
'View Post',
['prefix' => false, 'controller' => 'Articles', 'action' => 'view', 5]
);
Nota
Você deve conectar rotas de prefixo antes de conectar rotas de fallback.
Criando links para rotas de prefixo
Você pode criar links que apontam para um prefixo, adicionando a chave de prefixo
à sua matriz de URL:
echo $this->Html->link(
'New admin todo',
['prefix' => 'Admin', 'controller' => 'TodoItems', 'action' => 'create']
);
Ao usar o aninhamento, você precisa encadeá-los:
echo $this->Html->link(
'New todo',
['prefix' => 'Admin/MyPrefix', 'controller' => 'TodoItems', 'action' => 'create']
);
Isso vincularia a um controlador com o namespace App\\Controller\\Admin\\MyPrefix
e o caminho do arquivo src/Controller/Admin/MyPrefix/TodoItemsController.php
.
Nota
O prefixo é sempre camel case aqui, mesmo que o resultado do roteamento seja
tracejado. A própria rota fará a inflexão, se necessário.
Roteamento de Plugins
-
static Cake\Routing\Router::plugin($name, $options = [], $callback)
As rotas para Plugins devem ser criadas usando o método plugin()
. Este
método cria um novo escopo de roteamento para as rotas do plugin:
Router::plugin('DebugKit', function ($routes) {
// As rotas conectadas aqui são prefixadas com '/debug_kit' e
// têm o elemento de rota do plug-in definido como 'DebugKit'.
$routes->connect('/:controller');
});
Ao criar escopos de plug-in, você pode personalizar o caminho usando a opção path
:
Router::plugin('DebugKit', ['path' => '/debugger'], function ($routes) {
// As rotas conectadas aqui são prefixadas com '/debug_kit' e
// têm o elemento de rota do plug-in definido como 'DebugKit'.
$routes->connect('/:controller');
});
Ao usar escopos, você pode aninhar escopos de plug-ins dentro de escopos de prefixo:
Router::prefix('Admin', function ($routes) {
$routes->plugin('DebugKit', function ($routes) {
$routes->connect('/:controller');
});
});
O exemplo acima criaria uma rota parecida com /admin/debug_kit/:controller
. Teria o
conjunto de elementos de rota prefix
e plugin
. A seção Rotas para Plugin
possui mais informações sobre a construção de rotas para plugins.
Criando links para rotas de plugins
Você pode criar links que apontam para um plug-in, adicionando a chave do plug-in a seu array de URL:
echo $this->Html->link(
'New todo',
['plugin' => 'Todo', 'controller' => 'TodoItems', 'action' => 'create']
);
Por outro lado, se a solicitação ativa for uma solicitação de plug-in e você desejar
criar um link que não possua plug-in, faça o seguinte:
echo $this->Html->link(
'New todo',
['plugin' => null, 'controller' => 'Users', 'action' => 'profile']
);
Ao definir 'plugin' => null
, você diz ao roteador que deseja criar um link que não faça parte de um plug-in.
Roteamento otimizado para SEO
Alguns desenvolvedores preferem usar hífens nos URLs, pois é percebido que eles fornecem
melhores classificações nos mecanismos de pesquisa. A classe DashedRoute
pode ser
usada em seu aplicativo com a capacidade de rotear nomes de plugins, controladores e
ações «camelizadas» para uma URL tracejada.
Por exemplo, se tivéssemos um plugin ToDo
, com um controlador TodoItems
e uma
ação showItems()
, ele poderia ser acessado em /to-do/todo-items/show-items
com a seguinte conexão do roteador:
use Cake\Routing\Route\DashedRoute;
Router::plugin('ToDo', ['path' => 'to-do'], function ($routes) {
$routes->fallbacks(DashedRoute::class);
});
Correspondendo a métodos HTTP específicos
As rotas podem corresponder a métodos HTTP específicos usando os métodos auxiliares de verbo HTTP:
Router::scope('/', function($routes) {
// Esta rota corresponde apenas às solicitações POST.
$routes->post(
'/reviews/start',
['controller' => 'Reviews', 'action' => 'start']
);
// Corresponder vários verbos
// Antes do 3.5, use $options['_method'] para definir o método
$routes->connect(
'/reviews/start',
[
'controller' => 'Reviews',
'action' => 'start',
]
)->setMethods(['POST', 'PUT']);
});
Você pode combinar vários métodos HTTP usando uma matriz. Como o parâmetro _method
é
uma chave de roteamento, ele participa da análise e geração de URLs. Para gerar URLs para
rotas específicas de métodos, você precisará incluir a chave _method
ao gerar a URL:
$url = Router::url([
'controller' => 'Reviews',
'action' => 'start',
'_method' => 'POST',
]);
Nomes de host específicos correspondentes
As rotas podem usar a opção _host
para corresponder apenas a hosts específicos. Você
pode usar o curinga *.
para corresponder a qualquer subdomínio:
Router::scope('/', function($routes) {
// Esta rota corresponde apenas a http://images.example.com
// Antes da versão 3.5, use a opção _host
$routes->connect(
'/images/default-logo.png',
['controller' => 'Images', 'action' => 'default']
)->setHost('images.example.com');
// Esta rota corresponde apenas a http://*.example.com
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo']
)->setHost('*.example.com');
});
A opção _host
também é usada na geração de URL. Se a opção _host
especificar um
domínio exato, esse domínio será incluído no URL gerado. No entanto, se você usar um
curinga, precisará fornecer o parâmetro _host
ao gerar URLs:
// Se você tem esta rota
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo']
)->setHost('images.example.com');
// Você precisa disso para gerar um URL
echo Router::url([
'controller' => 'Images',
'action' => 'oldLogo',
'_host' => 'images.example.com',
]);
Extensões de arquivo de roteamento
-
static Cake\Routing\Router::extensions(string|array|null $extensions, $merge = true)
Para lidar com diferentes extensões de arquivo com suas rotas, você pode definir extensões
em nível global e de escopo. A definição de extensões globais
pode ser obtida através do método estático Router::extensions()
dos roteadores:
Router::extensions(['json', 'xml']);
// ...
Isso afetará todas as rotas que serão conectadas posteriormente, independentemente do seu escopo.
Para restringir extensões a escopos específicos, você pode defini-las usando o método
Cake\Routing\RouteBuilder::setExtensions()
:
Router::scope('/', function ($routes) {
// Prior to 3.5.0 use `extensions()`
$routes->setExtensions(['json', 'xml']);
});
Isso habilitará as extensões nomeadas para todas as rotas que estão sendo conectadas esse escopo
após a chamada de setExtensions()
, incluindo aqueles que estão sendo conectado em escopos
aninhados. Semelhante ao método global Router::extensions()
,
quaisquer rotas conectadas antes da chamada não herdarão as extensões.
Nota
A configuração das extensões deve ser a primeira coisa que você faz em um escopo, pois as extensões
serão aplicadas apenas às rotas conectadas depois que as extensões forem definidas.
Lembre-se também de que escopos reabertos não herdarão extensões definidas em escopos abertos anteriormente.
Ao usar extensões, você diz ao roteador para remover as extensões de arquivo correspondentes e analisar o que resta.
Se você deseja criar uma URL como /page/title-of-page.html, crie sua rota usando:
Router::scope('/page', function ($routes) {
// Antes de 3.5.0 use `extensions()`
$routes->setExtensions(['json', 'xml', 'html']);
$routes->connect(
'/:title',
['controller' => 'Pages', 'action' => 'view']
)->setPass(['title']);
});
Para criar links que mapeiam de volta para as rotas, basta usar:
$this->Html->link(
'Link title',
['controller' => 'Pages', 'action' => 'view', 'title' => 'super-article', '_ext' => 'html']
);
As extensões de arquivo são usadas por Request Handler (Tratamento de Requisições) para fazer a troca
automática de exibição com base nos tipos de conteúdo.
Agrupando Middlewares
Para ajudar a manter o seu código de rota DRY o middleware pode ser combinado em grupos.
Uma vez que grupos combinados podem ser aplicados, como o middleware:
$routes->registerMiddleware('cookie', new EncryptedCookieMiddleware());
$routes->registerMiddleware('auth', new AuthenticationMiddleware());
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->middlewareGroup('web', ['cookie', 'auth', 'csrf']);
// Aplica o grupo
$routes->applyMiddleware('web');
Criando rotas RESTful
O controle de rotas facilita a geração de rotas RESTful para seus controllers. Repousante as rotas são úteis quando você
está criando pontos finais da API para sua aplicação. E se queríamos permitir acesso REST a um controlador de receita,
faríamos algo como esta:
// no arquivo config/routes.php...
Router::scope('/', function ($routes) {
// anterior a versao 3.5.0 usar `extensions()`
$routes->setExtensions(['json']);
$routes->resources('Recipes');
});
A primeira linha configura uma série de rotas padrão para REST, de fácil acesso onde o método especifica o formato de resultado
desejado (por exemplo, xml, json, rss). Essas rotas são sensíveis ao método de solicitação HTTP.
HTTP format |
URL.format |
Controller action invoked |
GET |
/recipes.format |
RecipesController::index() |
GET |
/recipes/123.format |
RecipesController::view(123) |
POST |
/recipes.format |
RecipesController::add() |
PUT |
/recipes/123.format |
RecipesController::edit(123) |
PATCH |
/recipes/123.format |
RecipesController::edit(123) |
DELETE |
/recipes/123.format |
RecipesController::delete(123) |
A classe CakePHP Router usa uma série de indicadores diferentes para detectar o método HTTP que está sendo usado.
Aqui estão em ordem de preferência:
A váriavel _method
POST
O X_HTTP_METHOD_OVERRIDE
O cabeçalho REQUEST_METHOD
A váriavel _method
POST é útil na quando há um navegador como cliente REST (ou qualquer outra coisa que possa fazer POST).
Basta definir o valor do \_method
para o nome do método de solicitação HTTP que você deseja emular.
Criando rotas de recursos aninhados
Depois de conectar recursos em um escopo, você também pode conectar rotas para sub-recursos. As rotas de sub-recursos serão
precedidas pelo nome do recurso original e um parâmetro id
. Por exemplo:
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments');
});
});
Irá gerar rotas de recursos para articles
e comments
. As rotas de comentários terão a aparência de:
/api/articles/:article_id/comments
/api/articles/:article_id/comments/:id
Você pode obter o article_id
em CommentsController
por:
$this->request->getParam('article_id');
Por padrão, as rotas de recursos são mapeadas para o mesmo prefixo que o escopo que contém. Se você tiver controladores
de recursos aninhados e não aninhados, poderá usar um controlador diferente em cada contexto usando prefixos:
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments', ['prefix' => 'Articles']);
});
});
A descrição acima mapeia o recurso “Comments” para App\Controller\Articles\CommentsController
. Ter controladores
separados permite manter a lógica do controlador mais simples. Os prefixos criados dessa maneira são compatíveis com
Prefix Routing.
Nota
Embora você possa aninhar recursos tão profundamente quanto necessário, não é recomendável
aninhar mais de 2 recursos juntos.
Limitando as rotas criadas
Por padrão, o CakePHP conectará seis rotas para cada recurso. Se você deseja conectar apenas rotas de recursos
específicos, use a opção only
:
$routes->resources('Articles', [
'only' => ['index', 'view']
]);
Criaria rotas de recurso somente leitura. Os nomes das rotas são create
,
update
, view
, index
e delete
Alterando as ações usadas no controlador
Pode ser necessário alterar os nomes de ação do controlador usados ao conectar rotas. Por exemplo,
se sua ação edit()
é chamada put()
, você pode usar a chave actions
para renomear as ações usadas:
$routes->resources('Articles', [
'actions' => ['update' => 'put', 'create' => 'add']
]);
O exemplo acima usaria put()
para a ação edit()
e add()
em vez de create()
.
Mapeando rotas de recursos adicionais
Você pode mapear métodos de recursos adicionais usando a opção map
:
$routes->resources('Articles', [
'map' => [
'deleteAll' => [
'action' => 'deleteAll',
'method' => 'DELETE'
]
]
]);
// Isso conectaria a /articles/deleteAll
Além das rotas padrão, isso também conectaria uma rota para /articles/delete_all. Por padrão, o
segmento do caminho corresponderá ao nome da chave. Você pode usar a chave “path” dentro da definição
de recurso para personalizar o nome do caminho:
$routes->resources('Articles', [
'map' => [
'updateAll' => [
'action' => 'updateAll',
'method' => 'DELETE',
'path' => '/update_many'
],
]
]);
// Isso conectaria a /articles/update_many
Se você definir “only” e “map”, verifique se seus métodos mapeados também estão na lista “only”.
Classes de rota personalizadas para rotas de recursos
Você pode fornecer a chave connectOptions
na matriz $options
para resources()
para
fornecer configurações personalizadas usadas por connect()
:
Router::scope('/', function ($routes) {
$routes->resources('Books', [
'connectOptions' => [
'routeClass' => 'ApiRoute',
]
];
});
Inflexão de URL para rotas de recursos
Por padrão, os fragmentos de URL dos controladores com várias palavras são a forma sublinhada do nome do
controlador. Por exemplo, fragmento de URL do BlogPostsController
seria /blog_posts.
Você pode especificar um tipo de inflexão alternativo usando a opção inflect
:
Router::scope('/', function ($routes) {
$routes->resources('BlogPosts', [
'inflect' => 'dasherize' // Will use ``Inflector::dasherize()``
]);
});
O exemplo acima irá gerar URLs com estilo semelhantes a: /blog-posts.
Nota
A partir do CakePHP 3.1, o esqueleto oficial do aplicativo usa DashedRoute
como sua classe de
rota padrão. Recomenda-se o uso da opção 'inflect' => 'dasherize'
ao conectar rotas de recursos
para garantir a consistência da URL
Alterando o elemento de caminho
Por padrão, as rotas de recursos usam um formulário flexionado do nome do recurso para o segmento de URL.
Você pode definir um segmento de URL personalizado com a opção path
:
Router::scope('/', function ($routes) {
$routes->resources('BlogPosts', ['path' => 'posts']);
});