Is it possible in Symfony 4 to set the routing name trough yaml.
So old annotation
/**
* #Route("/cms", name="security_login")
*/
public function loginAction(Request $request, AuthenticationUtils $authenticationUtils) {
// code here
}
Yaml annotation
login:
path: /cms
controller: App\Controller\SecurityController::loginAction
name: security_login
It looks like yaml doesn't support the name key. only the following keys are supported:
"resource", "type", "prefix", "path", "host", "schemes", "methods", "defaults", "requirements", "options", "condition", "controller".
or is the key 'login' the name?
Yes, the "login" key in your file is the route's name.
Click on the "YAML" tabs in the documentation to see yaml examples :
# config/routes.yaml
blog_list:
path: /blog
controller: App\Controller\BlogController::list
blog_show:
path: /blog/{slug}
controller: App\Controller\BlogController::show
Corresponds to these annotations :
/**
* Matches /blog exactly
* #Route("/blog", name="blog_list")
*/
public function list()
{
// ...
}
/**
* Matches /blog/*
* #Route("/blog/{slug}", name="blog_show")
*/
public function show($slug)
{
// ...
}
The name is specified in the yaml entry ...
security_login:
path: /cms
controller: App\Controller\SecurityController::loginAction
Related
I want to open my websites like these:
http://127.0.0.1:8000/ (Works)
http://127.0.0.1:8000/en/ (Works)
http://127.0.0.1:8000/en/mrg (Works)
http://127.0.0.1:8000/mrg (Doesn't Work)
So I put this code in routing.yml:
teach:
resource: "#TeachBundle/Controller/"
type: annotation
prefix: /{_locale}
requirements:
_locale: "|en|fa"
and my controller is like this:
/**
* #Route("/mrg")
*/
public function mrgAction(Request $request)
{
$lang=$request->getLocale();
return new Response("<html><body>Your language: <b> $lang </b></body></html>");
}
All urls worked but http://127.0.0.1:8000/mrg doesn't work and returns:
No route found for "GET /mrg"
I need use default language for example if I try to open http://127.0.0.1:8000/mrg then open http://127.0.0.1:8000/en/mrg.
Is there any solution to fix this problem?
Add defaults option to your routing configuration to set the default locale if it's not set in your controllers #Routes:
teach:
resource: "#TeachBundle/Controller/"
type: annotation
prefix: /{_locale}
requirements:
_locale: "|en|fa"
defaults:
_locale: 'en' # or '%locale%'
Try this:
{_locale}
/**
* #Route("/{_locale}/mrg")
*/
public function mrgAction(Request $request)
{
$lang=$request->getLocale();
return new Response("<html><body>Your language: <b> $lang </b></body></html>");
}
Setting a Default Locale
# app/config/config.yml
framework:
default_locale: en
If doesn't work, Can You show your app/config/routing.yml.
I advice you to use : BeSimpleI18nRoutingBundle
https://github.com/BeSimple/BeSimpleI18nRoutingBundle
use BeSimple\I18nRoutingBundle\Routing\Annotation\I18nRoute;
class NoPrefixController
{
/**
* #I18nRoute({ "en": "/welcome", "fr": "/bienvenue", "de": "/willkommen" }, name="homepage")
*/
public function indexAction() { }
}
Here is the scheme of the required URLs:
/service/getBalance should map to CustomerController::getBalance
/service/addBalance should map to CustomerController::addBalance
/customer/getBalance should map to CustomerController::getBalance
/customer/addBalance should map to CustomerController::addBalance
Here is a simple controller
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class CustomerController extends Controller {
/**
* #Route("/getBalance")
*/
public function getBalanceAction(Request $request) {
}
/**
* #Route("/addBalance")
*/
public function addBalanceAction(Request $request) {
}
} // class CustomerController
Have tried the following ways. None of them worked.
# rounting.yml
v1:
resource: "#AppBundle/Controller/CustomerController.php"
prefix: /service
type: annotation
v2:
resource: "#AppBundle/Controller/CustomerController.php"
prefix: /customer
type: annotation
loading the same resource with different prefix always overrides the previous occurrence (the last one works). The following also doesn't work for the same reason and have the same behavior.
# rounting.yml
v1:
resource: "#AppBundle/Resources/config/routing_customer.yml"
prefix: /service
v2:
resource: "#AppBundle/Resources/config/routing_customer.yml"
prefix: /customer
# routing_customer.yml
getBalance:
path: /getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
Third not working option:
# rounting.yml
v1:
resource: "#AppBundle/Resources/config/routing_v1.yml"
prefix: / # evenr putting /service here instead of inside
v2:
resource: "#AppBundle/Resources/config/routing_v2.yml"
prefix: / # evenr putting /customer here instead of inside
# routing_v1.yml
getBalance:
path: /service/getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /service/addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
# routing_v2.yml
getBalance:
path: /customer/getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /customer/addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
I actually need to route / and /customer to the same controller:
/getBalance and /customer/getBalance.
I want to give two prefixes for a group of methods. How to do that in Symfony?
Conclusion from my trials, #goto's answer and #Cerad's comments:
The last Example above could have worked if I used different route names. Route names are unique though out the whole project (Not just unique in file). v1_getBalance and v2_getBalance.
The other solution is to use a custom loader as #goto described.
You could do routes this way:
#Route(
"/{subject}/getBalance",
requirements={
"subject": "customer|service"
}
)
in yml:
subject_getbalance:
path: /{subject}/getBalance
requirements:
subject: customer|service
The requirement is safer than nothing: it allows you to route another route like foo/getBalance on another controller (as it does not match the requirement)
EDIT: for your special case, as you need /getBalance to map to your route too you could do:
subject_getbalance:
path: /{subject}/getBalance
default: { _controller: YourBundle:Controller }
requirements:
subject: customer|service
default_getbalance:
path: /getBalance
default: { _controller: YourBundle:Controller, subject: customer }
Edit: the last idea is to a custom route loader (but I've never tried):
class ExtraLoader extends Loader
{
public function load($resource, $type = null)
{
/* ... */
$prefixes = [ 'default_' =>'','customer_' =>'/customer','service_' =>'/service']
// prepare a new route
$path = '/getbalance/{parameter}';
$defaults = array(
'_controller' => 'YourBundle:Actiona',
);
$requirements = array(
'parameter' => '\d+',
);
foreach($prefixes as $prefixName => $prefixRoute) {
$route = new Route($prefixRoute . $path, $defaults, $requirements);
$routes->add($prefixName . 'getBalance', $route);
}
This will allows you to have 3 routes generated:
default_getBalance: /getBalance
customer_getBalance: /customer/getBalance
service_getBalance: /service/getBalance
I am using sylius v0.18. I want to prefix locale with product show urls.
sylius_core:
routing:
%sylius.model.product.class%:
field: slug
prefix: /p
defaults:
controller: sylius.controller.product:detailsAction
repository: sylius.repository.product
sylius:
template: SyliusWebBundle:Frontend/Product:show.html.twig
criteria: {slug: $slug}
permission: false
I can use a static word as the prefix in this configuration. but It does not work with _locale. prefix: /{_locale}/p
I found a solution, by overiding getRouteCollectionForRequest method in Sylius\Bundle\CoreBundle\Routing\RouteProvider class with the following configuration.
sylius_core:
routing:
%sylius.model.product.class%:
field: slug
prefix: /{_locale}/p
defaults:
controller: sylius.controller.product:detailsAction
repository: sylius.repository.product
sylius:
template: SyliusWebBundle:Frontend/Product:show.html.twig
criteria: {slug: $slug}
permission: false
parameters:
sylius.route_provider.class: App\AppBundle\Routing\Provider\RouteProvider
class RouteProvider extends BaseProvider
{
/**
* {#inheritdoc}
*/
public function getRouteCollectionForRequest(Request $request)
{
//Overide this method to match the url with _locale
}
I created a task link and a contextual one for base_route: entity.node.canonical
mymodule.routing.yml
mymodule.mycustomroute:
path: '/node/{node}/custom-path'
defaults:
_form: '\Drupal\mymodule\Form\MyForm'
requirements:
_permission: 'my permission'
node: '[0-9]+'
mymodule.links.tasks.yml
mymodule.mycustomroute:
route_name: mymodule.mycustomroute
base_route: entity.node.canonical
title: 'my title'
mymodule.links.contextual.yml
mymodule.mycustomroute:
route_name: mymodule.mycustomroute
group: node
My link shows up next to View / Edit / Delete links on each node as I wanted.
Now I am wondering how is it possible to make these links available only for specific node type(s)?
mymodule/mymodule.routing.yml :
mymodule.mycustomroute:
path: '/node/{node}/custom-path'
defaults:
_form: '\Drupal\mymodule\Form\MyForm'
requirements:
_permission: 'my permission'
_custom_access: '\Drupal\mymodule\Access\NodeTypeAccessCheck::access'
_node_types: 'node_type_1,node_type_2,node_type_n'
node: '\d+'
mymodule/src/Access/NodeTypeAccessCheck.php :
namespace Drupal\mymodule\Access;
use Drupal\Core\Access\AccessCheckInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\node\NodeInterface;
use Symfony\Component\Routing\Route;
/**
* Check the access to a node task based on the node type.
*/
class NodeTypeAccessCheck implements AccessCheckInterface {
/**
* {#inheritdoc}
*/
public function applies(Route $route) {
return NULL;
}
/**
* A custom access check.
*
* #param \Drupal\node\NodeInterface $node
* Run access checks for this node.
*/
public function access(Route $route, NodeInterface $node) {
if ($route->hasRequirement('_node_types')) {
$allowed_node_types = explode(',', $route->getRequirement('_node_types'));
if (in_array($node->getType(), $allowed_node_types)) {
return AccessResult::allowed();
}
}
return AccessResult::forbidden();
}
}
Or you can specify route parameters in the mymodule.links.menu.yml file:
mymodule.add_whatever:
title: 'Add whatever'
description: 'Add whatever'
route_name: node.add
route_parameters: { node_type: 'name_of_node_type' }
menu_name: main
weight: 7
acme_admin_dashboard:
pattern: /{_locale}/admin
defaults: { _controller: AcmeBundle:Admin:dashboard }
I want this route to be accessible at /en/admin and /en/admin/. How would I achieve this?
I like #Kuchengeschmack's answer (https://stackoverflow.com/a/11078348/593957) because it doesn't trigger external redirects.
Here's a yaml version:
acme_admin_dashboard:
pattern: /{_locale}/admin{trailingSlash}
defaults: { _controller: AcmeBundle:Admin:dashboard, trailingSlash : "/" }
requirements: { trailingSlash : "[/]{0,1}" }
Just type :
/**
* #Route("/route/of/some/page/")
*/
so
www.example.com/route/of/some/page
and
www.example.com/route/of/some/page/
are accepted...
I found a solution to add a trailing slash to a route.
means both link are working www.example.com/route/of/some/page and www.example.com/route/of/some/page/. You can do is this way:
if you route looks like
/**
* #Route("/route/of/some/page")
*/
public function pageAction() {
change ist to
/**
* #Route("/route/of/some/page{trailingSlash}", requirements={"trailingSlash" = "[/]{0,1}"}, defaults={"trailingSlash" = "/"})
*/
public function pageAction() {
You could also simply use rewrite rule in the .htaccess file:
Say you have defined a route like so:
news:
url: /news
param: { module: news, action: index }
This will be matched by http://something.something/news, but not by http://something.something/news/
You might add an additional route with a trailing slash, but you could also simply use this rewrite rule in the .htaccess file:
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
http://symfony-blog.driebit.nl/2010/07/url-routes-with-or-without-a-trailing-slash/
I hacked the following line into front controller (app.php / app_dev.php)
$_SERVER['REQUEST_URI'] = preg_replace('|/$|', '', $_SERVER['REQUEST_URI'], 1);
before $request = Request::createFromGlobals()
Route:
remove_trailing_slash:
path: /{url}
defaults: { _controller: AppBundle:Redirecting:removeTrailingSlash }
requirements:
url: .*/$
methods: [GET]
Controller:
// src/AppBundle/Controller/RedirectingController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class RedirectingController extends Controller
{
public function removeTrailingSlashAction(Request $request)
{
$pathInfo = $request->getPathInfo();
$requestUri = $request->getRequestUri();
$url = str_replace($pathInfo, rtrim($pathInfo, ' /'), $requestUri);
return $this->redirect($url, 301);
}
}
Read more: http://symfony.com/doc/current/routing/redirect_trailing_slash.html
For new SF versions:
By default, the Symfony Routing component requires that the parameters match the following regex path: [^/]+. This means that all characters are allowed except /.
You must explicitly allow / to be part of your parameter by specifying a more permissive regex path.
YAML:
_hello:
path: /hello/{username}
defaults: { _controller: AppBundle:Demo:hello }
requirements:
username: .+
XML:
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_hello" path="/hello/{username}">
<default key="_controller">AppBundle:Demo:hello</default>
<requirement key="username">.+</requirement>
</route>
</routes>
PHP:
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('_hello', new Route('/hello/{username}', array(
'_controller' => 'AppBundle:Demo:hello',
), array(
'username' => '.+',
)));
return $collection;
Annotations:
/**
* #Route("/hello/{username}", name="_hello", requirements={"username"=".+"})
*/
public function helloAction($username)
{
// ...
}