Joomla Bài học 32: Lập trình Controller và Model phía Administrator để hiển thị danh sách dữ liệu
Trong Joomla Bài học 31, chúng ta đã định hình cấu trúc thư mục, thiết lập file Manifest XML và tạo bảng cơ sở dữ liệu #__custom_items. Trong Joomla Bài học 32, chúng ta sẽ chính thức bước vào thế giới lập trình hướng đối tượng bằng PHP 8.2+ để xây dựng hai thành phần cốt lõi đầu tiên của mô hình MVC phía Administrator: Controller (nhận yêu cầu và điều hướng) và Model (truy vấn cơ sở dữ liệu để lấy danh sách bản ghi).
1. Vai trò của Controller và Model trong Joomla MVC
-
Controller (
DisplayController.php): Đóng vai trò là "nhà điều phối". Nó kiểm tra xem người dùng đang muốn làm gì (xem danh sách, thêm mới, sửa hay xóa), sau đó gọi Model để lấy dữ liệu tương ứng và kích hoạt View để hiển thị. -
Model (
ItemsModel): Đóng vai trò là "bộ não dữ liệu". Model của Joomla cung cấp sẵn các lớp cơ sở cực kỳ mạnh mẽ nhưListModel(hỗ trợ sẵn phân trang, sắp xếp cột, lọc dữ liệu) giúp bạn giảm thiểu 80% thời gian viết câu lệnh truy vấn SQL thủ công.
2. Khởi tạo Component Extension (Extension/CustomComponent.php)
Trước khi viết Controller, Joomla 5 yêu cầu một lớp khởi tạo thành phần (Extension class) tuân theo chuẩn PSR-4 để quản lý vùng chứa (Container) và Namespace của component.
Tạo file tại: src/administrator/components/com_custom/src/Extension/CustomComponent.php
PHP
<?php
namespace MyCompany\Component\Custom\Administrator\Extension;
\defined('_JEXEC') or die;
use Joomla\CMS\Component\MVC\Controller\BaseController;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\MVCComponent;
use Joomla\CMS\HTML\HTMLRegistryAwareTrait;
class CustomComponent extends MVCComponent implements ComponentInterface
{
use HTMLRegistryAwareTrait;
public function boot(\Interop\Container\ContainerInterface $container): void
{
parent::boot($container);
}
}
3. Lập trình Model quản lý danh sách (Model/ItemsModel.php)
Lớp ListModel của Joomla tự động xử lý các tham số phân trang (limit, limitstart), sắp xếp (filter_order, filter_order_Dir) và tìm kiếm từ form quản trị.
Tạo file tại: src/administrator/components/com_custom/src/Model/ItemsModel.php
PHP
<?php
namespace MyCompany\Component\Custom\Administrator\Model;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\ListModel;
class ItemsModel extends ListModel
{
public function __construct($config = [])
{
if (empty($config['filter_fields'])) {
$config['filter_fields'] = [
'id', 'a.id',
'title', 'a.title',
'state', 'a.state',
'created', 'a.created',
];
}
parent::__construct($config);
}
/**
* Xây dựng câu truy vấn SQL lấy danh sách bản ghi từ bảng #__custom_items
*/
protected function getListQuery()
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
// Chọn các cột dữ liệu cần thiết
$query->select(
$db->quoteName([
'a.id',
'a.title',
'a.alias',
'a.state',
'a.created',
])
)
->from($db->quoteName('#__custom_items', 'a'));
// Xử lý bộ lọc tìm kiếm theo từ khóa (Search filter)
$search = $this->getState('filter.search');
if (!empty($search)) {
$search = $db->quote('%' . $db->escape($search, true) . '%');
$query->where($db->quoteName('a.title') . ' LIKE ' . $search);
}
// Xử lý bộ lọc theo trạng thái (Published / Unpublished)
$state = $this->getState('filter.state');
if (is_numeric($state)) {
$query->where($db->quoteName('a.state') . ' = ' . (int) $state);
}
// Xử lý sắp xếp danh sách (Ordering)
$orderCol = $this->state->get('list.ordering', 'a.id');
$orderDirn = $this->state->get('list.direction', 'DESC');
$query->order($db->escape($orderCol . ' ' . $orderDirn));
return $query;
}
}
4. Lập trình Controller điều phối (Controller/DisplayController.php)
Controller mặc định cho màn hình danh sách chỉ cần kế thừa lớp DisplayController chuẩn của Joomla.
Tạo file tại: src/administrator/components/com_custom/src/Controller/DisplayController.php
PHP
<?php
namespace MyCompany\Component\Custom\Administrator\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
class DisplayController extends BaseController
{
protected $default_view = 'items';
public function display($cachable = false, $urlparams = [])
{
return parent::display($cachable, $urlparams);
}
}
5. Tổng kết bài học
-
Hiểu rõ vai trò điều phối của Controller và sức mạnh của lớp ListModel trong việc tự động hóa phân trang, sắp xếp và lọc dữ liệu.
-
Xây dựng thành công lớp khởi tạo component
CustomComponent.phptuân thủ chuẩn PSR-4 Namespace. -
Lập trình hoàn chỉnh câu lệnh SQL an toàn thông qua lớp
DatabaseQuerycủa Joomla.
Trong Bài học 33, chúng ta sẽ tiếp tục hoàn thiện giao diện hiển thị danh sách phía quản trị với: Lập trình View và xây dựng bảng dữ liệu HTML (HTMLView & Layout Template).
All Rights Reserved