I am now working on my first symfony2 project. I have created a service, and I need to call it for every controllers to generate a html which is necessary throughout the all pages in my website.
So I created a BaseController class which extends Symfony\Bundle\FrameworkBundle\Controller\Controller class and tried to place the code in this BaseController class. Now whenever I call from the constructor:
$my_service = $this->get('my_service');
or
$my_service = $this->container->get('my_service');
I got error:
Call to a member function get() on a non-object.
The container object has not been initialized. What is the solution to this problem? How DRY method is followed in symfony2, if I want to place left panel or header in all pages which contains dynamic data?
Thanks in advance.
You shouldn't use the constructor in your controller class, especially when you inherit from Symfony Controller: that way you get the container after the object instantiation (the DIC will call the setContainer method inherited from Symfony's Controller).
In general, for your first experiments, use the services in the action methods; if there is some cross-cutting logic that you need to execute in every request you could consider registering some event listeners (see the "Internals" docs in the Symfony website).
When you get more confidence with the framework you can start thinking about not inheriting Symfony's Controller, registering your controller classes in the DIC and injecting the services that you need manually (eventually implementing some logic in the constructor).
I know this is not the answer you desire, but if you need some html on all pages, I think using a service the way you do is the wrong way.
I guess you know about twig and the possibility to use a layout to place common code. But you can also embed a controller:
{% render "AcmeArticleBundle:Article:recentArticles" %}
Within the recentArticlesAction, you can place your specific code and return a template. By this, you can get custom html into each of your templates! See the symfony docs for more: http://symfony.com/doc/current/book/templating.html#embedding-controllers
Business logic is all the custom code you write for your app that's not specific to the framework (e.g. routing and controllers). Domain classes, Doctrine entities and regular PHP classes that are used as services are good examples of business logic. Ref
Related
I'm having some problems with accessing org.springframework.ui.Model in a bean not annotated by #Controller Using #AutoWired fails in this bean and it isn't created. Similarly, if I try to make Model a parameter to a method in this bean it is not injected and the method call fails silently.
The reason for the need is to supply dynamic data to some views in my site such as allowed links for a user, or custom welcome messages. Theses elements may not be on every page. I've seen some tempting frameworks like Tiles. View templates were working, but needed model element on partial views was not being populated.
I've seen similar posts such as Add attributes to the model of all controllers in Spring 3 but this would add to all views which is not correct in this case. Any help or pointing in the right direction would be appreciated.
I have some logic that I want to be able to call from a controller, but I don't want it to reside within the controller. I want to provide a helper class that the controller calls into. I also want that helper class to be able to conveniently access the service container. What's the prescribed symfony way for doing that?
Your helper should be a service accessible via the service container.
Read and understand this: http://symfony.com/doc/current/book/service_container.html before going too far.
Also, do your absolute best to avoid injecting the complete container into the helper. You really want just to inject whatever the helper needs to do its job.
I have a base controller which is subclassed from a standard mvc controller. This containers lots of useful methods specific to a Controller.
I now need to have some asych functionality in one of my new controllers
However, to do that you need to create a controller that subclasses AsyncController
But I also want to access functionality in my base controller
Obviously multiple inheritance isn't possible
so how do I get around this?
You could externalize the functionality you are willing to reuse into a service layer, action filter, authorization filter, model binder, ... it will depend on the functionality you are willing to reuse so that you could easily switch the base controller to an async controller and still preserve the functionality. If you want to use async controllers you will need to derive from AsyncController.
You could make your controller class inherit IAsyncManagerContainer and IAsyncController, then implement this functionality yourself, perhaps using the code from MVC source code. You could even encapsulate this in its own class that you delegate the functionality to.
I am trying to figure out where the appropriate place is to intercept the resolution of what view + controller is being called in ASP.Net MVC 2. I have a situation where I have a controller and a corresponding set of views. I also have the possibility of a customized version of both the controller and N of the views sitting in the project (or we may use something like Portable Views from the MvcContrib project). If the customized version of the controller or view(s) exists at run time, and the user satisfies certain criteria, I need to call the customized controller and use the appropriate customized view. At design/compile time we don't know what customizations may be in place.
My first run at this was by using a custom controller factory that returns a custom controller if it exists. However, this controller is "wired up" to the standard view, and I cannot figure out how to return the customized view if it also exists.
To complicate matters, there may be no customized controller but customized views, and visa-versa.
Sounds like you're on the right track. You've got custom controller selection logic in place, but you need to also have custom View selection logic.
You can override and extend the default ViewEngine to plug into your app that uses your own logic to look for the view locations. Here's a good walkthrough of a simple ViewEngine that does exactly that.
I am working on an ASP.NET MVC application that contains a header and menu on each page. The menu and header are dynamic. In other words, the menu items and header information are determined at runtime.
My initial thought is to build a base Controller from which all other controllers derive. In the base controller, I will obtain the menu and header data and insert the required information into the ViewData. Finally, I will use a ViewUserControl to display the header and menu through a master page template.
So, I'm trying to determine the best practice for building such functionality. Also, if this is the recommended approach, which method should I override (I'm guessing Execute) when obtaining the data for insertion into the ViewData.
I'm sure this is a common scenario, so any advice/best-practices would be appreciated! Thanks in advance!
EDIT:
I did find the following resources after posting this (of course), but any additional anecdotes would be awesome!
http://www.singingeels.com/Blogs/Nullable/2008/08/14/How_to_Handle_Side_Content_in_ASPNET_MVC.aspx
How do you use usercontrols in asp.net mvc that display an "island" of data?
Depends on where your information is coming from. We have standard view data that we use to generate some of the information we have on screen that we create in just this fashion. It works well and is easily maintained. We override the View method to implement strongly typed view names and use this information to retrieve some of the data that the master page requires as well.
You could write a helper extension to render the header/menu
That way you could have it show in different places in the view should you need to, but only one place for maintenance.
public static HtmlString MainMenu(this HtmlHelper helper)
Use a base controller class to implement generell filter methods. The controller class implements some filter interfaces IActionFilter, IAuthorizationFilter, IExceptionFilter and IResultFilter which are usefull to implement some common behavior for all controllers.
If the menu data is the same on all pages but different for each unique user.
Generate the menudata in an OnAuthorization or Initialize method of your controller base class. First will be called on authorization. Initialize will be called before every action method. You have access to ViewData Context. Generate the menudata there.
Put the view content for menu and header into the master page and access generated ViewData there.
I tackled a similar design challenge a couple months ago - implementing a breadcrumb feature that changes as user navigates from page to page.
I overrided the OnActionExecuting method to gather the breadcrumbs and store them in ViewData (I use the name of the action as the breadCrumb of the view). Then I updated the Master page to include a user control that takes the ViewData and renders the breadcrumbs.
One thing to be aware is that if you were using the default ASP.NET MVC error handling attribute [HandleError] and your error page is using the same Master page that attempts to read the ViewData, you will soon find out that you can't access ViewData from your error page and it will raise an exception. Depending on whether you need the ViewData for failure scenarios, the viable solution is to use a separate Master page or do this: How do I pass ViewData to a HandleError View?
I'll answer your question with another question. Will the base controller have to determine what type it really is in order to generate the proper menu data? If so, then you're defeating the purpose of polymorphism and the code to generate the data should go in each controller, perhaps in OnActionExecuting if the menu is the same for all actions. Pushing it back down into a parent class seems likely to end up with some switch statement in the parent class doing what each derived controller really ought to take care of.