跳至主要内容

已移除和向后不兼容

所有已弃用的功能现已移除,以及任何向后不兼容的更改。应提供有关如何减轻移除/更改影响的说明。

将 .tar.bz2 替换为 .tar.zstd

从 Joomla! 5.0.0 的最终版本开始,我们不再创建 .tar.bz2 软件包。而是使用 .tar.zstd 软件包。这使我们能够创建比 bzip2 压缩文件小约 3 MiB,比 zip 压缩文件小约 11 MiB 的下载软件包。

PSR-3 升级到版本 3

PSR-3(日志记录)已升级到版本 3规范。

最重要的是,\Psr\Log\LoggerInterface 方法的签名已更改。$message 参数现在被严格类型化为 string|\Stringable。您使用的任何日志记录实现**必须**与这个新签名兼容。如果您实现自己的日志记录器,或者在扩展中使用第三方日志记录器(如 Monolog),这与您相关。

如果您使用的是自己的日志记录器,想要在同一扩展包中保留与 Joomla 4 和 5 的兼容性,并且不介意失去 PSR-3 兼容性,您可以将 PSR-3 的副本包含在您的扩展中只要它在您的扩展的命名空间下。例如,您可以使用 \Acme\Component\Example\Administrator\Log\LoggerInterface 而不是 \Psr\Log\LoggerInterface。请注意,您可以使用PHP Scoper轻松地将您的依赖项迁移到您自己的命名空间下。

如果您只需要维护与 PSR-3 的兼容性以使用组件外部的日志记录器(例如 Joomla 的日志记录器),您仍然可以针对 \Psr\Log\LoggerInterface 进行类型提示。请注意,您正在使用的外部日志记录器必须与 Joomla 4 上的 PSR-3 版本 1 和 Joomla 5 上的 PSR-3 版本 3 兼容。如果您自己提供第三方外部日志记录器,则可能需要将两个版本的日志记录器包含在您的扩展中,并且仅为每个 Joomla 版本加载正确的版本。

框架更新

Joomla! 5.0 使用 Joomla! 框架 3.0,这可能会有自己的重大更改

数据库必须注入模型构造函数

  • PR:https://github.com/joomla/joomla-cms/pull/38511
  • 说明:模型中的数据库实例应通过构造函数中的$this->setDatabase()或已弃用的函数$this->setDbo()配置注入,以使其在基类中可用。这样可以确保对$this->getDatabase()和已弃用的函数$this->getDbo()的调用将指向同一实例。
class MyModel extends ListModel {
public function __construct(..) {
parent::__construct(...);
$this->setDatabase(MyHelper::getGridDB());
}
}

删除 -es5.js 文件

  • PR:https://github.com/joomla/joomla-cms/pull/39618
  • 说明:构建工具不再生成 es5 文件(IIFE,转换为 ES5)。此外,所有 assets.json 文件中指向这些(es5)文件的依赖项都已删除(-es5.js 的实际条目已保留以供向后兼容,但 URL 为空,文件将不会加载)。.es6.js 文件被转换为 ES2018,并且具体而言,最小浏览器版本来自caniuse:es6-module。使用type=module/nomodule加载现代/遗留代码的第三方代码仍将像以前一样工作,但核心不再分发与IE11兼容的脚本!。

CSS 移除

CSS 类“.ie11”已通过PR #39018移除

Javascript 移除

已通过PR #40302移除以下 Javascript 资产

  • /media/com_templates/js/admin-template-compare.js - 自版本 4.3.0 以来,核心不再使用,请参阅 PR #38823

  • /media/com_users/js/admin-users-mail.js - 自版本 4.3.0 以来,核心不再使用,请参阅 PR #39374

这还包括-es5.js文件以及最小化和 gzip 压缩的文件,以及joomla.asset.json文件中相应的条目。

这些文件已保留在 Joomla 4 中,以向后兼容布局覆盖。

要修复 Joomla 5 的这些布局覆盖,请按照上面列出的每个 Javascript 资产的 PR 中提到的方式更改您的布局覆盖,就像相应的核心布局已更改一样。

例如,对于模板管理器并排比较视图,请参阅 PR #38823

返回类型

所有返回类型都已更新,以匹配 PHP 8.1 返回类型签名。这解决了任何使用 ArrayAccess、Datetime 或 JsonSerializable 接口的类。如果您从任何受影响的类继承并且需要与 Joomla 4.x 和 5.x 兼容,则应在您的代码中添加#[\ReturnTypeWillChange]注释。

administrator/components/com_users/src/DataShape/DataShapeObject.php

public function __isset(...)      --> public function __isset(...): bool
public function offsetExists(...) --> public function offsetExists(...): bool
public function offsetGet(...) --> public function offsetGet(...): mixed
public function offsetSet(...) --> public function offsetSet(...): void
public function offsetUnset(...) --> public function offsetUnset(...): void

libraries/src/Date/Date.php

public function format(...)      --> public function format(...): string
public function setTimezone(...) --> public function setTimezone(...): \Datetime

libraries/src/Document/JsonapiDocument.php

public function jsonSerialize(...) --> public function jsonSerialize(...): mixed

libraries/src/Feed/Feed.php

public function count(...)        --> public function count(...): int
public function offsetExists(...) --> public function offsetExists(...): bool
public function offsetGet(...) --> public function offsetGet(...): mixed
public function offsetSet(...) --> public function offsetSet(...): void
public function offsetUnset(...) --> public function offsetUnset(...): void

libraries/src/Language/Language.php

\Joomla\CMS\Language\Language 现在扩展自 \Joomla\Language\Language

已移除从框架扩展的重复代码

public function debugFile(...) --> public function debugFile(string $filename): int

用户更改

某些核心类不再是 CMSObject 类型

PR:https://github.com/joomla/joomla-cms/pull/40999 文件

  • libraries/src/Categories/CategoryNode.php
  • libraries/src/Changelog/Changelog.php
  • libraries/src/Filesystem/Stream.php
  • libraries/src/Installer/InstallerExtension.php
  • libraries/src/MVC/Model/BaseModel.php
  • libraries/src/MVC/View/AbstractView.php
  • libraries/src/Table/Table.php
  • libraries/src/Updater/Update.php
  • libraries/src/User/User.php

说明:这些类不再扩展自CMSObject,而是包含LegacyErrorHandlingTraitLegacyPropertyManagementTrait遗留特性,就像CMSObject一样。这样功能就不会改变。请记住,这些特性的函数已弃用,应抛出异常或创建适当的 getter 和 setter。

DIC 服务提供程序更改

PR:https://github.com/joomla/joomla-cms/pull/36499

输入对象现在在 DIC 中可用。您不应在扩展中直接使用它,而应继续通过应用程序对象获取输入。

\Joomla\CMS\Factory::$application 不再有时在应用程序的 DIC 提供程序内部设置,而是现在在每个应用程序的 includes/app.php 文件内部可靠地设置。预计此更改不会影响扩展开发人员,因为在 Joomla 应用程序生命周期的早期没有扩展挂钩。

会话对象更改

在创建\Joomla\CMS\Session\Storage\JoomlaStorage的完整自定义会话对象的罕见情况下,现在应在创建类时在选项对象中设置 cookie 域和 cookie 路径。它们不会从应用程序对象中获取,以修复各种循环依赖问题。由于我们期望所有扩展都使用应用程序中 CMS 创建的主会话,因此这预计不会对最终用户产生实际影响。

全局配置中的错误报告选项

全局配置中将错误报告设置为**开发**模式的选项已被移除,因为它已过时。因为从 PHP 5.4 开始,`error_reporting(-1)` 和 `error_reporting(E_ALL)` 的行为相同。请参阅 https://php.ac.cn/manual/en/function.error-reporting

Wincache 已被移除

WinCache 已被弃用,从 PHP 8 开始不再支持。已移除且没有替代方案。

工具栏弹出按钮现在使用 JoomlaDialog

工具栏弹出按钮现在使用 JoomlaDialog 进行弹出窗口渲染。旧版 Bootstrap 模态框仍然有效。PR: https://github.com/joomla/joomla-cms/pull/40359

要使用新的对话框,添加了以下属性

  • popupType - 弹出窗口类型:inlineiframeajax;
  • url - 用于内联弹出窗口的内容的 URL 或 CSS 选择器;
  • textHeader - 弹出窗口标题的文本;
  • modalWidthmodalHeight - 可选,宽度和高度,任何有效的 CSS 值;

使用 Bootstrap 模态框作为工具栏弹出按钮,属性onclose 已弃用。

内联按钮定义示例

// Old:
$toolbar->popupButton('batch', 'JTOOLBAR_BATCH')
->selector('collapseModal')
->listCheck(true);

// New
$toolbar->popupButton('batch', 'JTOOLBAR_BATCH')
->popupType('inline')
->textHeader(Text::_('COM_CONTENT_BATCH_OPTIONS'))
->url('#joomla-dialog-batch')
->modalWidth('800px')
->modalHeight('fit-content')
->listCheck(true);

批处理的内联渲染示例

Old:
<?php
echo HTMLHelper::_('bootstrap.renderModal', 'collapseModal', [
'title' => Text::_('COM_CATEGORIES_BATCH_OPTIONS'),
'footer' => $this->loadTemplate('batch_footer'),
],
$this->loadTemplate('batch_body')
);
?>

New:
<template id="joomla-dialog-batch"><?php echo $this->loadTemplate('batch_body'); ?></template>

注意:批处理按钮现在是 batch_body 的一部分。

iframe 按钮定义示例

// Old:
$toolbar->popupButton('example', 'Example iframe')
->url('index.php?option=com_example&view=foobar&tmpl=component');

// New
$toolbar->popupButton('example', 'Example iframe')
->popupType('iframe')
->url('index.php?option=com_example&view=foobar&tmpl=component')
->textHeader('Optional iframe title');

插件

演示任务插件已被移除

Recaptcha 插件已被移除,隐形验证码已解锁

Codemirror 插件

PR: https://github.com/joomla/joomla-cms/pull/41070

Codemirror 脚本已更新至第 6 版。新版本基于 ES 模块。为 Codemirror 5 编写的任何自定义和 JavaScript 代码都与 Codemirror 6 不兼容。

要初始化 Codemirror 实例,您可以使用 Joomla 在 codemirror 模块中提供的帮助程序,例如

$wa->getRegistry()->addExtensionRegistryFile('plg_editors_codemirror');
$wa->useScript('codemirror');
import { createFromTextarea } from 'codemirror';
const editor = await createFromTextarea(textAreaElement, options);

验证码插件现在必须使用 onCaptchaSetup 事件

PR: https://github.com/joomla/joomla-cms/pull/39657

验证码插件现在必须使用 onCaptchaSetup 事件来注册自己的验证码提供程序,该提供程序应实现 CaptchaProviderInterface。有关更多信息,请参阅 验证码插件

对于外部类,例如

public function onCaptchaSetup(CaptchaSetupEvent $event)
{
$event->getCaptchaRegistry()->add(new MyCaptchaProvider());
}

当插件自行实现 CaptchaProviderInterface

public function onCaptchaSetup(CaptchaSetupEvent $event)
{
$event->getCaptchaRegistry()->add($this);
}

验证码提供程序是一个类,它提供对验证码的抽象访问。它包含所有旧方法,但略有更改

  • onDisplay($name = null, $id = '', $class = '') 现在是 display(string $name = '', array $attributes = []): string;
  • onInit($id = '') 已移除,您应在 display() 方法中加载您的资源;
  • onCheckAnswer($code = null) 现在是 checkAnswer(string $code = null): bool;
  • onSetupField($field, $element) 现在是 setupField(FormField $field, \SimpleXMLElement $element): void

旧版插件将继续运行,直到下一个主要版本发布。

编辑器插件现在必须使用 onEditorSetup 事件

PR: https://github.com/joomla/joomla-cms/pull/40082

编辑器插件现在必须使用 onEditorSetup 事件来注册自己的编辑器提供程序,该提供程序应实现 EditorProviderInterface。有关更多信息,请参阅 编辑器插件

对于外部类,例如

public function onEditorSetup(EditorSetupEvent $event)
{
$event->getEditorsRegistry()->add(new MyEditorProvider());
}

当插件自行实现 EditorProviderInterface

public function onEditorSetup(EditorSetupEvent $event)
{
$event->getEditorsRegistry()->add($this);
}

编辑器提供程序是一个类,它提供对编辑器的抽象访问。它包含所有旧方法,但略有更改

  • onDisplay($name, $content, $width, $height, $col, $row, $buttons, $id, $asset, $author, $params) 现在是 display(string $name, string $content = '', array $attributes = [], array $params = []): string;
  • onInit($id = '') 已移除,您应在 display() 方法中加载您的资源;

旧版插件将继续运行,直到下一个主要版本发布。

编辑器 XTD 按钮插件现在必须使用 onEditorButtonsSetup 事件

PR: https://github.com/joomla/joomla-cms/pull/40082

编辑器 XTD 按钮插件现在必须使用 onEditorButtonsSetup 事件来注册按钮实例。有关更多信息,请参阅 编辑器按钮(XTD)插件。此外,按钮现在可以注册一个自定义操作,该操作将在单击按钮时运行。

将旧按钮转换为 Joomla\CMS\Editor\Button 的示例

// Legacy
$button = new CMSObject;
$button->modal = true;
$button->link = $link;
$button->text = Text::_('PLG_ARTICLE_BUTTON_ARTICLE');
$button->name = $this->_type . '_' . $this->_name;
$button->icon = 'file-add';

return $button

// New
$button = new Button($this->_name, [
'action' => 'modal',
'link' => $link,
'text' => Text::_('PLG_ARTICLE_BUTTON_ARTICLE'),
'name' => $this->_type . '_' . $this->_name,
'icon' => 'file-add'
]);

$event->getButtonsRegistry()->add($button);

旧版插件将继续运行,直到下一个主要版本发布。

插件构造函数不包含赋值运算符

  • PR: https://github.com/joomla/joomla-cms/pull/40746
  • 描述:CMSPlugin 类的构造函数现在不包含分发器的额外赋值运算符,因为对象始终通过引用传递。因此,插件中的构造函数现在应以以下方式编写
public function __construct(DispatcherInterface $dispatcher, array $config, more arguments)
{
parent::__construct($dispatcher, $config);

// Assign the extra arguments to internal variables
}

模块事件 onRenderModule 向后兼容性

// Old
function onRenderModule($module, &$attributes){
$attributes['foo'] = 'bar';
}

// New
function onRenderModule(Joomla\CMS\Event\Module\BeforeRenderModuleEvent $event){
$attributes = $event->getAttributes();

$attributes['foo'] = 'bar';

$event->updateAttributes($attributes);
}

模块事件 onAfterRenderModules 向后兼容性

  • PR: https://github.com/joomla/joomla-cms/pull/41413
  • 描述:onAfterRenderModules 现在应使用 $event->getContent()$event->updateContent($content),而不是通过引用修改。引用仍然有效,但将在将来移除。
// Old
function onAfterRenderModules(&$content, &$params){
$content .= '<strong>foobar</strong>';
}

// New
function onAfterRenderModules(Joomla\CMS\Event\Module\AfterRenderModulesEvent $event){
$content = $event->getContent();
$content .= '<strong>foobar</strong>';

$event->updateContent($content);
}

模块事件 onPrepareModuleListonAfterModuleListonAfterCleanModuleList 向后兼容性

  • PR: https://github.com/joomla/joomla-cms/pull/41780
  • 描述:onPrepareModuleListonAfterModuleListonAfterCleanModuleList 现在应使用 $event->getModules()$event->updateModules($module),而不是通过引用修改。引用仍然有效,但将在将来移除。modules 参数现在始终初始化为空数组。这是为了保持一致性(类型提示)并允许旧版插件使用引用。
// Old
function onAfterModuleList(&$modules){
unset($modules[3]);
}

// New
function onAfterModuleList(Joomla\CMS\Event\Module\AfterModuleListEvent $event){
$modules = $event->getModules();

unset($modules[3]);

$event->updateModules($modules);
}

自定义字段事件 onCustomFieldsAfterPrepareField 向后兼容性

  • PR: https://github.com/joomla/joomla-cms/pull/41495
  • 描述:onCustomFieldsAfterPrepareField 现在应使用 $event->getValue()$event->updateValue($value),而不是通过引用修改。引用仍然有效,但将在将来移除。
// Old
function onCustomFieldsAfterPrepareField($context, $item, $field, &$value){
$value .= '<strong>foobar</strong>';
}

// New
function onCustomFieldsAfterPrepareField(Joomla\CMS\Event\CustomFields\AfterPrepareFieldEvent $event){
$value = $event->getValue();
$value .= '<strong>foobar</strong>';

$event->updateValue($value);
}

安装程序事件 onInstallerBeforeInstallationonInstallerBeforeInstalleronInstallerAfterInstaller 向后兼容性

  • PR: https://github.com/joomla/joomla-cms/pull/41518
  • 描述:onInstallerBeforeInstallationonInstallerBeforeInstaller 现在应使用 $event->getPackage()$event->updatePackage($package),而不是通过引用修改。引用仍然有效,但将在将来移除。
// Old
function onInstallerBeforeInstaller($model, &$package){
$package['foo'] = 'bar';
}

// New
function onInstallerBeforeInstaller(Joomla\CMS\Event\Installer\BeforeInstallerEvent $event){
$package = $event->getPackage() ?: [];
$package['foo'] = 'bar';

$event->updatePackage($package);
}

此外,onInstallerAfterInstaller 应使用 $event->getInstallerResult()$event->updateInstallerResult($result)$event->getMessage()$event->updateMessage($message)

安装程序事件 onInstallerBeforePackageDownload 向后兼容性

  • PR: https://github.com/joomla/joomla-cms/pull/41518
  • 描述:onInstallerBeforePackageDownload 现在应使用 $event->getUrl()$event->updateUrl($url)$event->getHeaders()$event->updateHeaders($headers),而不是通过引用修改。引用仍然有效,但将在将来移除。
// Old
function onInstallerBeforePackageDownload(&$url, &$headers){
$url .= '&foo=bar';
}

// New
function onInstallerBeforePackageDownload(Joomla\CMS\Event\Installer\BeforePackageDownloadEvent $event){
$url = $event->getUrl();
$url .= '&foo=bar';

$headers = $event->getHeaders();
$headers['foo'] = 'bar';

$event->updateUrl($url);
$event->updateHeaders($headers);
}

内容事件 onContentBeforeValidateData 向后兼容性

// Old
function onContentBeforeValidateData($context, &$data){
$data['foo'] = 'bar';
}

// New
function onContentBeforeValidateData(Joomla\CMS\Event\Model\BeforeValidateDataEvent $event){
$data = $event->getData();
$data['foo'] = 'bar';

$event->updateData($data);
}

内容事件 onContentPrepareData 向后兼容性

// Old
function onContentPrepareData($context, &$data){
$data['foo'] = 'bar';
}

// New
function onContentPrepareData(Joomla\CMS\Event\Model\PrepareDataEvent $event){
// Note: The data may be or Object or Array, following changes need only when data is an Array
$data = $event->getData();
$data['foo'] = 'bar';

$event->updateData($data);
}

联系事件 onValidateContact 向后兼容性

联系事件 onSubmitContact 向后兼容性

// Old
function onSubmitContact($contact, &$data){
$data['foo'] = 'bar';
}

// New
function onSubmitContact(Joomla\CMS\Event\Contact\SubmitContactEvent $event){
$data = $event->getData();
$data['foo'] = 'bar';

$event->updateData($data);
}
// Old
function onPreprocessMenuItems($context, &$items, $params, $enabled){
unset($items[3]);
}

// New
function onPreprocessMenuItems(Joomla\CMS\Event\Menu\PreprocessMenuItemsEvent $event){
$items = $event->getItems();

unset($items[3]);

$event->updateItems($items);
}
  • PR: https://github.com/joomla/joomla-cms/pull/41780
  • 描述:onAfterGetMenuTypeOptions 现在应该使用 $event->getItems()$event->updateItems($items),而不是通过引用修改。引用仍然有效,但将在未来移除。
// Old
function onAfterGetMenuTypeOptions(&$items, $model){
unset($items[3]);
}

// New
function onAfterGetMenuTypeOptions(Joomla\CMS\Event\Menu\AfterGetMenuTypeOptionsEvent $event){
$items = $event->getItems();

unset($items[3]);

$event->updateItems($items);
}

用户组事件 onUserBeforeDeleteGrouponUserAfterDeleteGroup 向后兼容性

// Old
function onUserBeforeDeleteGroup($data){
}

// New
function onUserBeforeDeleteGroup(Joomla\CMS\Event\User\UserGroupBeforeDeleteEvent $event){
$context = $event->getContext();
$data = $event->getItem()->getProperties();

}

CategoryFeedView 继承

\Joomla\CMS\MVC\View\CategoryFeedView 直接扩展 \Joomla\CMS\MVC\View\AbstractView(之前它扩展了 \Joomla\CMS\MVC\View\HtmlView,后者又继承自 AbstractView),因为它不渲染任何 HTML。我们预计这不会对扩展产生重大影响。

移除第三方库

Joomla\Ldap

我们自己的 LDAP 库不再与 Joomla 5 兼容,它已被移除。作为此操作的一部分,我们从 b/c 插件中移除以下类别名

  • JClientLdap -> \Joomla\Ldap\LdapClient
  • JLDAP -> \Joomla\Ldap\LdapClient

Joomla 4 和 5 包含 symfony Ldap 包。

com_content > category > blog-links.php 和 com_content > featured > default-links.php 中的链接使用 <ul></ul> 而不是 <ol></ol>。更改通过 PR #40629 完成。

TinyMCE

模板的 editor.css 文件中定义的 CSS 类不再显示在格式下拉菜单或按钮中。如果您希望显示它们,可以通过启用 **新的** TinyMCE 插件选项 CSS 类菜单来实现。