CodeIgniter Model / Controller and UserID - codeigniter

My Models in CodeIgniter need to check that a user is authorised to perform the given action. Inside the Models I have been referencing using $this->session->userdata['user_id'].
My question is - should I be setting a variable to $this->session->userdata['user_id'] in the Controller and passing this to the Model, or simply checking it inside the Model ?
Does it even matter ? I suppose passing $user_id into the function would make it (slightly) more readable. What are the arguements and recommendations for / against ?

You can choose between data that is fundamental to your application and data that is incidental to a given model member function. Things that you use everywhere should be guaranteed (base members, globals, etc.), and things used only in the current function should be parameters. You'll find that using implied variables (like $this->session->userdata) in many places in your models and views will become spaghetti quickly, and will be unpredictable if you don't bootstrap them properly.
In my CodeIgniter projects, I add a custom base model and controller that inherit from the CI framework, adding their own member data that is used everywhere in the app. I use these base classes to provide data and functions that all of my models and controllers use (including things like userID). In the constructor of my_base_controller, I call the CI base constructor, and set up data that all of my controllers and views need. This guarantees predictable defaults for class data.

Strictly speaking $this->session->userdata['user_id'] belongs to the controller.
Models deal with data only... controllers, by definition control the flow of the data...
and authentication is a form of data control... (IMHO)
Codewise, I follow this procedure
class MyControllerName extends Controller{
function MyMyControllerName(){
parent::Controller();
$this->_user_id=$this->session->userdata['user_id']; //<-- define userid as a property of class
}
}
And then, say one of my functions foo() requires authentication.. I would do this
function foo(){
$this->_checkAuthentication(); //should short out if not authenticated
//rest of the function logic goes here
}
the _checkAuthentication() can be simplistic like:
function _checkAuthentication(){
if(!isset($this->_user_id) && $this->_user_id<=0){ /or any other checks
header("Location: ".base_url()."location_of/user_not_authorised_page");
exit;
}
}

Related

How do I pass arguments / parameters to model

Following the tutorial how to create a joomla 2.5 component I'm stucked to pass arguments from view.html.php to my model.
$items = $this->get('TableData');
and my TableData model would expect to get the following arguments
public function getTableData($table, $index_column, $columns) {}
You can not do this using the view's get method. Instead you would have to grab the model into the view and call the function directly in the view:
$model = $this->getModel();
$items = $model->getTableData($table, $index_column, $columns);
Alternately, you could create different entry points in the model that would be able to figure these input options either from state information or preset. Many would argue that this would lead to a better application design, since using my code above is putting what should be model logic in the view.
This is just an addon to David's answer.
Because most of the data usually comes from POST / GET methods, depending on your application, you may want to look at how loadFormData() from loadFormData JModelForm or populateState gets overridden in specific Joomla components.
Basically the state of model is set directly from POST data, using JInput.
Also, although it's not a rule or something, 3 parameters is a maximum I would pass to a method. For flexibility I would rather pass an array with can be later extended without changing the method signature.

codeigniter model inside a model, and model inside controller

I have actually 3 questions, but similar to each other:
I have a model called Permissions. and I need another model ie. Users. what is the proper way to user Permissions inside Users.
You get what I mean above, is that weird or is there another better way to do it.
This Permissions model, will be used globally throughout my application, what is the way to use it in other models or controllers (similar with 1st question)
One way is to get the global variable for the main CodeIgniter object, and then load the model from that object rather than $this:
class Permissions extends Model
{
function MyPermissionsFunction()
{
$ci =& get_instance();
$ci->load->model('users');
$ci->users->MyUserFunction();
}
}
You can also sidestep the issue by combining your models together into one larger model. The main reason to keep them separate is to only load the models that you need; if you nearly always use both together (as would make sense, for Users and Permissions), you may be better off taking this approach.

Access controller method from inside a model

How do I access a controller method from inside a model?
You don't.
Although it is technically possible, if you think that you need to, it suggests a flaw in your application's design.
The Controller layer is the backbone of you application and meant to handle requests from the user, talk to the Model layer, and stitch together the output in the View. Your Model layer should be blind to the Controller and View, but deal with data manipulation only. This is an over-simplified explanation of the MVC pattern (you can find resources for that elsewhere).
Your Codeigniter models should be reusable from any controller, and not dependent on them. There are many solutions to solve whatever problem it is that you have: You can pass data into a model in a number of ways, or you can use the result of a call to a model's method to perform an action in your Controller.
You can use like this:
class some_model extends Model
{
function getController()
{
$controllerInstance = & get_instance();
$controllerData = $controllerInstance->getData();
}
}

Where does Zend_Form fit in the Model View Controller paradigma

The Zend Framework is mainly meant for MVC use. One of the very usefull components is Zend_Form.
I have a bit trouble finding the place of Zend_Form. Is it part of the view, model, or controller and which responsibilities should I give it.
The thing is, Zend_Form does two things: decorate and render the form and validate it. The first is a real view task, the second a real model task.
Now the most common use seems to be to have the forms interact with the controller only, effectively putting both tasks (rendering and validating) to the view/controller.
Another option given by Matthew Weier O'Phinney is to attach the form to your model, and adding the later view options in the controller.
So, I'm doubting. Where in the MVC pattern should I place Zend_Form and how should I use it?
Edit Good answers so far, thanks! I will be awarding the bounty an hour or two before it expires, so please give an answer if you have some more thoughts!
Zend_Form can be viewed at different points. It can't be considered at all as part of just one layer of MVC pattern.
First of all Zend_Form use decorators and view helpers to render the form, at this point it is part of view layer.
Then, Zend_Form does part of the model job filtering and validating the content.
We know that Controller layer render input from the view and pass it to the model. Actually, the controller layer decide which resource to load from model layer and then perform the corrects calls.
When you call Zend_Form from controller layer, you can consider that you are calling one model resource to perform valitations and filtering actions and decide whether or not this is a valid input. For example:
public function newAction()
{
$form = $this->getForm();
if($this->getRequest()->isPost())
{
$formData = $this->_request->getPost();
if($form->isValid($formData))
{
$Model = $this->getModel();
$id = $Model->insert($form->getValues());
}
}
$this->view->form = $form;
}
Tie Forms to the model can be considered a good pratice because when you are performing filtering and validation actions you are on model layer. So, as Matthew proposed:
class Model_DbTable_Users extends Zend_Db_Table
{
protected $_name = 'users';
protected $_form;
public function getForm()
{
if(!$this->_form)
$this->_form = new Form_User();
return $this->_form;
}
public function add($data)
{
$form = $this->getForm();
if(!$form->isValid($data)) return false;
if($form->getValue('id'))
{
$id = (int) $form->getValue('id');
$this->update($form->getValues(), 'id =' . $id);
}
else
{
$id = $this->insert($form->getValues());
}
return $id;
}
}
From the standard directory structure we can see that Forms aren't in the model folder nor in the view folder because Zend_Form is a specific class that tie many resources and layers together. If you check the Matthews post you will realize that this is exactly what is being said when the action url is set on the view script and the form is tied to the model.
Finally, you can analyze your context and pick up one of these two approachs.
Currently, my choice is to tie forms to models. Looks nice! And make a lot of sense to me.
IMO, Zend_Form is designed to wear multiple hats. It is, in fact, a bridge between the view and model with a giant support beam from the controller.
Instead of assigning a Form to a Model, consider assigning Model(s) to a form.
In the Model layer, you can have a a getFormInputs method that could return the Elements needed to input data. The model doesn't care what form is going to use it, it just makes it available to any from that wants them.
Now in your form layer, make a setupInputs method that will loop thru an array of models to grab all the inputs. If there was only one model, add the inputs to the form. If there was more then one model, make sub forms.
Your controller will initiate the form and pass the values back to model (see Keyne's newAction method)
Zend_Form does often feel like the odd man out. I think everyone's mileage varies.
Lately, most of my administrative interfaces have been very drag + drop AJAX-y, and they require a good deal of html and javascript - actual form elements are sparse. So I chose to eschew a lot of the features of Zend_Form and use it as a fancy view helper with filtering. All my validation is done on a separate layer in the model.
I think O'Phinney's idea makes a lot of sense as well. Here, he's choosing to think of the form almost as a component of the domain object - where he can add business logic. This sounds just fine, as long as you're careful to keep all the view logic for the form separated. As he notes, it's about making semantic sense. There isn't necessarily a hard and fast rule.

MVC: pass model / model data to a view from a controller?

If a view needs to acces data from a model, do you think the controller should:
a) pass the model to the view
b) pass the data of the model to the view
c) neither; it shouldn't be the controllers concern. Let the view access the model directly to retrieve the data. Only let the controller give some parameters the view needs to filter the data from the model.
d) it depends on the situation.
e) none of the above, but [...]
Thanks
After some debate in the comments to an answer that was deleted by the user, maybe this needs clarification. My view of the MVC architecture is biased towards that of the Zend Framework (php) in which an action in a controller by default has a default view assigned to it. So it's not so much the model that dictates which view is approporiate, but rather the controller. Do you feel the model should dictate what view is appropriate? The only way I see fit to let the view be build based on a model, is by letting the controller pass the model to the view. Are there other techniques to let a view access a model without the controller being involved? Or is it perfectly fine to let a controller pass the model to a view, so that the view can be build based on the models attributes?
e) None of the above; pass in a view-optimised "ViewModel".
Example in ASP.NET MVC:-
public ActionResult Details(int id)
{
Product p = ProductService.GetProductById(id);
if(p == null) { return RedirectToAction("Index"); }
ProductViewModel model = new ProductViewModel(p);
return View(model);
}
both a) and b) "will do" subject to d). Never ever c).
Typically, the ViewModel just encapsulates the Model (if nothing complicated is going on, your view could access the model directly via ProductViewModel.Product). If the view needs to do anything complicated with the Model however, it's the ViewModel's responsibility to do that, rather than the responsibility of the Controller, or the View.
This keeps your concerns nice and segregated. Your Controller doesn't care exactly what specific data your View needs (beyond the fact that it's rendering some Details of a Product), or especially what format your View needs that data in. Your View doesn't depend on the implementation details of your Model. Your Model doesn't have to concern itself with how it's being Viewed. If you have two Views rendering Products (e.g. Create, Edit, Summary, MoreDetails etc), those Views can have different ViewModels to expose only the data that each specific View needs, so your Views aren't depending on eachother. Lovely :)
Some further reading from various viewpoints:-
http://www.thoughtclusters.com/2007/12/datamodel-and-viewmodel/
http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx
I think ViewModels are a particularly .NET thing, but I see no reason at all why the pattern can't be used in PHP.
Hope this helps.
Ideally, it should "pass the data of the model to the view" so the view doesn't need to know any explicit structure of the model and thus be more reusable and designer-friendly.
But practically, "pass the model to the view" works as just fine. Most of the time you will need a new view anyway because clients never share favorite colors (if you know what I mean :-) so views re-usability doesn't justify having a lot of tedious code required to copy data from the model to the view.
What you should concern more about is the modularity of the controller itself, since many websites do share common functionalities (controllers) such as web forums or a news listing but not looks (views)
This is late I know, but I'm having this issue on a project I am working on. I started with a) - for simplicity - and now running into road blocks.
I am coming around to this method:
e) None of the above; pass in a view-optimised "ViewModel".
because it avoid bloating both your model classes (instances of which are "transaction objects") and your views. For example, you may need to render a number with a specific number of decimal places (this is the problem I am having now).
With an intermediate "ViewModel" this is easy - you just write the relevant ViewModel "getXXX" method to return the number formatted how you wish.
If you just pass the model directly into the view, you will need to specify it in the view every time you use this figure (going against DRY - don't repeat yourself), or alternately, add a rendering method to your model classes (which goes against a class being for one purpose only).
Cheers
a) pass the model to the view
Otherwise the controller is manipulating the view via screening the model. This is what would happen in "b) pass the data of the model to the view". The b) option doesn't really even make sense in the pure MVC pattern. After all, the model IS the data. If the model is changed for consumption, a view has been applied, whether you choose to do it in the controller and pass it off as a controller function. What happens when you have a different view? Does the controller screen its data differently? You soon have two views for model, the controller sub-view and the view itself.
For me that's e).
As already mentioned here, ideally the view and the model are decoupled. The way I prefer to implement this is to have a viewHelper for a model. This has the API the view can use to get the data. Now views are not affected by changes in the model and the view doesn't need to 'get' the internals of the model. These are hidden away by the viewHelper.
example:
class Post {
public function export(ViewHelper $helper) {} // I try to avoid getters when I can
}
class PostViewHelper {
public function getTitle($parameters) {} // title of current post in the loop
}
class PostView {
private $helpers = array();
public function loadTemplate($path) {}
public function addHelper(ViewHelper $helper, $name) {}
public function __get($key) {} // if exists $this->helper[$key] etc
}
in a template
<h1><?php $this->post->getTitle(); ?></h1>
You may want to implement this differently. But my point is in how the view and the model are decoupled, introducing an intermediate viewHelper wich creates the view/template API.
I don't think it's that complicated. a or b.
The controller's job is to manage the relationship. It finds the model and view and provides the view all the model data it needs to do its job. That's it. MVC doesn't dictate the exact form the data takes.
(a) Start simple. It's pretty natural to pass the model objects directly to the view. If you have a page about a Foo, just pass the Foo.
(b) But at times-- and only at times-- you create a value object / DTO to get the data to the view (called a ViewModel above). Do this when there's a mismatch between the view and the native model, such as summary views. If the view is presenting a summary of 1,000,000 objects, you don't want to hand the view the model objects; you want to hand the view a summary of the 1,000,000 objects.
And the exact implementation really depends on the language and framework you are using. But I think these guidelines are a good start.
uhh b.
i dont really see the difference between a and b other then some technicallity of how you will be passing data.
usually you pass a map of data to the view with some data from the model

Resources