How to extract actions from Symfony Controllers? - php

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.

Related

Symfony2 architecture

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.

Symfony2 application structure best practices

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.

Hot to share common controllers action across other controllers in ZF?

Let us say I have a controller that takes care of login/registration/password recovery and such in my app. I want to share this across different modules and controllers. What's the best way?
Should I make an action helper, Or use inheritance? Of course I don't mean logic of those action, those are implemented by models (different for every module), I just want to share common parameters, interpretation and passing results to views.
I'm targeting to do some kind of a generic library for those things in my project. So I would have some abstract user model from which all other models that want to use login/registration function will inherit, but I'm wondering what about the controller stuff.
Any idea?
Basically I think what you are trying to create are widgets . Here is an great article how to create them using action helper by ZF team lead http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html .
Creating a re-usable authentication service is what you want to do. Creating it as a service allows you to test it in isolation. Inject the service into a front-controller plug-in so it is run during each request. The actual checking can be encapsulated into a custom validator so you can simply call ->isValid(). If not valid, re-route to the login page.

mvc design question

I am using Zend framework and doctrine in this app
In my web application i have various individual modules like events, conferences, case studies.. so i am making controller design at this moment. In the below image regulatory document is the controller and its sub are its actions. So regulatory doc, videos, podcasts all are having almost the same kind of functionality. so is this design appropriate...?
In mvc for each action i will be having a separate view. And on user type i may have to put access levels on this modules. so i have kept separate controller so that i can easily control the module for each user type. But this is resulting in duplicate code.
Now i am thinking to make one parent class and in that i will have all the common methods. eg. I will have common class Resources and in that i will keep list, search, suggest, addFavorite etc. And that will be the parent to the above given controllers.
So than how will i manage my view for all these different modules if i go with this approach..? if i go with this than my code will be bit messy..?
I would suggest to keep all the controllers to have nice URLs and clear structure in the modules, however keep the controllers thin. Put your domain logic into Services or Entities, hence no (or just less) code duplication is required.
More in:
Is MVC + Service Layer common in zend or PHP?
How to implement service layer in Zend Framework?
From DDD:
http://domaindrivendesign.org/node/118
controllers belong to application layer / domain logic belongs to domain layer
If I understand you correctly you have a set of common behaviors among your regulatory documents, videos and podcasts.
In this case you should probably try to abstract the commonalities out into a parent class from which these three areas inherit.
As an example, I have my own MVC framework where I define a superclass tnh_controller from which my other controllers (eg: venue_controller, group_controller) inherit. In the parent controller I define the header() and footer() and delete() methods. I can then use those unchanged in the child classes and save myself some effort.
You can likewise do some of the common work for your models (CRUD) in a model superclass, only overriding it as needed. Most of the logic for different models comes from class variables (table names, column names, etc).
I wouldn't worry too much about being "strict" MVC. Instead try to work out what will save you time and keep your code organized. It sounds like you're on the right track putting similar behaviors at a parent level.
You can still have a separate controller to contain suggest, addFavorite actions without having to make it the parent class for all the controllers. Basically the UI elements related to these you can render as partial views and call on to the actions in the relevant controller. That way you can get rid of the problem with the views.
MVC designing means that for each view, you have a controller and a model. However, the models don't need to be classes at all, nor having a different model for each MVC. Usually you will share a model between some MVCs, or your model might just be an integer value which you define in the own controller. Usually, you might even want to share data between them, then you will have a singleton mode:
http://www.galloway.me.uk/tutorials/singleton-classes/

What is MVC, in relation to the Zend framework?

I'm learning the Zend Framework and it uses a MVC model.
I still have not got my head around what MVC Model, View, Controller is.
What are the three different areas for and what would the program flow look like?
M - Models - are often the biggest source of confusion. These are the parts of your application that do all the 'heavy lifting' - they handle database access, perform the complex application-specific logic and are responsible for most of what your application 'does'. Unlike Views and Controllers, the Zend Framework doesn't have a base class for Models - this is because there's no real consistency in what they do. Some frameworks (like Ruby on Rails) try to present some sort of database-wrapper as a base for Model, but there are many cases (3rd party feed/API, static files, non-persistent calculations, concepts that span multiple tables...) for which this is, at best, a misleading practice. The Model is the part of the application where you're still forced to program and the framework can't really save you from it.
V - Views - are the simplest components here. They should be simple PHP/HTML templates. They're given view objects, arrays, strings, etc. which they then put into a page. There shouldn't be much (if any) complex logic here - loop over these, display this (if defined), zebra stripe this table and whatnot. There's some magic happening with View Helpers (such as the helper that magically renders a Zend_Form), but that's not essential to understanding the overall system.
C - Controllers - In the broadest sense, the controller is responsible for taking user requests, sending them off to Model objects and preparing Models to be handed to the Views. It's the glue that holds everything together. If you're using Zend MVC, you're concerned with 2 controllers - Zend_Controller_Front and Zend_Controller_Action.
Zend_Controller_Front (which you get 'for free' if you use Zend_Layout::startMVC()) is a single point of entry for your application - it handles the raw user requests and translates URLs into an Action to call. There are various places to 'plug-in' to this to handle things like authentication and access restrictions, but, at the core it's just the 'traffic cop' at the front gate directing incoming requests.
Zend_Controller_Action is the base class for actions - essentially an Action represents something your application does (log in, list blog entries, launch an ICBM, order a pizza...), but is not directly responsible for actually doing it. The Action Controllers are pretty boring - they pull values out of forms and URLs, call a few methods on Model classes to actually perform the action and push the results out into the view. As has been said before, they're the 'glue' that holds Models and Views together.
A rough test to see if you're splitting things along the right lines is to envision a major change to your site. A visual redesign would almost entirely be handled in the Views. Moving all your URLs would change your Controllers. Converting from a web app to a GUI app would replace the views and controllers, but your model would still be mostly unchanged. If you rewrite your models, you have a whole new application.
There are several other questions on Stackoverflow that give an explanation of the MVC concept:
What are MVP and MVC and what is the difference?
What is MVC (Model View Controller)?
A very good explanation of the concept can be found on Wikipedia:
Model-view-controller (MVC) is an
architectural pattern used in software
engineering. Successful use of the
pattern isolates business logic from
user interface considerations,
resulting in an application where it
is easier to modify either the visual
appearance of the application or the
underlying business rules without
affecting the other. In MVC, the model
represents the information (the data)
of the application; the view
corresponds to elements of the user
interface such as text, checkbox
items, and so forth; and the
controller manages the communication
of data and the business rules used to
manipulate the data to and from the
model.
In relation to Zend Framework:
models are generally presented by extensions of the Zend_Db_Table class
views are presented as *.phtml files in your defined scripts folder, which are handled by the Zend_View class.
controllers are defined by extensions of the Zend_Controller_Action class.
The Zend Framework has its own very nice Quick Start/Tutorial which especially introduces MVC.
Quote from there:
So what exactly is this MVC pattern
everyone keeps talking about, and why
should you care? MVC is much more than
just a three-letter acronym (TLA) that
you can whip out anytime you want to
sound smart; it has become something
of a standard in the design of modern
web applications. And for good reason.
Most web application code falls under
one of the following three categories:
presentation, business logic, and data
access. The MVC pattern models this
separation of concerns well. The end
result is that your presentation code
can be consolidated in one part of
your application with your business
logic in another and your data access
code in yet another. Many developers
have found this well-defined
separation indispensable for keeping
their code organized, especially when
more than one developer is working on
the same application.
In as few words as possible:
model is the db
view is what you see (the page)
controller is the glue (logic)
Your models know how to access tables containing your data; your views know how to display content; and your controllers glue it together (what view do I show? what model should I use?).

Categories