I'm having the same problem symfony2 is describing here
This comes in handy when you have a bundle but don't want to manually
add the routes for the bundle to app/config/routing.yml. This may be
especially important when you want to make the bundle reusable
TLDR; im trying to implement a custom Route Loader using this part of the symfony2 documentation
http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html#more-advanced-loaders
However it doesn't seem to be working, the route cannot be found;
This is what I've tried so far:
The loader:
<?php
//namespace Acme\DemoBundle\Routing;
namespace Gabriel\AdminPanelBundle\Routing;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\RouteCollection;
class AdvancedLoader extends Loader
{
public function load($resource, $type = null)
{
$collection = new RouteCollection();
$resource = '#GabrielAdminPanelBundle/Resources/config/routing.yml';
$type = 'yaml';
$importedRoutes = $this->import($resource, $type);
$collection->addCollection($importedRoutes);
return $collection;
}
public function supports($resource, $type = null)
{
return $type === 'advanced_extra';
}
}
here is my routing.yml
located in: src/Gabriel/AdminPanelBundle/Resources/config/routing.yml
the routing.yml
gabriel_admin_panel:
resource: "#GabrielAdminPanelBundle/Controller/"
type: annotation
prefix: /superuser
The Routes of the bundle can't be found unless I put the Routes back in the main app/config/routing.yml file, how to fix this?
Edit:
FileLoaderImportCircularReferenceException: Circular reference
detected in "/app/config/routing_dev.yml"
("/app/config/routing_dev.yml" > "/app/config/routing.yml" > "." >
"#GabrielAdminPanelBundle/Controller/" >
"/app/config/routing_dev.yml").
You must also configure service
# src/Gabriel/AdminPanelBundle/Resources/config/services.yml
your_bundle.routing_loader:
class: Gabriel\AdminPanelBundle\Routing\AdvancedLoader
tags:
- { name: routing.loader }
And routing file
# app/config/routing.yml
YourBundle_extra:
resource: .
type: advanced_extra
Related
No route found for "GET http://pogodynka.localhost:46530/weather"
This is the error I get when I try to access:
http://pogodynka.localhost:46530/weather
config/Routes.yaml
weather_in_city:
path: /weather/{country}/{cityName}
controller: App\Controller\WeatherController:cityAction
requirements:
city: \d+
config/packages/Routing.yaml
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
when#prod:
framework:
router:
strict_requirements: null
src/Controller/WeatherController.php
namespace App\Controller;
use App\Entity\Location;
use App\Repository\MeasurementRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class WeatherController extends AbstractController
{
public function cityAction($cityName, MeasurementRepository $measurementRepository, CityRepository $cityRepository): Response
{
$cities = $cityRepository->findCityByName($cityName);
$city = $cities[0];
$measurements = $measurementRepository->findByLocation($cityName);
return $this->render('weather/city.html.twig', [
'location' => $city,
'measurements' => $measurements,
]);
}
}
debug:router
You should use route annotations. This way you can define the route directly in the controller class. Here is a nice write up and example: SymfonyCasts: Annotation & Wildcard Routes
My personal opinion but I find annotations to be the way to go.
I'm trying to implement the LegacyController that is listed on the Symfony documentation https://symfony.com/doc/current/migration.html#legacy-route-loader
Using the custom loader configs for services and routes from:
https://symfony.com/doc/current/routing/custom_route_loader.html#creating-a-custom-loader
I wish there was a complete working example listed somewhere.
When I try to run the debug:router or composer:install I just get an error. This after trying various slight variations on this initial config.
$ console debug:router
In FileLoader.php line 166:
Invalid service id: "App\Legacy\LegacyRouteLoader\" in /var/www/site/config/services.yaml (which is loaded in resource "/var/www/site/config/services.yaml").
In ContainerBuilder.php line 991:
Invalid service id: "App\Legacy\LegacyRouteLoader\"
--
<?php
// src/Legacy/LegacyRouteLoader.php
namespace App\Legacy;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class LegacyRouteLoader extends Loader
{
public function supports($resource, $type = null)
{
return 'extra' === $type;
}
public function load($resource, $type = null)
{
$collection = new RouteCollection();
$finder = new Finder();
$finder->files()->name('*.php');
/** #var SplFileInfo $legacyScriptFile */
foreach ($finder->in($this->webDir) as $legacyScriptFile) {
// This assumes all legacy files use ".php" as extension
$filename = basename($legacyScriptFile->getRelativePathname(), '.php');
$routeName = sprintf('app.legacy.%s', str_replace('/', '__', $filename));
$collection->add($routeName, new Route($legacyScriptFile->getRelativePathname(), [
'_controller' => 'App\Controller\LegacyController::loadLegacyScript',
'requestPath' => '/' . $legacyScriptFile->getRelativePathname(),
'legacyScript' => $legacyScriptFile->getPathname(),
]));
}
return $collection;
}
}
--
<?php
// src/Controller/LegacyController.php
namespace App\Controller;
use Symfony\Component\HttpFoundation\StreamedResponse;
class LegacyController
{
public function loadLegacyScript(string $requestPath, string $legacyScript)
{
return StreamedResponse::create(
function () use ($requestPath, $legacyScript) {
$_SERVER['PHP_SELF'] = $requestPath;
$_SERVER['SCRIPT_NAME'] = $requestPath;
$_SERVER['SCRIPT_FILENAME'] = $legacyScript;
chdir(dirname($legacyScript));
include $legacyScript;
}
);
}
}
--
# config/services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
App\Legacy\LegacyRouteLoader\:
tags: ['routing.loader']
--
# config/routes.yaml
#index:
# path: /
# controller: App\Controller\DefaultController::index
app_legacy:
resource: .
type: extra
Thanks to #cerad above, I managed to get it going with some changes.
# config/services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
App\Legacy\LegacyRouteLoader:
tags: ['routing.loader']
--
<?php
// src/Legacy/LegacyRouteLoader.php
namespace App\Legacy;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class LegacyRouteLoader extends Loader
{
private $webDir = __DIR__.'/../../public/';
public function supports($resource, $type = null)
{
return 'extra' === $type;
}
public function load($resource, $type = null)
{
$collection = new RouteCollection();
$finder = new Finder();
$finder->files()->name('*.php');
/** #var SplFileInfo $legacyScriptFile */
foreach ($finder->in($this->webDir) as $legacyScriptFile) {
// This assumes all legacy files use ".php" as extension
$filename = basename($legacyScriptFile->getRelativePathname(), '.php');
$routeName = sprintf('app.legacy.%s', str_replace('/', '__', $filename));
$collection->add($routeName, new Route($legacyScriptFile->getRelativePathname(), [
'_controller' => 'App\Controller\LegacyController::loadLegacyScript',
'requestPath' => '/' . $legacyScriptFile->getRelativePathname(),
'legacyScript' => $legacyScriptFile->getPathname(),
]));
}
return $collection;
}
}
I have mvc php cms like this folder structure:
application
---admin
--------controller
--------model
--------view
--------language
---catalog
--------controller
------------------IndexController.php
--------model
--------view
--------language
core
--------controller.php
//...more
public
--------index.php
vendor
I install symfony/router component for help my route url using composer json:
{
"autoload": {
"psr-4": {"App\\": "application/"}
},
"require-dev":{
"symfony/routing" : "*"
}
}
Now with route documents I add this code for routing in index.php:
require '../vendor/autoload.php';
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$route = new Route('/index', array('_controller' => 'App\Catalog\Controller\IndexController\index'));
$routes = new RouteCollection();
$routes->add('route_name', $route);
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/index');
In My IndexController I have :
namespace App\Catalog\Controller;
class IndexController {
public function __construct()
{
echo 'Construct';
}
public function index(){
echo'Im here';
}
}
Now in Action I work in this url: localhost:8888/mvc/index and can't see result : Im here IndexController.
How do symfony routing url work and find controller in my mvc structure? thank for any practice And Help.
The request context should be populated with the actual URI that's hitting the application. Instead of trying to do this yourself you can use the HTTP Foundation package from symfony to populate this:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContext;
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
It's also documented here: https://symfony.com/doc/current/components/routing.html#components-routing-http-foundation
After the matching ($parameters = $matcher->match('/index');) you can use the _controller key of the parameters to instantiate the controller and dispatch the action. My suggestion would be to replace the last \ with a different symbol for easy splitting, like App\Controller\Something::index.
You can then do the following:
list($controllerClassName, $action) = explode($parameters['_controller']);
$controller = new $controllerClassName();
$controller->{$action}();
Which should echo the response you have in your controller class.
I created a EventListener to set the locale based on the user preferences, i set the langage like this in my listener:
$request->setLocale($user->getLanguage());
$request->getSession()->set('_locale',$user->getLanguage());
I tried both..
I register the Listener in the service.yml:
app.event_listener.locale:
class: 'AppBundle\EventListener\LocaleListener'
arguments:
- '#security.token_storage'
tags:
- {name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest'}
I also tried to add a priority: 17 to the service but it does not change anything...
The listener seems to works, i can get the Locale in my controller with a $request->getLocale()(or session).
But Twig is still in the default language I defined in the config.yml:
parameters:
locale: fr
I'm pretty lost now, any tips ?
I tried a lot of stuff (change the priority, check if the locale is passed to the front etc...)
Finally i forced the translator in my EventListener:
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if ($this->tokenStorage->getToken()) {
$user = $this->tokenStorage->getToken()->getUser();
if ($user && $user instanceof User) {
$request->setLocale($user->getLanguage());
} elseif ($request->query->has('locale')) {
$request->setLocale($request->query->get('locale'));
} else {
$request->setLocale($request->getPreferredLanguage());
}
}
$this->translator->setLocale($request->getLocale());
}
I don't understand why, this should be done in the Symfony translator, but it works...
You have to set the locale for the translator to get the right translation in templates.
E.g in controller:
$this->get('translator')->setLocale($user->getLanguage());
I'm trying to write a symfony 2 functional test. This is my code:
<?php
namespace WebSite\MainBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class ProductControllerTest extends WebTestCase
{
public function testPageContents()
{
$domCategoryLinksExpr = '.catalog-col-block > ul > li > a';
$client = static::createClient();
$crawler = $client->request('GET', '/catalog/');
$this->assertTrue($client->getResponse()->getStatusCode() == '200');
$countCategories = $crawler->filter($domCategoryLinksExpr)->count();
$this->assertTrue($crawler->filter($domCategoryLinksExpr)->count() > 0);
$categoryLink = $crawler->filter($domCategoryLinksExpr)->eq(rand(1, $countCategories))->link();
$crawler = $client->click($categoryLink);
}
}
But when i run this test:
phpunit -c app src/WebSite/MainBundle/Tests/Controller/
I got this:
1) WebSite\MainBundle\Tests\Controller\ProductControllerTest::testPageContents
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for "GET /app_dev.php/catalog/psp"
...
/app_dev.php/catalog/psp is the dynamic value of $categoryLink->getUri(). And
this route exists and correctly works in web browser. Any ideas?
UPD:
This is my routing rules:
routing_dev.yml:
...
_main:
resource: routing.yml
....
routing.yml:
....
WebSiteCategoryBundle:
resource: "#WebSiteCategoryBundle/Controller/"
type: annotation
prefix: /
....
src/WebSite/CategoryBundle/CategoryController.php:
/**
* #Route("/catalog")
*/
class CategoryController extends Controller
{
/**
* #Route("/{alias}", name="show_category" )
* #Template()
*/
public function showAction( $alias )
{
// some action here
}
}
It works fine in browser, but seems like $crowler does`not see this annotation rules.
UPD2: The problem was in "routing_test.yml" which missing in Symfony 2 standard edition.
So I create it:
routing_test.yml:
_main:
resource: routing_dev.yml
and exception disappear. Thanks to all.
It would be nice if you posted your routing.yml
You can also take a look at:
http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/annotations/routing.html
You can use routing annotation at your actions.
To solve your problem I would like to see your routing config.
echo $client->getResponse()->getContent() will help you with debugging (even there is an exception). It will output html of the request.
It looks like your route does not exist and might be in wrong location (wrong environment specified?)