Part I: Component entry point
As i said before, Joomla framework will access the component through one single file. This file needs to have the same name as the component (not as the component's folder). A demo for this step was done the the previous post, and we'll take it from there, so it's a good idea to go and download the hole zip file as we'll work on that
Ok, we see that our component works so far. Let's delete the contents of the entry file {joomla_server_path}+/components/com_+{component_name}+/+{component_name}+.php/joomla/server/path/components/com_blog_tutorial/blog_tutorial.php and put this
//this will load our base controller
jimport("joomla.application.component.controller");
//get the instance of our controller
$controller = &JController::getInstance("Blog_tutorial");
//execute the controller
$controller->execute(JRequest::getVar("task"));
$controller->redirect();
Typically this is all there's needed in the component's main file. It basically loads the controller and executes the specified task or the default task ('display') if none is specified, then redirects if redirect instruction is set.
Part II: The controller
You can say that the controller is the center of a tipical Joomla component because every request to that component passes through the controller.
The controller can be used in two ways, when getting or when posting information
-
A typical GET request to the component specifies, besides the component name (option=com_blog_tutorial), the view desired. In this case, the default task represented by the display() function is called
-
A typical POST request to the component specifies, besides the component (option=com_blog_tutorial), the task. In this case, the component entry point sets the task from the controller to be executed represented by a function with the same name. This function does not need views, because it just does something on the server and redirects to a proper GET flow, it will however load, if necessary, models to update the data, or in simpler cases will operate directly to the database.
For now we'll just concentrate on GET requests, meaning that we'll end up in the 'display()' function. But before this, let's create our controller.
The main controller resides in a file called 'controller.php' inside the component folder, here's the syntax: {joomla_server_path}+/components/com_+{component_name}+/controller.php/joomla/server/path/components/com_blog_tutorial/controller.php. The class name has this syntax {Component_name}+ControllerBlog_tutorialController. Inside the controller's class let's ad a function called 'display()'. This function has the purpose of loading the view specified in the URL, or a default one, it will load the proper model (in most cases the one with the same name as the view) and attach it to the view. Also it will set the default layout for the view. Other things can happen here, but we'll get into more details in a future lesson.
Here is the full code of our blog's controller found here: {joomla_server_path}+/components/com_+{component_name}+/controller.php/joomla/server/path/components/com_blog_tutorial/controller.php:
<?php
defined('_JEXEC') or die('DIRECT ACCESS NOT ALLOWED');
//import the base controller file
jimport('joomla.application.component.controller');
class Blog_tutorialController extends JController
{
function display()
{
//get a reference to the 'document' object
$document = &JFactory::getDocument();
//get the view, type, and layout
$vName = JRequest::getWord('view', 'posts');
$vFormat = $document->getType();
$lName = JRequest::getWord('layout', 'default');
//load the view
if ($view = &$this->getView($vName, $vFormat))
{
//load the model
$model = &$this->getModel($vName);
//attach the model and the layout to the view
$view->setModel($model, true);
$view->setLayout($lName);
$view->assignRef('document', $document);
//display the component
$view->display();
}
}
}
?>
Part III: the model
Models inside Joomla handle getting and modifying entities inside our component. As we know every blog has posts or comments to those posts, well they are represented by models, a model for posts, and a model for comments. This is for the beginning, every individual post is again represented by a model, the post model, and so on, for what ever entity we can consider inside our blog component.
Of course we'll come across situations where we need information from the post models and from the comments module on a single request. This situation can be handle in tree different ways:
- we'll consider the comments as being the same entity as the post, something that the post will always have. this is suitable for simple situations, if you'll have a complex comments system this is not the best choice
- (I'm not really sure about this) we'll bind to the view the post model, and let him load the comments model, and when the view asks the model for some comments, the post model will ask the comments model for the comments
- we could bind to the post view, besides the post model, the comments model, so the view can access it, and ask for the comments
I'm not sure what is the best solution, at first we'll use the first situation and until we get in detail with models, I'll have a better advice for all this
Now lets get to where things go. The models go in the 'models' folder inside the component folder: {joomla_server_path}+/components/com_+{component_name}+/models/joomla/server/path/components/com_blog_tutorial/models and it's file must be named the same as the model. Every model must have the following name as the class name, this is the example for the 'posts' model {Component_name}+Model+{Model_name}Blog_tutorialModelPosts
The model class structure
First thing we need to do is to include the base controller class from witch we'll extend our controller, this is done with he 'jimport()' function
jimport('joomla.application.component.model');
We already know the class name from above that will extend 'JModel' base class. We'll need a variable (member) inside this class that will hold our actual data, we'll call this member 'posts' or '$_posts'. This member will be protected, because we don't need direct access to it, it will be fetched to us by a function inside this class (public method)
class Blog_tutorialModelPosts extends JModel
{
protected $_posts = null;
}
All we need now is the method to get the posts out of the model, we'll call our function 'getPosts()' and will return a reference to our '$_posts' member. It's a good practice to name our 'get' methods descriptively, meaning that if we what to get the posts, we'll name our method 'getPosts', in this case we allow Joomla facilitate easy access to out model data, but we'll talk about this particular thing in detail in a future chapter. For now, the model will return some 'hard coded' information because we didn't get to the database operations part yet. And here's the function:
public function &getPosts()
{
//if this is the first time getting the posts
if(!$this->_posts)
{
$posts = array();
$posts[] = 'First post.';
$posts[] = 'Last post';
$this->_posts = $posts;
}
//return the posts
return $this->_posts;
}
Part IV: the view
What does the view do? I probably mention this already before, but we'll talk here i a little more detail here. The view gets the information needed to be displayed, after it has the information, any modification needed is done here, as an example it can calculate the days since the post has been created based on the creation date. After the modifications took place, the view assigns the information needed to be displayed to the layout file
The view file
The view file is simply called view+{view_type}+.phpview.html.php no matter what the view itself is called, the only difference between views is the folder they reside in. Each view must be placed in a folder with the same name as the view, all these folders are located inside the 'views' folder inside the component folder. Here's the path of the 'posts' view for our blog: {joomla_server_path}+/components/com_+{component_name}+/views/+{view_name}+/view+{view_type}+.php/joomla/server/path/components/com_blog_tutorial/views/posts/view.html.php.
The view class
The view class for you posts needs to have the following structure: {Component_name}+View+{View_name}Blog_tutorialViewViews. Now... let's get to the code, all this class needs to do for now is to get the data from the controller assigned to this view, and pass it to the model.
Include the Joomla base view class from witch we'll extend our view
jimport('joomla.application.component.view');
Get our posts from the model, the default model that is, because we can have multiple models to a view, but we'll talk about this later. Notice that we only have to access the 'get()' method, and the view automatically calls the get+{first_parameter} on the model
$posts = &$this->get('Posts');
Now all we need is to assign the information to the layout and display it
$this->assignRef('posts', $posts);
parent::display($tpl);
And here's the full code for the view file
defined('_JEXEC') or die('Restricted Access');
jimport('joomla.application.component.view');
class Blog_tutorialViewPosts extends JView
{
public function display($tpl=null)
{
//get the posts
$posts = &$this->get('Posts');
//assing the posts to the view
$this->assignRef('posts', $posts);
//display
parent::display($tpl);
}
}
Part V: the layout
And finally the layout, so we can display the information. The layout needs to be here: {joomla_server_path}+/components/com_+{component_name}+/views/+{view_name}+/tmpl/+{layout_name}+.php/joomla/server/path/components/com_blog_tutorial/views/posts/tmpl/default.php. The layout is just a HTML block that will present our information to the user's browser, accessing the data assigned to it is done with the '$this' keyword because the layout is part of the view class, and when assigning data to the layout we actually create/modify members of the view class. Here an example of a layout that will output a summary of our posts
<?php defined('_JEXEC') or die('DIRECT ACCESS NOT ALLOWED')?>
<h2>This blog's posts</h2>
<?php
if(count($this->posts))
{
?>
<ol>
<?php
foreach($this->posts as $p)
{
?>
<li><?php echo $p?></li>
<?php
}
?>
</ol>
<?php
}
else
{
echo 'No posts yet';
}
?>
Conclusion
That's about it, we now know where views and models are located, what they suppose to do and we have a few examples so we can build on them our future blog component. In our next tutorial we'll talk about database access and we'll add another view to our component to display a single component
Here's the full structure (don't forget to include a blank 'index.html' inside every folder you create), a screenshot and demo.
This tutorial will help you understand proper techniques for developing native MVC components within Joomla 1.6 environment.
At the time i started this tutorial, Joomla 1.6 was in the alpha state, the development and testing was done with the latest development version from the SVN. I will keep an eye on the development, so this tutorial will be up to date for any changes that will occur with Joomla system.
If you find mistakes, typos, security holes please let me know by posting a comment or by mailing me.
Through this tutorial we'll use the following conventions:
This tutorial was made by studying the core and the components of the Joomla CMS and from experience with developing joomla 1.5 components. I haven't used any copyrighted material, or materials from other tutorials. This tutorial represents just my point of view regarding Joomla development. Also, i am not affiliated in any way with Joomla or Open Source Matters, and this tutorial can not be considered an official one.
This tutorial and the components resulting from it are offered free, and will always be free in some form, you can use them in any way you like without having to ask for permission, but things like: link back, keeping the author and author site (P18X, P18X.com) where they should be, mail or comment with impressions are always welcomed