So, I like CakePHP and use it lots. When 2.0 came out, I was pleased to see the AuthComponent be made available throughout your whole application as a static class, which makes lots of things much easier - i.e. you no longer have to pass user data as an argument to model methods.
Recently on a project, I have perceived the need to access methods of the SessionComponent from a Model. Specifically, when a user logs in, some checks are performed to see if the user has a valid subscription to the site. This is all done in the model. If the user no longer has a valid subscription, there are a few reasons why that might be. It seems easiest to return false from the model, and at the same time set a flash message giving the reason for the expired subscription. Rather than return an array something like this:
array('status' => 0, 'message' => 'You\'re not welcome here anymore')
which needs interpreting in the controller.
There are other times I have wanted to deal with sessions in models, but this is the example that came to mind.
So, I'd like to know, am I right in wanting to access the SessionComponent in models? Should I just use $_SESSION directly when I have this need? Or am I doing things wrong - are there better ways to code?
you can always use
CakeSession::read()
anywhere in your application. so also in the model.
see previous posts like Reading a session variable inside a behavior in cakephp 2
but be adviced, that you should try to avoid it if possible.
models are supposed to be as stateless as possible - mixing them with sessions makes that more and more blurry.
According to CakePHP cookbook:
Usage of the $_SESSION is generally avoided in CakePHP, and instead
usage of the Session classes is preferred.
There are several different configurations where you can store session data, f.ex. in the database. So, by using CakeSession changes to session configuration will not affect every place where you access session data.
I would advice not to use SessionComponent from the model. Better pass parameters to the model with necessary data. Take a look at Understanding Model-View-Controller.
Passing session control to the Model violates MVC. You should use the model to make the decisions and the controller to reflect those decisions to the application. In a correct MVC enviroment the Model won't even know you are using sessions much less manipulating it.
Also, using the $_SESSION var violates the framework encapsulation. If you find yourself needing to do that, yes, you went wrong somewhere.
You can write and read data in session in model by using Authcomponent and session
App::uses('AuthComponent', 'Controller/Component');
App::import('Component', 'Session');
and you can write and read data using following functions
CakeSession::write('Auth.User.id', '1');
debug(CakeSession::read());
Related
I've been working on an API for awhile now that has a sort of 'soft' api validation so I can use Backbone more easily on the front end. Basically the design principal has always been to only validate and update the attributes sent back that we care about. On the backend, I use the model's fillable array to limit this after validating the input array. This way we don't have to annoy people when they accidentally send back model data that we don't allow them to touch as the docs clearly state whats fillable. People seem to enjoy working with the API.
What we run into is a problem because we want to use things like 'createOrUpdate' for our backend stuff that's creating or updating models automatically. Basically we end up adding things to fillable that go against our user facing input validation. Trudging around the docs I came across 'forceFill' and other various 'force' methods, but noticed that they are missing from the more magical methods like 'createOrUpdate'. Seems like they should be methods, or at least boolean flags that can be passed to the methods to force, and maybe these options are built into Laravel 5+?
Before I go ahead and write my own methods in the base, I just wanted to ask if this is already built into 4.2 and I'm just missing it? I also wanted to create this thread as it may be informative to people still confused by how Laravel's mass assignment works.
If I don't get any feedback I'll probably just delete it.
Model::unguard(); is added in 5.1 https://laravel.com/docs/5.1/seeding available in 4.2.
You just call it before you create the object, and then you can fill any fields using createOrUpdate(), firstOrNew(), create() etc.
Correction, here it is in the L4.2 API: https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Model.html#method_unguard
see also: Model::reguard()
I've worked with OOP for a while now, and have gotten into the habit of creating classes for 'things', such as person, account, etc. I was coding in Java for this.
Recently I begun to work with MVC (in PHP), and I've come to realise that, contrary to what I originally thought, the model is not like an OOP class - feel free to correct me if I'm wrong, but my understanding is that the model is simply an interface between the controller and the database (maybe with data processing - more on this below). My reason for thinking this stems from my recent messing around with the CodeIgniter framework for PHP. CI doesn't allow for instances of models. Rather, it's a singleton pattern, and in most tutorials I've seen, it's used only for database queries and sometimes some static method.
Now, coming from OOP, I've gotten into the habit of having classes where the data is stored and able to be manipulated (an OOP class). My issue is that in MVC, I'm not sure where this takes place, if it does (I initially thought 'class' was synonymous with 'model'). So, I guess what I'm looking for is someone to explain to me:
Where does the manipulation of data (business logic) take place? I've read many articles and posts, and it seems some prefer to do it in the controller, and others in the model. Is one of these more correct than the other in terms of MVC?
Where/how do I store data for use within my application, such as that from a database or JSON/XML files returned from an API call? I'm talking things that would usually be attributes in an OOP class. Does this even still take place, or is it straight from the database to the view without being stored in variables in a class?
If you could link me to any guides/sites that may help me to understand this all better, I would appreciate it.
Representing MVC in terms of classes, you can say that:
Model - A class which stores/provides data.
View - A class which provides functionality to display the provided data in a particular fashion.
Controller - A class which controls that how the data is manipulated and passed around.
MVC design is adopted to provide facility to easily replace any of the module (Model/View/Controller) without affecting the other. In most cases, it is the view which gets changed (like same data represented in form of graphs, chats) but other modules must also be made independent of others.
This is an interesting question, and you often hear contrary things about how clean and stripped down models should be vs them actually doing everything you'd think they should do. If I were you I'd take a look at data mappers. Tons of people much smarter than I have written on the subject, so please do some research, but I'll see if I can summarize.
The idea is that you separate out your concept of a model into two things. The first is the standard model. This simple becomes a property bag. All it does is have a state that often reflects your database data, or what your database data will be once saved, or however you use it.
The second is a data mapper. This is where you put the heavy-lifting stuff. It's job becomes providing a layer between your pure model, and the database, that's it. It talks to the database, retrieves data specific to your model, and maps it to the model. Or it reads the model, and writes that data to the database. Or it compares the model's data with that of the DB.
What this does is it allows each layer to concern itself with only one thing. The model only has to keep a state, and be aware of its state. Or have some functionality related to the model that does not involve the database or storage. Now the model no longer cares about talking to the database which is hugely freeing! Now if you ever switch to a different database, or you switch to cookies or storing things in files or caching or any other form of persistence, you never need to change your models. All you have to change is the mapping layer that communicates between your models and the DB.
I'm really confused by this... still.
I asked a similar question to this a while before, but i'll ask it even simpler now.
I see this in a lot of samples and tutorials. How could you put [Bind(Exclude="ID")] on an entire Model, and expect to do Edits on the model? If you get pack all the properties of a model on a POST but not the ID, then how do you know which ID to edit?
Even if i'm using ViewModels... i'm probably creating them without IDs. So in that case... also... how do I know which ID was updated on an Edit?
Yes, i understand that there is a "security" element to this. People can hijack the ID... so we need to keep people from updating the value during a POST. But... what is the correct way to handle edits then? What's common practice?
I feel like i'm missing something VERY trivial.
In MVC requests are processed by the model binder when the client makes a request. If you include models on your controllers then, as far as I'm aware, you actually have to specify the model you wish to bind to by prefixing your arguments with the model name (unless you only have one argument which is the model)
SomeModel_ID
Now, in some cases you might want to exclude certain properties from being bound to because they pose a security risk, which you seem to be happy with as a concept. We will exclude ID on the model, preventing any client request from posting this value in plain text.
Now why might we exclude an entire model? Well not all controller arguments are pre-processed by a model binder. RedirectToAction for example does not pass through the model binder, so it is conceivable in this instance for you to create a new model in a POST controller action, and redirect to a GET controller action, passing along a sanitised model. That model cannot be populated by the client, but we are free to populate it ourselves on the server side.
The only time I bind to a model is when I have a view model and an associated editor for that model. This makes it really easy to inject a common editor into a page and to encapsulate those properties. If you have to exclude certain properties from being bound to I would argue that you are doing it wrong.
Update
Following your comments I think I can see why you might be confused. The model bind excluder prevents the client from ever setting a model property. If you need this property to do your updating then you simply can't exclude it. What this does mean then is that the user could potentially post back any ID. In this case you should check that the user has permission to be modifying any objects or database records associated with this ID before serving the requested update. Validating the arguments is a manual process. You can use data annotations for validating inputs, but this isn't likely to help very much with access permissions. It's something you should be checking for manually at some stage.
You know the ID because it's passed to you through the page address. So:
http://yoursite.com/admin/users/edit/20
Will populate your ID parameter with 20. If it's used in a POST (ie, the information is filled in), just manually fill in the ID field and pass it to the database controller in whatever manner you have devised.
This is also immune to (trivial) hijacks because if they were to write some other ID besides 20, they wouldn't be updating the user with ID 20 now would they? :)
I am new to MVC, CodeIginter. Instead of getting things easy, it needs lot of code to be written for a simple application. These are might be happening becouse I am new. So I have few confusions about this thing. Any kind of help is appreciated.
1) Methods are written in one controller can not be accessed in another controller classes. I have to write a new function for the same functionality.
2) To create website administration panel (back-end) in none mvc panel, we usually create it in a new folder. Is this thing possible in CodeIgniter? If not what about the admin (back-end)??
Let's try to clear some of your doubts about this.
1) Calling a controller's method from another controller is not possible, and it's whtouth meaning by the way.
A controller is supposed to get an action from the URL (which is routed by CI to the right controller for the task) and, based on that, decide which Model and which model's method needs be called to elaborate the data requested.
The model, then, hands back the result of this elaboration to the controller, which , in turns, decides to which view pass this results.
The view, eventually, is structured to get those datas and display them.
SO, as you can see, calling a controllers' method from another controller is nonsense, it would be like going to a page and finding another one instead; if you want to pass to another controller the request...well, there's the redirect for that.
If you find out you have the same functionalities in several moment, think twice:
What is a funcionality? Do you mean somehtin like "display posts" in controller "archive" and "display posts" in controller "news" ? they're hardly the same functionality; they can maybe share views, or models, but that's it.
For functions that doesn't relate to URLs, but involve some further elaboration (which might be wrong to do in Models) and are nonetheless called in a controller, you have library instead. Think at the "form_validation" library, which is called in a controller's method, but has its own peculiar (and encapsulated) functionalies. Ora a "session" library, or an "authentication" library
2) To create an admin panel the easiest thing is: create an "admin" controller (which is accesible then to www.mysite.com/index.php/admin), and put all the administration actions there, in its methods: create_page(), edit_page(), manage_users(), whatever.
In order to avoid people accessing it freely you need to build an authentication system, which, in its simplest and barabone strucutre, might be a check of wheter a session is set or not (maybe a check done at __construct() time).
But you can find nice Auth libraries out there already made, such as Ion Auth or Tank Auth (the 2 most popular to my knowledge)
Hope things are a bit clearer now. See also Interstellar_Coder's comment at this answer if you're interested in the modular HMVC approach.
1) Methods are written in one controller can not be accessed in another controller classes. I have to write a new function for the same functionality.
What's the functionality about? Perhaps you should write a library/helper instead, controller's logic should be limited to request flow or something else but not too complicated. For that, put the functionality in the model, or if more general, in library/helper.
2) To create website administration panel (back-end) in none mvc panel, we usually create it in a new folder. Is this thing possible in CodeIgniter? If not what about the admin (back-end)??
I don't get it, could you elaborate more?
The text is quite long, the question is actually simple and written in bold. The other text is only for trying to explain the problem.
I have recently started to use CodeIgniter for developing my website. Currently, I'm writing a side menu where you can filter the items showed in the view (basic e-commerce functionality).
The idea I had was to have an array in my Shop-controller where I store my filtering values which are passed to and from my filterview, so the filter menu kan handle several types of filters.
The problem is that it seems like the constructor of the controller is run each time the controller is called. I thought that the controller was constructed only once when the user enters the website. I'm pretty new at website devlopment and am mainly a C++-guy, so this seems a bit strange for me.
My question is pretty simple actually: Is it true that the controller instance is created at each call to a controller function? Otherwise, what am I doing wrong to cause the controller instance to be reinstantiated at each controller call...
I hope that my question is not too fuzzy. It is important for me to understand the lifecycle behaviour of CodeIgniter to be able to find a simple solution for this. I would like to avoid using $_SESSION, because I would like to use a OOP like solution.
Is it true that the controller
instance is created at each call to a
controller function? Otherwise, what
am I doing wrong to cause the
controller instance to be
reinstantiated at each controller
call..
Yes, the controller instance is re-instantiated every time you make a call to that controller. In CodeIgniter, there is no such thing as a persistent instance of your controller for each user interacting with your application (unlike single-user apps built in C++). What you do have is session management, where you use Session variables to store data persistent to that particular session between the user's browser and your web server (more). Another way to do this is by using cookies. I personally prefer session over cookies.
There is no harm in using $_SESSION for the purpose of your filter, and it is not against OOP principles. What matters is how you use the data stored in your Session variable once your controller instance has loaded ( that's where the OOP concepts come into play).
Shivaas, the same answer can by safely used with models? What about autoloading models? I mean, autoloading it's just a way to avoid typing $this->load->model('the_model') when needed? There's no way to use singleton pattern without recurring to use session/database?
private $instance;
function init_model() {
if ($this->instance === NULL) {
$this->instance = array();
}
return $this->instance;
}
Once init_model exits, the class instance is destroyed so $instance will be always initialized to a new array()?