Symfony 2 - How can I share data between controllers - symfony

I need to be able to make some request data from one controller available in another controller. I can make a service to set the data in one controller, but when the other controller fires and I get the service, a new instance of the service is created. Is there any way I can make this data static and share it between two controllers?

The same basic things you would do whenever you need information to be available in PHP from a new request:
Store it in the session. Symfony2 has a great session component for this. Ideal for fleeting data that needs to be saved only while the user is navigating
Store it in the database. Symfony2 supports Doctrine which makes this very easy. Ideal for permanent storage
Optionally:
Store it on the filesystem. Not recommended unless it's actually a file, but possible as well.

In the end, rather than using the session to store data, I created two separate routes to the same controller action. I added an optional argument in the controller action, with a default value only specified in one of the routes. I can then test for that argument's value when the controller runs. In the Twig template that calls this controller action, the path can be generated using either one of these routes, depending on a variable already available.
Bit of a work around, but problem solved!

Related

Symfony differentiate application by dynamic route prefix

I need to differentiate what data to load by route prefix.
Let's say that I have these routes:
http://test.com/app1/news
http://test.com/app1/gallery
http://test.com/app2/news
http://test.com/app2/gallery
http://test.com/app3/news
http://test.com/app3/gallery
URL of apps (app1, app2, app3) are saved in database. For each app, there are different data for news, gallery etc.
Is there any way how to "cache" app entity and do not load it every time from database and check prefix in every action in controllers?
Is it good idea to save app object to session (and change it only if URL is changed)?
Thanks.
Yes, if you use Doctrine ORM you can configure second level cache.
More Information in link Doctrine second-level-cache

Manage security/routing with Symfony2 by requesting a database

Using Symfony2, I'm looking for a way to easily access the main route prefix for a given request, outside any controller:
I am trying to figure out the best way to deal with access control related to some database elements in Symfony2.
I would like to restrict the access to some 'applications' located in the path /application/APP_ID according to the Subscription stored in the database.
Every restricted resource will be in this path.
The subscriptions are referencing a User entity and an Application entity. It includes an ending date. After this ending date, the application should not be accessible anymore.
The restriction should be : for every resource starting with /application/APP_ID, I need to check if the controller should be accessed.
This prefix is static and is actually defined in the app/config/routing.yml as a 'prefix' and the corresponding route name is stored in one of the Application entity attributes. The other involved routes are defined in an independent routing.yml file located for example in MyAppBundle/Resources/config/routing.yml and imported in the main routing file.
Can I easily know if the current route requested (ex. /application/APP_ID/action/1) is included in the route defining the prefix (ex. /application/APP_ID) in order to know what Application is concerned?
Or, is there a way to do that without having to give a list of routes or paths which necessarily require modifications for every application added, route added or modified?
Did you try to develop your own Voter ? As explained here : http://symfony.com/doc/current/cookbook/security/voters.html.
Instead of testing $request->getClientIp, you could test $request->getRequestUri. And you could have an access to doctrine, using $this->container->get('doctrine'). I think you could have all informations you need to secure your paths.
I did it few days ago to store my own RoleHierachy in database, it works well.

hiding method from certain layers in project

I was looking through an old project and wanted to see if anyone had a suggestion on how to hide certain methods from being called by various layers. This was a 3 tier project, webapplication -> web service -> database
In the application there is a User object for example. When a User was being updated, the webapplication would create a User object and pass it to the webservice. The webservice would use the DataAccessLayer to save the User object to the database. After looking at this I was wondering if instead I should have made a Save method in the User class. This way the service and simply call the Save on the User object which would trigger the db update.
However doing it this way would expose the Save to be called from the webapplication as well, correct? Since the webapplication also has access to the same User object.
Is there anyway around this, or is it better to avoid this altogether?
There is a separation of concerns by keepeing the User object as object that only holds data with no logic in it. you better keep it separated for the following reasons:
As you stated, it is a bad practice since the Save' functionality will be exposed to other places/classes where it is irrelevant for them (This is an important for programming generally).
Modifying the service layer - I guess you are using WCF web service as you can transfer a .NET object (c#/VB) to the service via SOAP. If you put the saving logic in the 'User' object, you can't replace it another webservice that receives a simple textual data structures like JSON or XML or simply doesn't support .NET objects.
Modifying the data storage layer - If you want, for example, to store the data inside a different place like other database such as MongoDB, RavenDB, Redis or what ever you want, you will have to reimplement each class that responsible for updating the data. This is also relevant for Unit Testing and Mocking, making them more complicated to interrogate.

Symfony2: Is better to use session object or my own manager?

Related to that question.
I've understood that I have to create some services for handle my entity and so on. That's because I have to "move" my logic away from controllers and place into "managers" (i.e. services)
Now I have a service that have some logic into it. In that service I, depending on user, return a list of "associated object" - say that those object are sport's team.
Let's say that first element of my list (generated from a repository somehow) is the "default" team and say that I have a page were I can change it FOR all session long.
After log out or sessions stale, I want to return at "default" situation.
So my idea was: "since I've wrote a manager for this entity, I'll write a private attribute in this class where load (from db) this property and store (temporarily, with setter method) my changes."
This doesn't affect my db and I can keep my information for all session long.
But a thought came into my mind: how about session object? (is a service, if I didn't understood wrong)
Is my solution a good solution, or is better to store my information into session object?
From my point of view it's the same except that I can read session's variables directly from twig by using app.session. Am I wrong?
Moreover, if I'm not wrong, how can I access my object properties from twig without each time pass them from controller? (is much like having a global variable that I want to display everywhere into my application pages).
Edit:
More information can be found in this chat transcript.
If you want to store a variable for the duration of a session (for example, login until logout or as long as the user doesn't close his browser window) you have to store it in the session object. If you want to store a variable for the duration of a request, you can store it in the manager service.
However, you can use the manager service to load the session variable and make it available to the controller.
Just like it is a good idea to decouple the controller from the database/Doctrine it is also a good idea to decouple the controller from the session.
Update: As mentioned in the comments when looking at REST it is not a good idea to do the session stuff in the service. However, you should still store the variables in the session and use the controller to set the value in the service.

Custom IIdentity or IPrincipal Or something else

I'm finding that in the current application I'm working with, I'm retrieving several entities (related to the authenticated users account) in almost every controller. These entities are cached at the orm layer however, it seems that these entities would be a good candidate to load once at authentication time and add a few properties to the applications custom IPrincipal object.
Another option I was thinking of was creating a custom context object (with the users related account objects) and passing it around with the current request.
Benefits / drawbacks to either approach? Is there another way of dealing with commonly used objects like this?
It sounds like you miss the fact that the instance of IPrincipal/IIdentity is recreated upon every request. It is not persisted anywhere if you not persist it in an explicit way.
I don't think then there's performance difference between a custom principal class holding the data vs a cached ambient property.
On the other hand, the drawback of a custom authentication classes is that you have to provide a custom authentication module so that these instances are recreated during AuthenticateRequest event in the processing pipeline. In other words, you'd have to replace FormsAuthenticationModule with your own one. This is not difficult but I wouldn't do this if it is not absolutely necessary.
Note also that some data can be persisted in the UserData section of the forms cookie. This means that you can have it as long as the cookie is valid and create it only once.

Resources