Controller, view and layout
A component page is produced by three files. The controller receives the request and picks a view. The view prepares the data. The layout turns it into HTML. Let us make the first site page — a list of blog posts.
Files
Create three files in the site part by hand:
components/com_hello/
├── src/
│ ├── Controller/
│ │ └── DisplayController.php
│ └── View/
│ └── Posts/
│ └── HtmlView.php
└── tmpl/
└── posts/
└── default.phpThe controller
// components/com_hello/src/Controller/DisplayController.php
namespace My\Component\Hello\Site\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
class DisplayController extends BaseController
{
protected $default_view = 'posts';
}DisplayController is the controller Joomla calls when the request names no other action. Its display() method is already written in the parent class: it reads the view parameter from the address and renders the view with that name. Without the parameter, $default_view is used.
The view
// components/com_hello/src/View/Posts/HtmlView.php
namespace My\Component\Hello\Site\View\Posts;
defined('_JEXEC') or die;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
class HtmlView extends BaseHtmlView
{
public array $posts = [];
public function display($tpl = null): void
{
$this->posts = ['First post', 'Second post'];
parent::display($tpl);
}
}The view puts data into its properties and calls parent::display(), which includes the layout. For now the posts are hard-coded; in the next lesson a model supplies them.
The layout
<?php
// components/com_hello/tmpl/posts/default.php
defined('_JEXEC') or die;
?>
<h1>Blog</h1>
<ul>
<?php foreach ($this->posts as $title) : ?>
<li><?php echo $this->escape($title); ?></li>
<?php endforeach; ?>
</ul>In a component layout $this is the view object: its properties are available as $this->posts. The escape() method escapes output.
The result
Open this address on the site:
http://joomla.test/index.php?option=com_hello&view=postsInside the site template you see the heading "Blog" and a list of two posts. The address without view — index.php?option=com_hello — shows the same page thanks to $default_view.
How the address maps to files
| In the address | What Joomla looks for |
|---|---|
option=com_hello | The component and its provider |
view=posts | The class View\Posts\HtmlView |
layout=default (the default) | The layout tmpl/posts/default.php |
format=html (the default) | The HtmlView class; for format=json it is JsonView |
task=post.save | The save() method of the Controller\PostController class |
To add a second page, create one more folder in View and one more in tmpl. No new controller is needed for that.
Controller actions
The task parameter calls a controller method. Everything that changes data is done this way: saving, deleting, publishing. task=post.save means "the PostController controller, the save method". When done, such a method does not render a page but redirects to one with $this->setRedirect(). Ready-made controllers with actions appear in the lesson on saving data.
The control panel
The administrator part is built exactly the same way; only the paths and one word of the namespace change:
| File on the site | File in the panel |
|---|---|
components/com_hello/src/... | administrator/components/com_hello/src/... |
My\Component\Hello\Site\... | My\Component\Hello\Administrator\... |
Common mistake
Class and folder names are tied together strictly: the posts view is the View/Posts folder and the tmpl/posts/default.php layout. On a mismatch Joomla reports "View not found". On Windows the letter case of folder names does not matter, but on a Linux server View/posts and View/Posts are different folders: use a capital letter in src and lowercase in tmpl.