we have a CMS system build on top of symfony2 and I've been struggling with routing problem, when you would like to implement behavior similiar to every CMS system using friendly URL slug as identifier of entity.
Let's say I have multiple bundles, each of them taking care of their stuff and entities. How can I use their own controllers with dynamic route param slug?
For example, I have a base slug controller with route "/{_slug}/" with lowest priority. So it can found entity by slug in repositories which knows about, but this solution is not flexible. And also it kind of degrading controllers, because now you have only one master controller, instead of deffering the logic to each controller of each bundle.
I found several ideas of approach to this problem.
Load routes from database - a little worse performance, no cached routes
Add dynamic loader of routes - Too much code, worse control of slugs
Custom router, which will be used before symfony core CMF router - so far I've found a little information about this solution
I've found several topic, that tries to cover this problem:
More complex routing - Discussion about dnyamic routes
How to add custom routes to Symfony 2 before container compilation?
If you haven't already, I suggest to take a look at the "Dynamic Router" from the RoutingBundle included in the Symfony CMF project.
Since the CMF project is about building CMS functionalities on top of Symfony, I think it may fit your needs.
Related
I am developing an app with Symfony2 that has 3 main parts called frontoffice, backoffice, admin. I was thinking to create three separate bundles: FrontOfficeBundle, BackOfficeBundle, AdminBundle but Symfony's docs says, each bundle should not have any relation with each other. Entity is already a shared property and probably some models. I could create a SharedBundle but it does not make sense. I remember when I created an app 2 years go when I had like 15 bundles and all connected each other and I know from experience that it's a nightmare.
Should I have just one bundle AppBundle and logic split in the folders, eg. Controller/Admin; Controller/FrontOffice, Controller/BackOffice?
What's the best approach?
It's all about SRP and DRY
It doesn't hurt to create a bundle, so make a separate bundle for stuff you need in multiple bundles, e.g. I tend to create an EntityBundle which contains entities and their repositories (as service).
Of course you can just use a single AppBundle too but please don't put your logic into the controllers -> create reusable services! Inject the services you need into your controller (which should themselves be services too).
Alternatives to base Controller Methods
No such thing as best approach.
However, instead of grouping by class type (Controller,Command,Form,Templates) within a directory, I like to create a single "component" directory for each request action. So I would have
Action
FrontOffice
BackOffics
Admin
User
UserController.php
UserFormType.php
UserTemplate.html.twig
Grouping files in this fashion really cuts down on figuring out where the various files live. Is it the "best" approach? Nope. But it works for me.
I'm looking for a solution where I can routing in Silex different URLs to a controller to get more organized my code.
The problem is that I need to route to the same controllerProvider some routes in different languages:
$app->mount("/{_locale}/string-in-english", new App\Controllers\myController());
$app->mount("/{_locale}/string-in-spanish", new App\Controllers\ myController());
Where /string-in-english and /string-in-spanish are routed to the same controller.
Most likely, the possible routes are inserted into a table in a database.
Greetings and thanks in advance.
Full i18n routing is tricky, you will need to use a translation service and a single call to a mount() that can handle translatable routes.
Take a look to this article. There are some interesting comments and the author published an I18nRoutingServiceProvider.
In my opinion Silex rocks when used in simple apps, but it can become really hard when you start to add this kind of features. Sometimes it is easier to implement them in a Symfony app.
I'm refactoring a not-so-complex website based on Symfony 2.2 / PHP 5.3, and the main issue here is repeated code.
There are two bundles, one for the main website, and another with the mobile version. Those differences are not only on templates and static files, as they comprise some differences in business rules and so on.
Currently those two bundles sport three controllers, one being the main guy, another being the exceptions controller, but a third is the "mother-controller", that holds several common methods and behaviours, and is inherited by the actual controllers.
This poses a small problem, since I can't simply make the action controllers of the mobile bundle inherit from the desktop bundle. All I could do is implement inheritance between the mobile's DefaultController and the desktop one... And thus I still have a bunch of actions almost equal, except for some custom lines.
Is there a way to extract those actions to a generic class and them import them into the controllers (like we have in Yii's Action classes)? I searched about using the decorator pattern to no avail, and was wondering if there's any sort of known method to implement this idea.
Since you have two bundles my first idea would be to create another (let's call it "CoreBundle") and create CommonController there and put common logic into it. Then, let other controllers extend this CommonController.
The more cleaner, but harder, solution would be to create service which would be parametrized by needed data/services.
For the past two months, I've been developing a Symfony2 web application. Now I've been going back through and trying to fix some issues with it, because it's gotten a little out of control and I want to make it easy to maintain.
My application is structured into a series of bundles like this:
src/AppName/HelpBundle
src/Appname/InterfaceBundle
src/AppName/ProductBundle
src/AppName/UserBundle
InterfaceBundle just contains several twig templates for the main layout, and each of the other bundles just extend that, e.g.:
{% extends 'AppNameInterfaceBundle::layout.html.twig' %}
For controllers, each controller directory has two sub directories: User and Admin, for example:
src/AppName/ProductBundle/Controller/Admin/ProductCategoryController.php
src/AppName/ProductBundle/Controller/User/ProductCategoryController.php
Is this the appropriate way to structure a Symfony application, or should it be done differently?
The problem is not very detailed but for what I see I think that what you could do is organize things in a way that AdminBundle and a UserBundle contain a set of generic services that allow you to build controllers reusing them.
Then you could have a series of bundles like ProductBundle that reuse/interact with these services. Use dependency injection in your controllers rather than extending the Symfony's Controller class; this way you can leverage service inheritance and build abstract controllers in your AdminBundle and UserBundle and use them to derive your specific controllers.
More in general I like to structure Symfony applications in a way that for each concern that is cross-cutting the application's domain (e.g. indexing of entities in a search engine, logging, generation of URLs and so on) I like to create a bundle that provides some abstractions to handle it; for each area of the domain (e.g. product management, user management etc.) then I like having a bundle that implements interfaces provided in the abstraction ones and that registers specific services to be used in the provided abstractions. Interfacing can be done in this case through the container's configuration and tagging systems.
The question was pretty generic and so my answer is too, if you want more details feel free to provide more details to your question.
I want to create a blogging system in order to practice symfony2,
but currently I get a bit confused when creating entities such as user or blog.
The reason is the following :
User( or Blog) is commonly used in frontend and backend(admin)
(currently I have considered creating FrontendBundle and AdminBundle)
Entity must belong to one bundle.
Currently I have considered the following methods, but what is the best way
in this case, or please tell me if there is another way.
Create bundle named 'BlogCommonBundle' and define User entity as "BlogCommonBundle:User".
Define all controllers under 1 bundle, such as 'BlogBundle', so
frontend/backend(admin) controllers belong to same bundle.
I think creating a BlogBundle and having multiple controllers for frontend and admin functionality is a good way to handle this. Both controllers would make use of the same entities and repositories, and you can easily firewall your admin actions in the security settings of your application. By keeping everything blog related to one bundle, you maintain good code organization.
The same goes for a UserBundle. It's helpful to remind yourself that a bundle should represent a set of like functionality for an application. So if you have code that fetches blog posts, and allows you to create and manage them, they naturally group together in a single bundle.
I asked a similar question here:
How to share a Symfony2 model with several projects
I went with the 'ModelBundle' approach that contains all the entities, forms, repositories, etc. These are all shared with the FrontendBundle and BackendBundle.
So far I'm very happy with this solution.