Symfony2 Routing within a bundle - php

I have a symfony project where i have seperated my code into two different bundles lets say HomeBundle and AppBundle however the routes are commonly accessible inside both bundle.
eg:- /home defined in HomeBundle can also be accessed from AppBundle
and
/App defined in AppBundle can also be accessed from HomeBundle
what i want is to access /home ONLY from HomeBundle and /App from Only AppBundle I'm looking for 'structuring' my code in a way where i dont have to write any logic to accomplish this, but instead leverage symfony frameworks structure to do this for me, something along the lines of restricting routing to only within the bundle, or some way where the route definition goes 'out of scope' when inside the wrong bundle
im using annotaions for routing, and defined in app/config/routing.yml
edit: the application requires subomain partitions so i'm also using this host/default with placeholder
any help would be appreciated :) thanks

Unfortunately this isn't going to be possible, primarily because of the architecture of Symfony bundles. While separating your code into bundles is good from a cognitive point of view, Symfony doesn't have the concept of being "in" a bundle; what code is run (specifically your controller actions) is usually handled by routes, and routes have to be compiled together from ALL bundles to ensure that a request can be routed successfully.
You would have to write extra code to accomplish what you're asking - my initial thought would be your own Controller class (maybe extending from FrameworkBundle\Controller\Controller) that ran some code before a request (see documentation that may achieve this).
Fundamentally this is an architectural decision for you and my question would be - why do you not want to be able to access /home from the AppBundle? Would a security / role set up work as well or are you trying to sandbox code?
EDIT After some further detail, it turns out that the requirement is for two different actions for the same URL path (e.g. /home) but on different domains e.g. www.example.com/home and subdomain.example.com/home. In this instance it wasn't about code sharing but URLs so Symfony's host/domain based routing solution worked.

I was under the assumption that business logic inside bundles are isolated and would not be 'aware' of routes defined inside other bundles, turns out the routes are globally available to all bundles, i wanted to use the framework of symfony to achieve what i asked for, it happens so there is no way to do it. i probably should use Listeners or before filters etc to achieve this. John Noel answered this.
Luckily for me, the bundles happen to operate on separate Domains (one on the main domain and the other on the subdomain) i noticed this after a chat with #John Noel he suggested matching the Route Based on the Host/Domain. i had this in place previously, upon a second look i figured out i have to -based on the domain redirect all (except for a white list of routes) routes to a controller that throws a 404 exception. Here is what i mean.
Home_restrict:
path: /{slug}
host: "{domain}"
defaults:
_controller: HomeBundle:Home:notfound
requirements:
domain: example.com|www.example.com
slug: ^(?!.*(admin|login)$).*
Routes that appear on top of the list on the page takes precedence, so this should be placed appropriately

You can add a routing.yml per bundle, and include these in your "global" routing:
# src/HomeBundle/Resources/config/routing.yml
home:
resource: "#HomeBundle/Controller/HomeController.php"
type: annotation
and
# src/AppBundle/Resources/config/routing.yml
home:
resource: "#AppBundle/Controller/AppController.php"
type: annotation
then import them in app/config/routing.yml, and maybe even prefix it over there?
# app/config/routing.yml
app:
resource: "#AppBundle/Resources/config/routing.yml"
prefix: /app

Related

How symfony handles multiple bundles routing?

I am trying to understand symfony's routing system.
In app/config/routing.yml, I have two routing configurations from two different bundles
'
firstbundle:
resource: "#FirstBundle/Resources/config/routing.yml"
prefix: /api
secondbundle:
resource: "#SecondBundle/Resources/config/routing.yml"
prefix: /api
`
So if I am making a request like,
https://example.com/app.php/api/images/ (defined in first bundle config)
or
https://example.com/app.php/api/views/ (defined in second bundle config)
How does the router decide which bundle to use?
Suppose I am going to access api./views, in this case will it also check within FirstBundle routing config? My doubt is regarding the routing flow. Does router traverse through every bundle configurations?
Routes, as other configuration parameters, are parsed in the same order they appear in your file.
That means that if two identical routes (keys, speaking more in general) are defined, the first one defined (and so parsed) is the one that is taken.
If you're worry about performances, I can tell that this is not something you should worry about (them are cached)

Override parameters.yml in each bundle symfony2

I'm working on a complex Symfony project. In the project, we have a core bundle which uses the parameters.yml located in app/config.
Each other AppBundle will inherit this CoreBundle and will correspond to a website.
What I need is to have specific parameters in each bundle that will override the default parameters one: when I'll use a route that will bring me into a controller's bundle, the parameters of this specific bundle have to override all the other ones.
I've tried the preprend method but it doesn't fit to this need. It only allows me to create new parameters for this bundle, but not to override the other ones.
I think you misunderstand the idea of bundles in Symfony. Bundle by design should be a reusable module, therefore the configuration placed inside a bundle is the default one. Then it is possible to override parameters (and not only!) in configuration in app folder.
The basic idea is:
Bundles don't use application. Application uses bundles.
So it's completely the opposite to what you expect it to be. Acutally it makes no sense to condition whole application configuration depending on current route since bundles can use one another. What if your currenct action will internally (without redirect) call another bundle's service or even controller?
Also it's worth mentioning that the app folder is the final folder for your application, therefore you can override in it not only bundle's configuration but also other things like services, view templates and so on.
Edit: I forgot to suggest a solution for you :)
Since you want to use custom parameters inside bundle, why do you need the default value in first place? Just create separate parameter namespace for each bundle that won't be overridden by application config. Then use it only inside that bundle.
Solution found thanks to dragoste's asking about separated kernels.
To solve my problem, I had to split the kernels : one for each website.
Documentation can be found here :
http://jolicode.com/blog/multiple-applications-with-symfony2

Symfony 2 - "Internal" bundle routing

Is there any way to register bundle's routing from within bundle itself and not importing it in the main routing file?
Now my routing.yml looks like this:
my_route:
resource: "#MyExampleAdhocBundle/Resources/config/routing.yml"
prefix: /
However, I would like to somehow enable bundle routing in ExampleBundle class or bundle config, so it will be on only if bundle is registered in AppKernel.
Have you tried to do this inside your bundle extension file (AcmeDemoExtension for the AcmeBudle) ?
I think you should look inside Kernel::buildContainer to understand how it's done and how you can handle this.
I think custom route loader is the answer.
A custom route loader allows you to add routes to an application without including them, for example, in a Yaml file. 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, or when you have open-sourced it as this would slow down the installation process and make it error-prone.
Alternatively, you could also use a custom route loader when you want your routes to be automatically generated or located based on some convention or pattern.
No. For every bundle the routing must be imported in routing.yml. Every popular bundle (like FOSUserBundle) have to do this also.
So no bundle can override users routing. Importing the routes in routing.yml offers the option to define a prefix or host option on this imported routes.

Symfony Routes without app/config/routing.yaml

The tutorials I've read for Symfony 2 instructs users to enter their routing information in
app/config/routing.yml
If users want to have routing information in their own bundles, they're instructed to add a routing.yml file to their Bundle, and then point to their file from app/config/routing.yml with something like
my_route_stuff:
resource: "#CustomstuffBundle/resources/config/routing.yml"
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file? I'm looking for the ability to hand off a bundle to someone else, and have them be able to deploy it into their Symfony application without needing to edit their own app/config/routing.yml.
If this isn't possible, bonus point if anyone can explain why (i.e: the general philosophy behind) routing information is part of the AppKernel instead of the individual Bundles. I'm still a little unclear on the differences between routing.yml files and the normal Symfony config.yml files.
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file?
No, this is the way SonataAdminBundle, FOSUserBundle and a bunch of others handle it.
Why?
Routing belongs to the application, not each and every bundle. If every bundle started including their own routing files and Symfony2 autoloaded them, you would quickly have a mess of routes you may or may not want to enable in your application.
What if SonataAdminBundle wanted you to use /admin, but you already had a route there and wanted Sonata to use /sonata/admin instead? You'd need a file to override those routes and then you're back to square one!
Additionally, although caching mitigates this part, looking up files is expensive and would significantly slow down the development environment. This is why translation files are read from cache even in dev mode and you must clear the cache when you add a new translation resource. See: http://symfony.com/doc/current/book/translation.html#message-catalogues
Finally, leaving the routing out of config.yml is simply a matter of organization. Routing and configuration are two different things and don't belong in the same file.
The general idea is that every file is a thing and should only do that thing.

How to structure a project in Symfony2?

I would like to ask, what is the best way to structure a project with frontend and backend in Symfony2? In other versions of Symfony this is easy to achieve, because you can create two applications - frontend and backend - then all the libraries/models will become shared between those applications.
Now in Symfony2, everything is a bundle. What is not really clear for me is how could I represent the "two" applications, frontend and backend. Should I create two namespaces - frontend and backend? I would like to keep my entities in just one place, rather than accessing them from the two applications.
Just have one application, create an AdminBundle or BackendBundle or whatever for your project that has all the tools you'll need in the back end, and use firewalls and access control lists in security.yml to create separate routes for the two.
No need to create separate app directories, mess with the console script, or anything like that. By default, Symfony knows how to find entities and other resources for any bundle that you have registered, so you'll be able to share them easily.
This documentation entry on Security is a good place to start learning about access control and firewalls. Here's a quick sample of what my security config looks like:
firewalls:
main:
pattern: /.*
anonymous: true
form_login: true
access_control:
- { path: /admin/.*, roles: ROLE_ADMIN }
- { path: /.*, roles: IS_AUTHENTICATED_ANONYMOUSLY }
If you want complete authentication separation for / and /admin, create a new admin firewall: firewalls do not share authentication information between each other, so you can track users and their sessions separately if you'd like.
I have tried the approach suggested by PAStheLoD (creating app_backend and web_backend, etc) but I found it too much hassle; you have to remember which app to target from console, maintain separate bootstrap files, and the directory structure gets messy.
The method recommended by the Symfony documentation Symfony documentation is to have a separate project for each app. You can then create a separate area for your source code, write most (if not all) of your bundles there and then simply adjust how they are included in autoload.php of both apps.
e.g.
admin_app/
app/
bin/
src/
web/
frontend_app/
app/
bin/
src/
web/
common_src/
Acme/
AdminBundle/
DataBundle/
jQueryBundle/
Then in *_app/app/autoload.php:
$loader->registerNamespaces(array(
'Acme' => __DIR__ . '/../../common_src'
));
As far as I know you still can do the more or less the same thing with Symfony2. Just rename app/ to app_frontend and make a copy to app_backend, also duplicate web/ the same way. Then everything else can live in bundles. Bundles are very powerful, because they can contain routes, configuration or anything else, so you can share what you want and perfectly isolate what you don't want to share.
There might be some problems with the bin/ scripts due to renamed directories, but you just have to correctly configure them (or raise it as an issue at Symfony's Github site.)
How about having one app and creating three bundles, src/Vendor/BackendBundle,src/Vendor/FrontendBundle and src/Vendor/SharedBundle. SharedBundle holds the entities and other shared parts betweeen the FrontendBundle and BackendBundle

Categories