Actions

Using multiple models in an MVC component

From Joomla! Documentation

Revision as of 07:42, 28 May 2013 by Wilsonge (Talk | contribs)

Sometimes a view needs to assemble information garnered from more than one model.

With just a single model per view it is usually possible to ensure that models and views follow standard naming conventions and the minimum of code is then needed to give the view the data it needs. In a component called MyComponent if there is a view, called My1 (class MyComponentViewMy1) that requires a model, also called My1 (class MyComponentModelMy1), then no additional coding is required as the controller will automatically associate the same-named model with the view.

If a view requires a different model from its same-named counterpart then the controller must explicitly state the model to be used and pass it to the view. For example, suppose view My2 requires data from model My3 instead of My2. Then in the controller task-method you need to state the required model, like this:

$view = $this->getView( 'My2', 'html' );
$view->setModel( $this->getModel( 'My3' ), true );
$view->display();

Here the JController->getView method instantiates the required view object and the JController->getModel method instantiates a model object. The JView->setModel method adds the model to the view's internal pool of model objects. Setting the second argument in the JView->setModel call to true establishes My3 as the default model for the view.

Notice that you should not call the parent::display() method because that will try to instantiate the view and attach the default model to it. You will need to adjust the code in this example if you need to use a format other than 'html', or a non-default layout. See the code for JController::display to see what you need to do.

No changes to the view code are needed. For example, in the My2 view's display method, these statements

$item1 = $this->get( 'data1' );
$item2 = $this->get( 'data2' );

will call the getData1 and getData2 methods in the default My3 model (class MyComponentModelMy3).

If the view requires data from more than one model, then the above code can be extended easily. For example, if view My3 requires data from models My1 as well as My3 then the controller task-method would look something like this:

$view = $this->getView( 'My3', 'html' );
$view->setModel( $this->getModel( 'My3' ), true );
$view->setModel( $this->getModel( 'My1' ) );
$view->display();

Notice that My3 has been set as the default model for the view in this example, but that My1 has also been added to the pool of models available in the view.

Having more than one model available to the view means that some small changes to the view code are now needed in order to specify from which model each data item should be obtained. Continuing with the above example, the My3 view's display method might have need of data like this

$item1 = $this->get( 'data1' );
$item2 = $this->get( 'data2', 'My1' );

which will call the getData1 method in model My3 (class MyComponentModelMy3) and the getData2 method in model My1 (class MyComponentModelMy1).

Notice that it is always the controller's responsibility to determine which models are required by a view and to instantiate and pass the required model objects into the view object.