跳至主要内容
版本:5.1

安装流程和脚本文件

本节概述了扩展安装过程,以及如何编写脚本文件与之交互。

安装脚本文件是一个包含 5 个函数的类。

  • preflight - 在安装过程开始时调用
  • install, update, uninstall - 在过程进行中调用
    • install 在操作是扩展的初始安装时调用
    • update 在操作是现有扩展的安装时调用
    • uninstall 在操作是扩展的删除时调用
  • postflight - 在安装过程结束时调用

您还可以通过编写安装插件来与过程进行交互,这些插件监听以下事件。

安装流程

在 Joomla 中安装扩展有各种方法,以及各种类型的扩展,但最终,安装过程对所有扩展都遵循类似的模式。

当您去安装扩展并选择一个要安装的扩展的压缩文件时,以下是发生的情况概述:(如果您想在调试器中逐步完成此过程,请在 administrator/components/com_installer/src/Model/InstallModel.php::install 处设置断点)

  • 导入 "installer" 类型的插件,并触发 'onInstallerBeforeInstallation' 事件
  • 压缩文件存储在 Joomla /tmp 文件夹中,然后解压缩到 /tmp 的子文件夹中
  • 触发 'onInstallerBeforeInstaller' 事件
  • 触发 'onExtensionBeforeInstall' 事件
  • 从新安装文件中加载 .sys.ini 语言文件(或者如果失败,则从现有扩展目录加载)
  • 从清单文件中读取有关扩展的基本信息,例如,扩展的类型
  • 对安装脚本文件执行 require_once
  • 调用脚本文件 preflight 函数
  • 将扩展文件从 /tmp 文件夹复制到它们在 Joomla 实例中的位置 - 例如,当安装站点模块 mod_example 时,代码将被复制到 /modules/mod_example
  • 在数据库中写入/更新扩展记录(即此扩展在 #__extensions 表中的记录)
  • 执行特定于该扩展类型的任何功能。例如,对于模块的新安装,它会在 #__modules 表中创建一个记录
  • 应用此安装所需的任何数据库更改。
  • 调用脚本文件 install / update / uninstall 函数
  • 整理
    • 如果 #__updates 表中有一条记录表明此扩展存在新版本,则将其删除。
    • 它将清单文件复制到目标扩展目录(对于组件,它将是 /administrator 下的组件目录)
  • 调用脚本文件 postflight 函数
  • 触发 'onExtensionAfterInstall' 事件
  • 触发 'onInstallerAfterInstaller' 事件
  • 执行一些进一步的整理,例如删除临时安装文件

示例脚本文件

编写脚本文件的最简单方法是使用 libraries/src/Installer/InstallerScriptInterface.php 中的 \Joomla\CMS\Installer\InstallerScriptInterface 定义。您只需返回一个实现 5 个安装函数的类的实例。

您可以:

  1. 返回一个实现 InstallerScriptInterface 的匿名脚本文件类,或者
  2. 返回一个匿名服务提供者类,该类使用键 InstallerScriptInterface::class 将脚本文件类放入依赖注入容器。然后 Joomla 将从 DIC 获取该脚本文件类。

以下示例使用第二种方法。

有关第一种方法的示例,请参阅 模块教程步骤 6

<?php

use Joomla\CMS\Application\AdministratorApplication;
use Joomla\CMS\Installer\InstallerAdapter;
use Joomla\CMS\Installer\InstallerScriptInterface;
use Joomla\CMS\Language\Text;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Exception\FilesystemException;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

return new class () implements ServiceProviderInterface {
public function register(Container $container)
{
$container->set(
InstallerScriptInterface::class,
new class (
$container->get(AdministratorApplication::class),
$container->get(DatabaseInterface::class)
) implements InstallerScriptInterface {
private AdministratorApplication $app;
private DatabaseInterface $db;

public function __construct(AdministratorApplication $app, DatabaseInterface $db)
{
$this->app = $app;
$this->db = $db;
}

public function install(InstallerAdapter $parent): bool
{
$this->app->enqueueMessage('Successful installed.');

return true;
}

public function update(InstallerAdapter $parent): bool
{
$this->app->enqueueMessage('Successful updated.');

return true;
}

public function uninstall(InstallerAdapter $parent): bool
{
$this->app->enqueueMessage('Successful uninstalled.');

return true;
}

public function preflight(string $type, InstallerAdapter $parent): bool
{
return true;
}

public function postflight(string $type, InstallerAdapter $parent): bool
{
$this->deleteUnexistingFiles();

return true;
}

private function deleteUnexistingFiles()
{
$files = []; // overwrite this line with your files to delete

if (empty($files)) {
return;
}

foreach ($files as $file) {
try {
File::delete(JPATH_ROOT . $file);
} catch (\FilesystemException $e) {
echo Text::sprintf('FILES_JOOMLA_ERROR_FILE_FOLDER', $file) . '<br>';
}
}
}
}
);
}
};