Your view in the administration area usually does not contain only static text. You display data here that is dynamic. At least that's how most extensions work. That's why in this part we create a database for your component. In the database, we store three records during setup and display them in the administration area. A static list is displayed. The single entries are not changeable via the backend. We will work on that in the next part.
For impatient people: View the changed program code in the Diff View[^codeberg.org/astrid/j4examplecode/compare/t5...t6] and copy these changes into your development version.
Step by step
New files
administrator/components/com_foos/sql/install.mysql.utf8.sql
We create a file that contains SQL statements for creating the database table. So that these statements are called, we add the name of the file later in the manifest.
Besides the id
, which we use to make the element uniquely findable and the name name
, which is optional and names the item in our extension, there is the alias alias
. The latter prepares the data for routing, among other things. Imagine a system URL like http://www.example.com/index.php?option=com_foos&view=foo&id=1
. This is not very readable for humans. Machines like search engines also process such a URL poorly. A textual description is mandatory. In Joomla this is done with the help of the alias. This can be defined by the user. So that the alias text for the URL contains only valid characters, there are automatic processes in the background processing of Joomla.
With CREATE TABLE IF NOT EXISTS ...
we create the database table if it does not already exist. With INSERT INTO ...
we store sample contents in the database table. In a real extension, I would not add sample data via the SQL file during installation. In Joomla 4, a plugin of the type sampledata
is a good choice. For inspiration you can find plugins in Joomla in the directory plugins/sampledata
.
administrator/components/com_foos/sql/install.mysql.utf8.sql
<!-- https://codeberg.org/astrid/j4examplecode/raw/branch/t6/src/administrator/components/com_foos/sql/install.mysql.utf8.sql -->
CREATE TABLE IF NOT EXISTS `#__foos_details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
INSERT INTO `#__foos_details` (`name`) VALUES
('Nina'),
('Astrid'),
('Elmar');
Read in the preface of this tutorial what exactly the prefix
#__
means, if you are unfamiliar with it.
administrator/components/com_foos/sql/uninstall.mysql.utf8.sql
So that Joomla does not contain unnecessary data in case of uninstallation, we simultaneously create a file that contains the SQL command to delete the database table. This automatically executed when uninstalling.
administrator/components/com_foos/sql/uninstall.mysql.utf8.sql
<!-- https://codeberg.org/astrid/j4examplecode/raw/branch/t6/src/administrator/components/com_foos/sql/uninstall.mysql.utf8.sql -->
DROP TABLE IF EXISTS `#__foos_details`;
You might think ahead and ask yourself already how to handle potential future database changes. What is needed to store the first name in addition to the name in a future version. SQL updates are name-based in Joomla. This means exactly: For each version of the component you have to create a file whose name consists of the version number and the file extension
.sql
in case database contents change. Practically you will experience this in the further course of this tutorial.
administrator/components/com_foos/src/Model/FoosModel.php
Next, we create a Model for the administration area. Since we are extending the ListModel
class, we do not need to take care of the connection to the database ourselves. We create the getListQuery()
method and specify our specific requirements here. Specific are for example the name of the database table and the column.
If not done so far, you will see here why the separation of model and view makes sense. Have a look at the method
getListQuery()
in Joomla components, for example incom_content
. The SQL statement is usually extensive. Therefore it is clearer to encapsulate this from other parts.
The following code shows you the model, which in our case is still quite clear.
administrator/components/com_foos/src/Model/FoosModel.php
// https://codeberg.org/astrid/j4examplecode/raw/branch/t6/src/administrator/components/com_foos/src/Model/FoosModel.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_foos
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace FooNamespace\Component\Foos\Administrator\Model;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\ListModel;
/**
* Methods supporting a list of foo records.
*
* @since __BUMP_VERSION__
*/
class FoosModel extends ListModel
{
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
*
* @see \JControllerLegacy
*
* @since __BUMP_VERSION__
*/
public function __construct($config = [])
{
parent::__construct($config);
}
/**
* Build an SQL query to load the list data.
*
* @return \JDatabaseQuery
*
* @since __BUMP_VERSION__
*/
protected function getListQuery()
{
// Create a new query object.
$db= $this->getDatabase();
$query = $db->getQuery(true);
// Select the required fields from the table.
$query->select(
$db->quoteName(['id', 'name', 'alias'])
);
$query->from($db->quoteName('#__foos_details'));
return $query;
}
}
Modified files
administrator/components/com_foos/foos.xml
The entry in the installation manifest marked with a plus sign causes the SQL statements in the named files to be called at the right moment, either during an installation or during an uninstallation..
administrator/components/com_foos/foos.xml
<description>COM_FOOS_XML_DESCRIPTION</description>
<namespace path="src">FooNamespace\Component\Foos</namespace>
<scriptfile>script.php</scriptfile>
<install> <!-- Runs on install -->
<sql>
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
</sql>
</install>
<uninstall> <!-- Runs on uninstall -->
<sql>
<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
</sql>
</uninstall>
<!-- Frond-end files -->
<files folder="components/com_foos">
<folder>src</folder>
<files folder="administrator/components/com_foos">
<filename>foos.xml</filename>
<folder>services</folder>
<folder>sql</folder>
<folder>src</folder>
<folder>tmpl</folder>
</files>
In this example, I only support a MySQL database. Joomla supports[^downloads.joomla.org/technical-requirements] as well as MySQL (from 5.6) and PostgreSQL (from 11). If you also support both databases, you can find an implementation to check out in the Weblinks component[^github.com/joomla-extensions/weblinks]. How you name the drivers is flexible.
postgresql
andmysql
are correct.mysqli
,pdomysql
andpgsql
are changed by Joomla in the file/libraries/src/ Installer/Installer.php
if you use this.
Updates
For the sake of completeness, I anticipate here changes of a following chapter concerning updating. If something changes, it is sufficient to include only the changes in the database. You should take care that existing data are not affected. You save the changes in a separate file for each version. The directory, where the files for the future updates are to be stored, you write in the <update>
tag. This is logical, right?
...
<update> <!-- Runs on update -->
<schemas>
<schemapath type="mysql">sql/updates/mysql</schemapath>
</schemas>
</update>
...
Below you can see the update file src/administrator/components/com_foos/sql/updates/mysql/10.0.0.sql
as an example. This file will be added later in this example.
ALTER TABLE `#__foos_details` ADD COLUMN `access` int(10) unsigned NOT NULL DEFAULT 0 AFTER `alias`;
ALTER TABLE `#__foos_details` ADD KEY `idx_access` (`access`);
administrator/components/com_foos/services/provider.php
Previously it was not necessary to set the MVCFactory
in provider.php
, now it is required. Otherwise you will see the following error message or you will be forced to program the connection to the database yourself: MVC factory not set in Joomla\CMS\Extension\MVCComponent
.
administrator/components/com_foos/services/provider.php
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\HTML\Registry;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use FooNamespace\Component\Foos\Administrator\Extension\FoosComponent;
$component = new FoosComponent($container->get(ComponentDispatcherFactoryInterface::class));
$component->setRegistry($container->get(Registry::class));
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
return $component;
}
administrator/components/com_foos/src/View/Foos/HtmlView.php
In the view we get all the items at the end. For this we call the method $this->get('Items')
in the model:
administrator/components/com_foos/src/View/Foos/HtmlView.php
*/
class HtmlView extends BaseHtmlView
{
protected $items;
/**
* Method to display the view.
*
*/
public function display($tpl = null): void
{
$this->items = $this->get('Items');
parent::display($tpl);
}
}
administrator/components/com_foos/tmpl/foos/default.php
Last but not least, we display everything using the template file. Instead of the static text Hello Foos
there is now a loop that goes through all elements.
administrator/components/com_foos/tmpl/foos/default.php
*/
\defined('_JEXEC') or die;
?>
Hello Foos
<?php foreach ($this->items as $i => $item) : ?>
<?php echo $item->name; ?>
</br>
<?php endforeach; ?>
Are you wondering about the syntax? In the preface I had explained why I choose the alternative syntax for PHP in a template file and enclose the individual lines in PHP tags.
Test your Joomla component
-
install your component in Joomla version 4 to test it: Copy the files in the
administrator
folder to theadministrator
folder of your Joomla 4 installation. Install your component as described in part one, after copying all files. Joomla creates the database during the installation. -
Next, test if the view of your component in the administration area is correct. Do you see three entries? We had entered these as sample data in the SQL file when setting up the database.
- make sure that the elements are stored in the database. I use locally phpmyadmin.net for database administration.
Webmentions