I'm thinking about using CodeIgniter for a new project. I was reading the user-guide for CI and I noticed a few things. In all their examples, they seem to put all the logic in the Controller and just use the model to get and set data. I like to put all my logic in my Model.
Are all of their functions universal to all 3 parts (model, view, and controller) or will there be problems if trying to do logic in the model as opposed to the controller.
Also, are all variables accessible to all 3 parts (model, view, and controller). If I wanted to know if a user was logged in within the view, would I have to pass that information to the view from the controller or is it already accessible within the view?
Also, I noticed that session data is stored within cookies, even though they are encrypted. Is the encryption safe enough to use, beause im more used to using sessions. Also, how long are these cookies stored by default? I was a little confused about that part, if anybody can clear that up.
If you have any other tips to help my learning this new framework, I would appreciate it.
Thanks
EDIT: I like to use Fat Models and skinny controllers, so that I can use the same functions in more than one place.
Just read about Kohana, I think I'll look more into that
You have made a lot of assumptions from some basic examples which are not entirely correct.
Controllers should contain interaction logic.
That means that your Controllers should just be saying what models, views, libraries, etc should be used based on what the user is doing.
Models contain data logic.
This can be your business logic, tax calculations, all sorts of data related work. The examples in the userguide suggest just using Models as a "dump wrapper for the database" but you can do anything with them. The model simple represents your data and the rest of your application should not care where it came from.
My models contain a mixture of XML file parsing, REST method calls and of course, some ActiveRecord queries.
Views just show stuff, therefore has no idea about login/logout state. You would of course need to tell it this from your controller (or from global code such as MY_Controller, which IMHO almost every decent sized application needs).
Sessions stored as encrypted cookies are perfectly safe. They would only be able to decode them if they knew your application encryption key, but that is very unlikely unless you have not set one; in which case you only have yourself to blame.
If storing sessions in cookies is not your cup of tea, you can store session values in the database to keep them even more secure, or grab a different session library to work with.
The thing to remember with CodeIgniter is that it only suggests ways to work, if you don't like it, extend, override or replace.
they seem to put all the logic in the Controller and just use the model to get and set data.
CodeIgniter expects very little logic in its models, and instead gives you a very dumb SQL wrapper for returning simple arrays of POD types to represent your data. It even puts a lot of validation code into the controllers, which (in my opinion) is incorrect and repetitive. I've rolled my own solution for Rails-style in-model validation and dynamic find method, allowing things like
// inside model:
// username must be 8 to 25 chars long
$this->validates_length_of('username', 8, 25);
// dynamically handled via __call()
$this->User->find_first_by_username('john'); // Return object or null
$this->User->find(); // select *
$this->User->find_by_group('admin'); // return 0 or more records
but AFAIK there isn't any built-in way of doing similar things with CodeIgniter.
Also, are all variables accessible to all 3 parts
No; you have to manually pass your variables from your controller to your view, and there is no sharing of variables with models/controllers or models/views.
I believe the method suggested by CodeIgniter:
<?php
function users() {
$data['users'] = $this->User->find();
// must use $data['users'] for controller logic; verbose and annoying
$this->load->view('users/index', $data); // $users defined for view
}
?>
can be improved by using PHP's compact keyword:
<?php
function users() {
$users = $this->User->find();
// now we can use $users more easily
$this->load->view('users/index', compact('users'));
}
?>
I noticed that session data is stored within cookies
CodeIgniter can store session data in a database; see $config['sess_use_database'] in config/config.php. There are other config settings in there that pertain to the lifetime of the session cookie.
I'm inclined to say that the only thing CodeIgniter does well is their documentation, read more about session configuration and their implemntation of active record (really a language-independant SQL wrapper which has nothing to do with the Active Record pattern)
CodeIgniter is based on the Model-View-Controller development pattern. The model represents your data structures and should be used just for that.
I would follow that convention, especially if you want to learn the new framework.
AFAIK, the session id is encrypted and stored in cookies, but session data is stored in local database.
The main idea of MVC is such division. But models are not restricted to just direct access to data, they can perform various data manipulation. The idea is to represent objects(and sets of objects) stored in database as php objects, so if it seems logical to have some function in you object - it's as much logical to have it in your model.
I think the misunderstanding here is that so many web applications have hardly any logic outside some simple data processing, that developers are getting used to it.
Related
I am creating an application with the help of codeigniter. People can register and log in to the application. User can view each others profile as well.
I noticed that I am using the functions like getting a username from user id, email from user id...... quite a lot. The common thing I noticed about all these functions is that they all are supplied with a user id as its parameter. All these functions are in the controller.
I was thinking to put all these functions in a helper file. As it is quite easy to call the function from helper file. Since, I am using these functions quite a lot, I can directly use them in views if they are from helper file.
Now my question is, is it safe to put these functions in helper instead of controller from the security point of view ? As these functions directly access the database to get the crucial information from the users table.
I know this question might be regarded as very much to a opinion based. But at the same time, I am trying to get the exact answer whether it is safe or not.
From a "secure" standpoint, they're both in your code and not visible by the end user. From a testing standpoint though, code that accesses your database is best tested when it's isolated from code touching other components like UI (which is generally in the controller). This sort of thing would normally go into the model or model helpers in an MVC pattern.
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.
I am working with an MVC framework (specifically, PHP's CodeIgniter). I am trying to follow "best practices" as much as possible, but I don't have much experience with MVC. Is it bad practice for me to retrieve data from a session within the Controller? Should I "ask" the model if, say, a particular session value is 'foo' or 'bar', or should I do that directly inside the Controller? I'm thinking I should do it inside the Model since the session data is technically data, but I just want to make sure. To be clear, I don't store the session data in the database at all, so I'm not running a query.
Models typically handle all domain objects that are persisted to some sort of long-term storage. They may or may not have transient values in them that have to do with the particular application's use of them.
Controllers should be querying any data they need in order to correctly route and display information. It may help to create a 'Service' layer that operates directly on domain objects (your model) and provides an API for Controllers to use. The main thing to not include in Controllers is business logic.
It would be reasonable, for instance, for the Controller to grab the referring page and do something with that data in regards to the user flow. However, apart from validation, it probably shouldn't, say, examine the amount of money being transferred between accounts - it should just pass that on to a service object that instantiates and works with the correct domain objects.
Questions to ask about logic you're putting into a Controller:
Does this logic help figure out what Model objects I need? If not, it shouldn't be here.
Does this logic help figure out what View objects will be used to construct the response to the user? If not, it shouldn't be here.
I am working on this app that accesses session variables in the model layer. This just seems wrong but am willing to be proven wrong. Maybe not wrong but, in most places in app, session variables are handled in controller and passed in as arguments but, in other places, the session value is just accessed. Am I wrong that this seems like bad practice?
edit:
one reason I don't like sessions in models is that it seems to make it more complex to test. Keep it as just params passsed to functions and then recordset passed back.
thx
It depends.
The way I think about this is such:
A Model represents your data layer.
most of the time that data layer will be DB Table based
The Session is just another data storage medium.
Conclusion: If the data that your model represents is stored in the Session, than it is OK to access that data from within the model
An example is a Session based shopping cart. My cart's objects are models of my session data.
Controller shd do a check weather session exist or not before using the model which uses that session inside it .
No it shouldn't. The storage type, should be apart from your business logic. For example:
I have one simple plug-in that perform the access check and put the user object on the registry. So, instead of access session, the model have access to the registry, which is well defined.
$User = Zend_Registry::get('User'); // User model object
From the theoretical point of view, everything should be accessed through data mappers. In the future, if you change from session storage to something else, you'll need to update it just in one place. Your models do not need to know from where the data came from.
If you are taking more than one path to get your data, probably this will cause some problems when your application get large.
The OOP and layered systems approach suggestion is to created specialized objects and layers and keep things simple preventing specific actions to be spread all over the code.
But again, you do not need to change that unless you see advantages.
Keep in mind that sometimes refactoring is more efficient than try to predict everything.
What's stored in the session variables? If it's simply 'logged in? Y/N', then they probably don't need to be part of the model layer. If, however, it's more complex than that, they are probably inextricably linked to your business model and should be treated as such.
The examples at the bottom of the Zend Test documentation show how to test the full MVC using a login function. Presumably you could do the same when testing models?
I've been working on creating my own MVC app in PHP and I've seen a lot of differing opinions online about how exactly this should be set up. Sure, I understand there seems to be a general "It's MVC, it is what you make of it" approach, but I'm running into 2 seemingly conflicting viewpoints.
A little background on my app: I'm using smarty as my presenter and an object-oriented approach. Seems simple enough, but I'm trying to figure out the ubiquitous "what is a model" question.
If I take a look at some tutorials and frameworks, they seem to view the model as strictly a class that inherits DAL methods from an abstract class, with a little bit extra defined in the class itself as your data needs differ from object to object. For example, I might see something like $productModel->get(5) that returns an array of 5 products from the database. So what if I need to query multiple models? Do I store all of the data in the controller or an array and pass that to the view? Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view? This seems bad, especially because I then have to pass in things like "controllerName", "controllerData", and my View::render() method gets hugely bloated with parameters, unless I pass in the controller itself. Maybe I'm missing something here.
Let's say I want to make a login that queries a users table. Login is a model or a controller, depending on certain implementations I've seen online. Some implementations (I'll call this method 1) make a LoginController with method login() that might do a comparison of $_POST and what's returned from the user model instance $user->get(1) to see if a user is validated. Or maybe login() might be a method in a default controller. On the flipside, an implementation (implementation method 2) that resembles more of a Joomla approach would make a Login model and declare all of the actions inside of that. Then any data that needs to get assigned to the view would get returned from those methods. So login->login() would actually check post, see if there's a match, etc. Also the User model would probably be instantiated inside that model method.
My feelings about 1: The controller is fat. Additionally the controller is storing data pulled from models or passing in ten thousand variables. It doesn't seem to jibe with the idea that the model should be passing data to the view that the controller should be blind to. Also, let's say I want to wrap everything that is in a specific model handled by a specific controller in an outer template. I'd have to copy this template-setting code all across my controller functions that interface with this model. It seems grossly inefficient.
My feelings about 2: It doesn't make for having actions that aren't model methods. If I want to go to my site root, I have to make an index model or something that seems like overkill in order to have a model that passes data to the view. Also, this doesn't seem to be a very popular approach. However, I do like it more because I can just do View::render(mymodel->func()) and ensure that the data is going to be passed back just the way I like it without having to crap up my controller with code merging a thousand query results together.
I've waded through far too many religious arguments about this and want to know what you guys think.
I've built my own framework in the past too so I know what you're going through. I've heard the saying "build fat models" and I agree with that -- as long as the main goal is to return data. I considered the controller to be "The Overlord" as it manipulated data and directed where it should go.
For a login controller i might create something it like...
Post URI: http://example.com/login/authenticate
LoginController extends ParentController {
public function authenticate() {
$credential_model = $this->getModel('credentials');
// Obviously you should sanitize the $_POST values.
$is_valid = $credential_model->isValid($_POST['user'], $_POST['email']);
$view = $is_valid ? 'login_fail.php' : 'login_success.php';
$data = array();
$data['a'] = $a;
// .. more vars
$this->view->render($view, $data);
}
}
In my opinion data should always flow from the model -> controller -> view as it makes the most sense (data, manipulation, output). The View should only have access to what it has been given by the controller.
As for this...
Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view?
Well I would imagine you're building a 'base' or 'parent' controller that gets extended off of by your dynamically called controllers. Those child controllers can have properties that are needed for for the view to render -- honestly I'd need an example to go further.
Hopefully this helps a bit. If you ask more specific questions I might be able to give a better thought out opinion.
If you're writing your own app, I think the best solution is to do it yourself and find out.
Ultimately, whatever makes the most sense to you, and whatever makes it easier for you to conceptualize your app and quickly add to or change it, is going to be your best option.
If one way is "wrong", then you'll find out through experience, rather than someone else telling you. And you'll know the entire situation that much better, and know EXACTLY why one way is better.
What helped me when I was writing my own framework in PHP was, strangely enough, CherryPy. It made the concept of an object-oriented web app so simple and obvious, and I enjoyed using it so much, that I modeled the basic structure of my PHP framework to imitate CherryPy.
I don't mean to imply you should learn CherryPy. I mean that simplicity, clarity, and enjoying developing with your own web app go a LONG way.
If I were to give one piece of specific advice, I'd say try to avoid retyping code; write your code to be reusable in as many situations as possible. This will not only be good for your app, but for future apps you may write or work on.
You might check out Eric S. Raymond's Rules for Unix Programming. I think they're definitely applicable here.