Symfony2 inject an array of services into a controller from config.yml - symfony

How I can inject an array of services from config.yml giving class names (with namespaces) to a controller? I need to run a function from each of this services in the controller. At the moment I use $this->get('service'); in the controller, but I need to make controller independent from services. Is there a way to do this?
Edit
I don't know names and how many services will be injected, though all of them implement an Interface.
Edit2
Well, probably I did not express correctly my thoughts. I have a bundle named Widgets. It has an array of widget names, display widget holders for each widget and with AJAX I get the content and display it. At the moment I have in the Widget controller hardcoded some widget deffinitions (title and id for Ajax) and some are retrieved by calling getWidgetList from some controllers from another bundle. Well I need that the list of the widgets wont be hardcoded itself in the widget bundle. I need a way to pass this list from the config.yml. Any ideas?

Injecting an array of services is, generally speaking, not the right approach (even if there was a way to do it, which I don't think there is)
The whole reason you don't want to write container-dependent code is to keep your codebase flexible, lithe, and testable. A variable array of services is, in practice, just a mini container, so if you implemented that you'd just be shrinking the scope of the problem, not eliminating it. You'd still be making your code dependent on an arbitrary bucket of services.
I strongly recommend explicitly defining each service your controllers need (as outlined by the links in the comments from Rufinus and Cerad) or look into using something like the jms/di-extra-bundle.
Update
Maybe you need to do more research on the configuration options available?
How to Create Friendly Configuration for a Bundle
The Config Component
http://symfony.com/doc/current/cookbook/bundles/configuration.html

Related

Asp.net Core 2 Domain dependent View selection?

I have a new multi-tenant web application in ASP.NET Core 2.0, single DB.
I've established a method of determining a particular request's 'TenantId' by examining the domain in a simple piece of middleware.
I've also established a DataContext which applies TenantId filters to applicable tables as needed.
The last thing I'm unclear about is how I can differentiate Views/partial views based on the TenantId whilst sharing the controllers.
I think some scheme where the app first looks in some kind of TenantId sub-folder for the customized tenant's view and if it can't find it, it goes through the regular steps to locate the view... might work okay? Is this a reasonable approach? In other words, it should use the specialized tenant view if it exists, otherwise use the default view.
Would this involve building a custom view engine of sorts?
I've tried something similar with tenant based Html fragments, but it was a pain maintaining it, so I'm looking for something more straight forward on this project.
I'm open to other suggestions of how to implement this functionality as well.
Thanks in advance!
You don't need a whole custom viewengine, you can implement an IViewLocationExpander to make it check various locations for views.
In my project I have mutliple tenant support with both shared themes and tenant specific themes. I can override any view by dropping a copy below the theme folder, ie the main view could be Views/SiteAdmin/Index and I can override it in /pathtothemes/themefolder/SiteAdmin/Index
You can see my implementation of IViewLocationExpander here.
How you register your IViewLocationExpander is like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.ViewLocationExpanders.Add(new cloudscribe.Core.Web.Components.SiteViewLocationExpander());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
;

how to feed the ::base.html.twig with datas of database more proprely?

in my symfony application i use many controllers . They render their templates who all extend ::base.html.twig template. I feed these templates with an array of datas for display the dynamic content , thanks to my controllers. But the ::base.html.template need also to receive his array of datas for display 4 pictures in a kind of slider . These datas (url of pictures) come from datas base and are available for all pages in my website so i'am asking myself how to send just one time this array of picture? For moment in every controllers I have to repeat the same code for get the url of pictures from database .
Sorry if my question is not clear
I'd personally move the code that creates these sliders out of the controllers into a service layer, be it a proper service or simply a class you create and use dependency injection you need to access things like the EntityManager within it. Services are fine, but they have an associated overhead.
By moving the code out of the controllers, you have a method you can call from all the controllers and one copy of the code, instead of multiple copies through your controllers.
Rendering controllers within twig is certainly possible, but it seems a bit of a fix for bad design (in my opinion anyway). It's a quick win, but not exactly an efficient one.
Remember, controllers should be thin, not bloated fat with code.
I think the correct way would be to create a Twig extension that will get this data for you.

Symfony2: Where do I place my univeral helper class

I'm new to Symfony2 and would like to know the proper place to put my universal helper class. The helper class contains things like removeCurseWords, uplodFile, resizeImage, watermarkImage, convertDateToServerTime, doStuffHere and other things used by many but belong to none. I want this class to be accessible to all the bundles in my app so where do I place it to make it available to all.
Group those methods and put them in services (see http://symfony.com/doc/current/book/service_container.html). That way you can use them cross-bundle via the service container. You could have one service for all image operations and one for the rest which doesn't fit elsewhere.
If you have your php Library i suggest you to write a bundle that wrap it for symfony2 usage for, as example, expose the functionality as services container, manage the initialization, implement for type and so on for enable your library in yhe symfony2 way, then you can share via composer in other projects.
See this for further details.
Hope this help
I always create a folder called "Utils" at the same level as Controllers, Repositories, etc Found several people doing it that way too.

Symfony2, how create a widget like a standalone class

Let's start with basic thing, simple example is Yii. It has such thing as widgets. Standalone, configurable and callable from any place we want classes. And I'm wondering can symfony2 has the same? What it will be? Controller in bundle? Action simple (method)? Widget (twig) with parameters?
In Yii we create class (of widget), standalone, describe it and use (by calling in template). How will it look like in symfony2?
Simple example 'i want create menu navigation using widget, where it will construct html by user roles'.
Symfony doesn't provide such a feature however you can make them yourself. They are few ways of doing it.
I'll just admit that we are talking about widgets that could do backend work (i.e. get data from DB, call an API, etc.).
1 - The scalable way
The use of the render tag in Twig which allows you to call a controller action from a template. It's scalable because you could use esi tags with Varnish (you can also implement your own caching profiles).
As a bonus, the profiler will show details about the specific render calls in the timeline (it will look like a subset of the entire request).
2 - Include a template
The included template gathers the data through a Twig function call. By experience, it's a bit faster than the first solution however it's not easily scalable.
3 - Render through a custom TwigExtension
The twig function will get the data and call the renderView method of the template service. If you are planning on doing this, you probably want to use the first method.
Conclusion
If you have a big website with modules/widgets that gets a lot of traffic (or "hit"): use the first solution.
If you have a small website with no support for caching: use the second solution. You'd use this solution if the module/widget is super light.
If you are thinking about the third solution... it's probably a good idea to use the first solution.
Personally, I'll always try to use the first solution and try to boost the performance one way or another. The render call in Twig has been significantly improved since the last versions of Symfony2.
Hopefully, my answer will provide you some guidelines.

Symfony bundle composition, how do I structure my code when using multiple bundles

I'm looking for some guidance on best practice around how to structure my Symfony 2.0 application. If I have a few bundles (Cart Bundle, Product Bundle, CMS Bundle) and I wish to use aspects of all of these bundles when composing my page how should I best do this?
I can imagine two ways to do this, but am looking for guidance on which (if either) is correct.
1) Expose all of the functionality of my bundles through services, and have these services available to use directly from within twig. This way I can pass my routing request to the most appropriate bundle (so http://myclient.org/User/Account) is passed to the ClientUser bundle to handle, but the base template which has a mini shopping cart in the navigation is able to access the information it needs directly from within twig (I don't need to pass this in)
2) Create a bundle that accesses all the other bundles in order to build up the page (like VendorFrontend or VendorBackend). This would mean that ALL routing requests would be passed to this bundle and this bundle would access the required information for every part of the page before passing off to the template.
The first option feels wrong because I'm not sure if it's even possible to allow Twig to consume services directly (though the service container)?
Second option feels wrong because It's like using a second router, the routes would be being passed into a bundle, which only exists to compose the other bundles (it's a given here that this bundle is tightly coupled to the bundles that it uses). Surely this goes against the concept of a 'bundle' that the code is reuseable.
In this example I'm trying to build a very simple e-com site for demonstration purposes only. I have a base template which will have a primary navigation, mini shopping cart, 'body' and footer. I'm storing this in the /app/Resources directory. I was planning on having all other templates inherit this one and overriding the 'body' area.
Not looking to be spoonfed, just a nudge in the right direction. Thanks.
I think that it's important to get away from the idea that, in order to generate a "page", one has to corral together all the variables that the templating involved might need in order to render, and then pass these into a template. A controller should be doing only the specific thing for the request it's serving, and no more. So if there's a specific product referenced in a URL, fetch the product and pass it into the template. If there's a specific product referenced but it doesn't exist, or shouldn't be shown, you respond with a 404/ 410/ whatever is appropriate. If there's a specific collection, fetch the collection and pass it in. The routing/ controller should be decoding the request - the URL itself, the HTTP method, etc - and translating that into something specific. Anything general and not specific to a particular request doesn't belong there.
It's also important, I would say, to abstract as best you can the bundles you use from Twig templates. I am advocating more that templates "pull" what it needs into them, rather than being pushed in, but this is achieved by the definition of Twig functions within bundles that can themselves, via the DI container, hook into data that may or may not be in the current request, etc. So you make a Twig function that can take as a parameter anything that might change - if it has to do with product categories, let it take a product category object as a parameter.
Essentially the answer is more 1) than 2), but you shouldn't be accessing services directly through Twig - you should be proxying via functions that make semantic sense within the template, that themselves are defined to have services injected into them at runtime, services that you are at liberty to define differently in any new bundles you include or write.

Resources