Session and Request object dilemma - php

Session is retrieved in SF2 through the Request object. Hmm, this becomes kind of problematical when some architecture is considered - in cases where access to a session vars is needed from within a service.
Or perhaps, I'm not quite correct in this matter? (Hope so).
Obviously each request from a user through a webbrowser is a Request. So as long as we use controller actions in standard SF2, we have Request. But should we then pass the Request object to any service we need?
Passing Request object to all of the services that needs their methods to be run (e.g. storing info, checking settings, putting filters for displaying data etc. - well in some bigger apps it's quite a lot of them!) because it might be needed because of the dependent services, seems to be a very stupid idea to me. It also breaks the "S" in S.O.L.I.D. recommendation for OOP.
So I came up to a conclusion I need either to:
Pass the Request obj to many services just because the dependant service might need some data from it (i.e. broken "S" as above)
Retrieve and process data from Request every time I needed in every single controller action (i.e. code duplication) - in this case I don't pass a Request obj, but previously prepare all data needed - but I must do it then in many action methods in almost all controllers (retrieving/processing data from Request is just a simple call for another service, but then it's not centralized)
I'm putting this question, because I have e.g. the following problem to solve:
I'm using the same filters for all different data (from different data-sources) on the whole page.
Filters can be enabled and disabled - and they should be remembered for all the pages for the single session
I decided that saving "disabled" filters to a session is probably the best approach (because by default all data should be seen, i.e. all filters should be in "enable" state)
The 3rd point - saving data (filters) to a session - is what makes trouble in SF2, as described above. For displaying filtered data on page, I need access to a session, and thus access to the Request obj. And this means I have difficulties in keeping "S" in SOLID, because of making dependency on a service's method to always pass a Request obj to it.
Is there any other, better solution than the 2 mentioned (i.e. one, breaking SOLID, or two, code duplication)?

The session is also a service in the symfony di container, you can simply inject session into your servives

Related

How to pass parameter through views and controllers?

I have a model Project which have many Orders. On the page of the project, I have a list of its orders and create/update buttons.
Now I pass project_id in GET params in url. I need watching that each url and redirect have this parameter (in the update and create views/controllers and in the list of orders view/controller).
Is there a better way, to pass parameter through views and controllers?
This doesn't really have anything to do with MVC. In a web context, each HTTP request must be self-contained. All the information your server needs to fulfil the request must be contained within the request. Either within the URL, or within the request body.*
Whenever your server generates a URL somewhere to send back to the client, you need to embed all the information necessary in that URL so a request made to that URL gives your controller all the information it needs to fulfil the request. So, yes, you'll need to pass all the information through to that place in your code. That's pretty much the same whether you use MVC or plain spaghetti PHP files.
The only alternative is for you to reduce the amount of information the controller needs to fulfil the request, e.g. because you can implicitly get one part of information from another, like the project id when given just an order id.
* (I'll forego something like session storage here, since that's stateful across all requests and generally cannot be used for transporting information specific to individual requests.)

PHP Architecture: Save and use "constants" in whole system

I use my PHP (like normal) in a server architecture where I have an incoming request and build an outgoing response. All request attributes (like client ID) are given to each sub function and class to make magic with (like in my Mappers and Models and Helpers).
Is there an idea to work with request data WITHOUT putting it from function to function to function.
Idea 1: Make my Request/Response object static. I have exactly one request and one response so there is no problem to do this.
Idea 2: Saving data in Session (or similar). This also sounds uncomfortable and heavy.
Is there another idea doing this?
Implement your own Request or RequestContext class and populate a object of this type with all the data that ongoing methods might need. This way you don't need a growing number of arguments for each of your functions, instead you just forward the entire Request.
This is much easier to extend and you don't suffer drawbacks of "global" data. It's a typical pattern which is used by a lot of frameworks as well.

Drivers vs Controllers (MVC)

I am working with Codeignitor 2.x and I was originally using controllers as modules (though not completely HMVC), in that I had a Top Level controller that would call other lower level controllers. My thinking was that because these lower level controllers were still interacting with the view, that they should remain controllers rather than models or drivers.
What I found, however, is that each instance of a controller also spawns a new instance of CI. So I would have 3 or 4 instances of CI running for each request. Ton of overhead, and also caused session issues.
I have since moved these lower level controllers into the library as drivers. They now capture the CI instance in the construct method, and make modifications to it. This makes it VERY nice to work with, and doesn't require the HMVC extension. The drivers are not externally callable either, so it allows me to funnel all requests through specific entry points.
My question is whether this is structurally correct. I have always held the notion that drivers should only modify the data they are provided through their method calls, but many of these drivers will pull information directly from GET and POST, and while they will not directly append to the View, they are often accessing view files, and passing the processed view to the CI instance for output.
[EDIT] A little more context:
One of the drivers I have created is essentially a user login driver called 'Access'. It makes calls to the 'User' model for create/login/logout methods. The driver uses the POST data to check the User model, then loads the correct view with errors and whatever is needed. The idea, being, with 2 lines, I can include this driver in any controller throughout the project, so there is a significant decrease in code redundancy. Again, I know that the drivers should be confined to their scope, however the driver does not modify anything outside it's scope, but simply returns the view it has created.
Is there another method to for doing this that is more inline with straight MVC?
I can't say whether it is right or wrong. But if I were you, I wouldn't do that. I'd probably refactor some of the code. I'd make sure that they don't grab and manipulate data directly from the $_GET or $_POST superglobals. Instead, pass in some data as arguments to a function call. This would make testing easier, since you don't have to simulate a GET or a POST request. While technically, you could just set the value for the superglobals manually from the code, but I'd not recommend doing that. Supplying data as arguments would be much better, especially if you want to write test cases that are to be executed subsequently. Plus, having the libraries interacting with the scopes beyond its own might introduce some hidden gotchas.
In my opinion, libraries are meant to be something like modules, where you can just drag and drop, and then use them without any hassle. If your code really needs to grab or manipulate values from $_GET or $_POST, maybe they are meant to be models instead. Also, you might want to think whether your code is actually a library or not. Ask yourself, will this code be useful outside this application? Or is it highly dependent and can only be useful for this particular app? If you say yes to the latter, then it's probably should be a model instead of a library. Last thing, you should leave the views to the controller. Just return the data you need from the library/model method then pass it to the view from the controller.

A Backbone UI and a CMS backend: Wading through the Restful CRUD

Backbone tutorials I have read implement some type of a mini-framework (i.e. Slim) with a RESTful architecture performing CRUD on a server db, like this. The Backbone docs state you need a RESTful api, which I believe is due to the Backbone Route and Sync functionality that keeps models up to date, which is a huge aspect of my choosing to use Backbone.
For example, the line below maps a faux url (route) to the 'addWine' function (within a Slim api):
$app->post('/wines', 'addWine');
Assumption 1: If I have a (PHP) CMS backend (and not a mini-framework) I assume I could simply replace the 2nd parameter (addWine) with my own CMS class method call and return a json object.
Assumption 2 But I would not be able to directly call that same class method from a link in the html without causing backbone to lose state and thus it's ability to sync the model data (and remember the browsers history).
Assumption 3 In that case, I will need to use the Slim api and route backbone urls through (Slim) RESTful CRUD calls in order to access my CMS database to keep backbone happy.
If those assumptions are correct, then it would seem backbone is intercepting those HTTP calls - which leaves me wondering how the whole RESTful + Backbone relationship works. Can you explain some of it?
If my assumptions are incorrect, then I need more help than I thought. Can you help with that?
Thanks
I can't speak intimately to your three assumptions, but as for your final question -- Backbone does not "intercept" HTTP calls -- it constructs them, just as any other javascript library would to create an AJAX request.
Backbone is relatively agnostic to your server side language/framework. Here is what Backbone expects any time "sync" is called:
Backbone's sync function uses different HTTP request types based on which method was called. These different HTTP request types are:
POST
GET
PUT
DELETE
Your framework needs to support all of the above to support the "out of the box" functionality of Backbone. This means that you must specify all of the above routes within your application in order to work with Backbone.
One other thing to note is the "create" and "update" method does not carry post data with the request specifically -- instead it sends a content body with a json digest of the data and expects the server side to properly parse a JSON object and deal with it appropriately.
I say yes to all three assumptions and also agree with #Andy Baird.
Also, the only problem to your project is how to notify Backbone that you have updated the database and you would like it to update itself in the front-end. I can only see two solutions:
1) using Javascript's setInterval() - if you do not need the front end to be updated immediately on DB update, you can check for changes every 1 minute, Backbone knows to only update what has changed and add new stuff but of course this is not healthy to the server if you have 1k active people making repeated request every minute
2) using SocketIO or similar service - this way you can send from the server to Backbone either the entire list of modifications to your DB or a simple 'Please refresh, new stuff waiting'. Check this discussion.

Does php mvc framework agavi use CRUD compliant to REST?

The agavi framework uses the PUT request for create and POST for updating information. Usually in REST this is used the other way around (often referring to POST adding information while PUT replacing the whole data record).
If I understand it correctly, the important issue is that PUT must be idempotent, while POST does not have this requirement. Therefore, I wounder how creating a new record can be idempotent (i.e. multiple request do not lead to multiple creations of a record) in particular when usually the ORM uses an id as a primary key and the id of a new record would not be known to the client (since it is autocreated in the database), hence cannot be part of the request. How does agavi maintain the requirement of idempotence in light of this for the PUT request.
Thanks.
PUT can be used both for creation and for updating complete records. POST is usually used for partial updates and related operations as well as for creating a new type of record on the server without specifying a URL for the resource (e.g. POST to /articles/23/comments returns a 201 status and a Location: /articles/23/comments/283136 header). So in your case (with a sequence/autoincrement ID), you would use that approach.
However, HTML (and thus web forms) is different. It only knows GET and POST, not DELETE and PUT. For deletion and updating operations, it overloads the POST method.
That's why Agavi, by default, maps POST to "write" and GET to "read" - it's the most common use case, and "read" and "write" were chosen because they are relatively neutral and also in a way represent the safety aspects of GET vs POST (safety as in "GET can be called without side effects" and blah).
You can change the mapping of verbs for the AgaviWebRequest implementation in factories.xml; refer to the Agavi users mailing list or the IRC channel if you need help with that (or ask away here). A lot of people on the IRC channel are also quite experienced with URL scheme design in case you need more help with making your API pretty.
Instead of thinking of PUT as creating, think of it as "putting". You put a resource at a URI (ie send an entire resource to a URI).
PUT http://example.com/articles/1
If you repeat this (send the same entire resource to the same URI) you get the same result and you haven't changed the resource at that URI, that's what makes it idempotent.
If agavi's implementation of PUT is idempotent then it is implementing PUT correctly. Otherwise it's not.
PUT can be used to create a resource, except that if the resource already exists (or has already been created by a previous PUT) it will just update it. POST should not update resources, however, if this is simple CRUD. Note that the HTTP verbs do not have a defined mapping to certain actions necessarily, since they're useful for a lot more than just CRUD.
Also note that this question has nothing to do with REST - just proper HTTP usage. So please remove the REST tag.
I've had this problem before. This can be solved by changing the factories.xml

Categories