WordPress 社区新闻

体验WordPress 7.1图标注册API

查看官方原文 ↗ 发布于

当WordPress 7.0今年早些时候推出图标块时,那是我一段时间以来最激动人心的时刻之一。但这也让我有些失望,因为没有公开的API来注册自定义图标。该方块可用的图标列表对大多数创意用途来说显得受限。

好消息是:公共API将随WordPress 7.1一起发布!

它几乎满足了我在项目中真正使用它所需的一切,比如我一直在琢磨的这个餐厅菜单创意:

WordPress 帖子编辑器显示餐厅菜单,分为四类供应类型。图标块已被选中,设置显示在侧边栏。

在这个教程中,我会带你了解一些基础知识。然后你会学会从头到尾构建一个完整的图标注册插件。

如何注册图标

本教程涵盖了使用API的入门层面,以及大多数用例相关的部分。想了解完整情况,请阅读 WordPress 7.1 开发者说明中的注册与渲染 SVG 图标。

注册功能的简要概述

注册自定义图标时,你需要做两件事:

  • 注册一个自定义图标集合,或者知道你想注册图标的现有集合的哪一个字符。
  • 注册你的图标到特定系列。

大多数插件和主题都需要自定义集合,这些集合可以通过以下函数注册:wp_register_icon_collection()

wp_register_icon_collection( string $slug, array $args );

该函数有两个参数,你必须将参数传递给它们:

  • $slug:为你的收藏插件提供独特的密钥。理想情况下,这个名称会加上你的插件/主题名称(例如,)。plugin-collection
  • $args:集合的参数数组:
    • label:一个可读且国际化的集合标签,用于界面界面。
    • description:一串国际化的字符串描述该收藏。

一旦你有了收藏,你将用来注册单个图标:wp_register_icon()

wp_register_icon( string $icon_name, array $icon_properties );

它还有两个参数:

  • $icon_name:一个集合命名空间的图标标识符。它必须以一个集合字条开始,后接一个(例如,)。/plugin-collection/icon-slug
  • $icon_properties:定义图标的参数数组:
    • label:一个国际化、人类可读的图标标签。
    • content:图标的SVG标记(可选)。
    • file_path:图标的SVG标记文件路径(可选)。

这两个都是可选参数,但你必须选择其中一个才能真正注册图标。contentfile_path

一个示例收藏与图标

在本教程后面,你将学习如何构建一个完整的餐厅图标集成插件。但我们先从一个简短的例子开始,展示你刚学到的函数如何运用。

注册集合和图标时,应该在挂钩上进行。以下代码,无论是添加到插件文件还是主题中,都会在餐厅集合下注册一个蛋糕图标:initfunctions.php

add_action('init', 'devblog_restaurant_icons_register');

function devblog_restaurant_icons_register(): void
{
	wp_register_icon_collection('devblog-restaurant', [
		'label'       => __('Restaurant', 'devblog-restaurant-icons'),
		'description' => __('Demo icons provided by the DevBlog Restaurant Icons plugin.', 'devblog-restaurant-icons')
	]);

	wp_register_icon('devblog-restaurant/cake', [
		'label'   => __('Cake', 'devblog-restaurant-icons'),
		'content' => '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#1f1f1f"><path d="M160-80q-17 0-28.5-11.5T120-120v-200q0-33 23.5-56.5T200-400v-160q0-33 23.5-56.5T280-640h160v-58q-18-12-29-29t-11-41q0-15 6-29.5t18-26.5l56-56 56 56q12 12 18 26.5t6 29.5q0 24-11 41t-29 29v58h160q33 0 56.5 23.5T760-560v160q33 0 56.5 23.5T840-320v200q0 17-11.5 28.5T800-80H160Zm120-320h400v-160H280v160Zm-80 240h560v-160H200v160Zm80-240h400-400Zm-80 240h560-560Zm560-240H200h560Z"/></svg>'
	]);
}

该代码使用上述属性而非。对于一次性的例子来说,这可能更好,因为它能显示完整的代码。你将在下面的完整插件示例中使用该属性。contentfile_pathfile_path

要测试已注册的集合和图标,请在帖子或网站编辑器中插入图标块,并在该块工具栏点击替换按钮。随后您将看到带有新餐厅标签页(即集合)的图标库:

WordPress 帖子编辑器,界面覆盖图标库模态。选择了餐厅图标收藏标签,显示一个蛋糕图标。

选择蛋糕图标后,它会出现在图标块中,你可以用现有的设计工具进行自定义。

生成的区块标记如下:

<!-- wp:icon {"icon":"devblog-restaurant/cake"} /-->

如你所见,集合和图标字条都包含在内: 。你可以像使用其他方块一样,在模板或图案中使用这些标记。devblog-restaurant/cake

就新开发功能而言,这个相当直接。这就是大多数图标注册API使用时你需要知道的全部信息。

但让我们深入探讨在新API之上实际构建一个完整项目。

构建图标注册插件

如前所述,我有一个想法,想用图标做餐厅菜单页面。我知道在设计中点缀几个图标,会让读者更具视觉吸引力。

所以我来跟你讲讲我是怎么构建一个插件来添加这些图标的。所有代码分步骤展示,你也可以在其GitHub仓库中学习完整代码。

插件设置

和其他插件一样,你必须在下面创建一个新文件夹,并在里面放一个主插件文件。你还需要几个子文件夹来做这个项目。请创建一个插件目录,结构如下:wp-content/plugins

  • devblog-restaurant-icons/
    • public/
      • icon/
    • src/
      • plugin.php

然后通过你喜欢的代码编辑器添加以下代码:plugin.php

<?php

/**
 * Plugin Name:       DevBlog: Restaurant Icons
 * Plugin URI:        https://github.com/wptrainingteam/devblog-restaurant-icons
 * Description:       WordPress 7.1+ demo plugin for registering icon collections.
 * Version:           1.0.0
 * Requires at least: 7.1
 * Requires PHP:      8.1
 * Author:            Developer Blog
 * Author URI:        https://developer.wordpress.org/news
 * License:           GPL-3.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-3.0.html
 * Text Domain:       devblog-restaurant-icons
 */

declare(strict_types=1);

namespace DevBlog\RestaurantIcons;

# Prevent direct access.
defined('ABSPATH') || exit;

# Define the plugin constants.
const PLUGIN_DIR = __DIR__;

这些大多是制作插件的模板内容。但请注意一个常数;你以后会提到这个。PLUGIN_DIR

在编辑器中保持这个文件打开。你还会在本教程后面添加更多代码。

我把它做成插件,但你也可以通过主题注册图标。唯一的区别是图标SVG文件的加载点。你可以在主题上下文中跳过上述代码。

插件中的图标捆绑

在这个项目中,我使用了谷歌Material Icons库中的多个与食物相关的图标。你可以直接从那里拉取,或者直接从本项目的GitHub仓库文件夹获取列表。

拿到图标后,把它们放进插件里的文件夹里。你的文件夹结构应该是这样的:public/icon

  • icon/
    • bakery.svg
    • bento.svg
    • breakfast.svg
    • brunch.svg
    • cake.svg
    • dinner.svg
    • kebab.svg
    • lunch.svg
    • ramen.svg
    • restaurant.svg
    • rice-bowl.svg
    • soup-kitchen.svg
    • tapas.svg

定义图标数据结构

在 PHP 中表示图标值的方法有很多种。你可以用普通数组、常量、生成像WordPress本身那样的图标清单(也是数组),或者在代码里包含大量调用。wp_register_icon()

我不喜欢那些方法。PHP 已经有五年的枚举(枚举)功能(自 8.1 版本起)。在这种情况下,我更倾向于使用字符串支持的枚举,以保证编译时安全和自动补全。而且,没有魔法线!

在你的插件文件夹里,创建一个新文件,并添加以下代码:srcIcon.php

<?php

declare(strict_types=1);

namespace DevBlog\RestaurantIcons;

enum Icon: string
{
	case Bakery      = 'bakery';
	case Bento       = 'bento';
	case Breakfast   = 'breakfast';
	case Brunch      = 'brunch';
	case Cake        = 'cake';
	case Dinner      = 'dinner';
	case Kebab       = 'kebab';
	case Lunch       = 'lunch';
	case Ramen       = 'ramen';
	case Restaurant  = 'restaurant';
	case RiceBowl    = 'rice-bowl';
	case SoupKitchen = 'soup-kitchen';
	case Tapas       = 'tapas';

	// Additional code for the enum goes here...
}

如你所见,每个枚举大小写代表你在上一步添加的一个图标文件名(不含扩展名)。.svg

你还需要为图标准备其他几项数据:

  • 集合的蛞蝓:。devblog-restaurant
  • 插件中图标存储的绝对路径,也就是你之前添加的常数 + 相对路径。PLUGIN_DIRpublic/icon

在枚举定义中将这些作为常数加入:

public const COLLECTION = 'devblog-restaurant';

private const ICONS_PATH = PLUGIN_DIR . '/public/icon';

枚举在这种情况下还需要携带某种行为。如前所述,注册图标需要三项信息:名称、标签和SVG。所以这些东西都需要在枚举中等价地返回数据。Icon

首先,在枚举中添加一个新方法:label()

public function label(): string
{
	return match ($this) {
		self::Bakery      => __('Bakery', 'devblog-restaurant-icons'),
		self::Bento       => __('Bento', 'devblog-restaurant-icons'),
		self::Breakfast   => __('Breakfast', 'devblog-restaurant-icons'),
		self::Brunch      => __('Brunch', 'devblog-restaurant-icons'),
		self::Cake        => __('Cake', 'devblog-restaurant-icons'),
		self::Dinner      => __('Dinner', 'devblog-restaurant-icons'),
		self::Kebab       => __('Kebab', 'devblog-restaurant-icons'),
		self::Lunch       => __('Lunch', 'devblog-restaurant-icons'),
		self::Ramen       => __('Ramen', 'devblog-restaurant-icons'),
		self::Restaurant  => __('Restaurant', 'devblog-restaurant-icons'),
		self::RiceBowl    => __('Rice Bowl', 'devblog-restaurant-icons'),
		self::SoupKitchen => __('Soup Kitchen', 'devblog-restaurant-icons'),
		self::Tapas       => __('Tapas', 'devblog-restaurant-icons')
	};
}

该方法的用途match()返回当前ENUM案例的国际化文本标签。

接下来,向枚举添加一个方法:handle()

public function handle(): string
{
	return self::COLLECTION . '/' . $this->value;
}

因为图标名需要与集合名称一起命名,我们可以在这里直接在前面加上。所以每当你需要引用图标的完整句柄/名称时,都可以调用 。Icon::CaseName->handle()

最后,你需要一种方法将绝对文件路径引用到 SVG,所以在枚举中添加一个方法:filePath()

public function filePath(): string
{
	return self::ICONS_PATH . '/' . $this->value . '.svg';
}

注意,如果在主题中构建,请使用 。根本不需要恒定。get_theme_file_path("public/icon/{$this->value}.svg")ICONS_PATH

使用支持的枚举代替数组,可以实现编译时的安全性和自动补全。例如,是真实且可检查的类型,PHP 验证它,IDE 也能自动补全;而数组键(如 Array 键)只是字符串,拼写错误,可以无声无误地破解直到运行时。IconIcon::Cake$icons['cake']

枚举还让行为与数据并存。像 、 和 这样的方法,每例通过 定义一次。添加新图标意味着每个方法只添加一个案例和一行,PHP 匹配系统会通过静态分析或运行时提醒你如果案件未处理。label()handle()filePath()matchUnhandledMatchError

枚举使所有有效图标成为封闭、可发现且自我文档化的,而不是分散在数组中的开放式“魔法字符串”集合。

用WordPress注册图标

现在你已经有了类型安全、IDE友好的代码图标表示,剩下的就是通知WordPress了。你可以用一个小班级来完成,他们唯一的责任就是注册图标。

创建一个名为 的新文件。然后添加以下代码:srcIconRegistrar.php

<?php

declare(strict_types=1);

namespace DevBlog\RestaurantIcons;

final class IconRegistrar
{
	public function boot(): void
	{
		add_action('init', $this->register(...));
	}

	private function register(): void
	{
		// Register the collection.
		wp_register_icon_collection(Icon::COLLECTION, [
			'label'       => __('Restaurant', 'devblog-restaurant-icons'),
			'description' => __('Demo icons provided by the DevBlog Restaurant Icons plugin.', 'devblog-restaurant-icons')
		]);

		// Register icons for the collection.
		foreach (Icon::cases() as $icon) {
			wp_register_icon($icon->handle(), [
				'label'     => $icon->label(),
				'file_path' => $icon->filePath()
			]);
		}
	}
}

该类有一个方法,调用时会添加 WordPress 钩子上的动作。然后,它会同时注册图标集合和单个图标。boot()register()init

因为你用的是字符串背板枚举,所以你会得到内置的静态cases()免费的方法,它会返回你的图标案例数组。所以上述代码只需循环每个案例,并将每个自定义方法的结果传递到 。wp_register_icon()

另外要注意的是,代码在注册集合时无需记住那个字符串。不用担心打错字!Icon::COLLECTION

加载插件文件并启动

最后几项:加载你刚创建的PHP文件并调用该方法。IconRegistrar::boot()

在你的文件底部,添加以下代码:plugin.php

# Load classes manually. In production, use an autoloader.
require_once PLUGIN_DIR . '/src/Icon.php';
require_once PLUGIN_DIR . '/src/IconRegistrar.php';

# Bootstrap services.
add_action('plugins_loaded', static function (): void {
	(new IconRegistrar())->boot();
});

现在如果你查看之前提到的图标库→餐厅标签页,应该能看到完整的注册图标列表:

WordPress 帖子编辑器,界面覆盖图标库模态。选择了餐厅图标收藏标签,以网格形式显示各种与食物相关的图标。

出场图标

如本文前述所述,您可以通过图标块中的名称来引用已注册的图标:

<!-- wp:icon {"icon":"devblog-restaurant/cake"} /-->

对于大型集合来说,这通常是个糟糕的开发体验,因为你必须记住具体的字符串名。如果字符串存在于某个普通数组中,就没有自动补全功能。

有了枚举,修正起来很容易,不用担心具体名称。为了确保你得到正确的蛋糕图标,请像这样引用:

<!-- wp:icon {"icon":"<?= Icon::Cake->handle() ?>"} /-->

如果你不在块上下文(例如经典主题或以其他方式作为插件输出的一部分),你可以使用以下函数:wp_get_icon()

<?= wp_get_icon(Icon::Cake->handle(), [
	'size' => 32
]) ?>

缺失的拼图:你还不能做到的

图标注册API现在非常强大,允许你注册大多数需求的图标。但 WordPress 7.1 仍然会有一些限制。这些功能正在为7.2版本及以后版本积极开发。

元素允许列表

目前,只有 、 和 被允许用于 SVG 图标的元素。其他一切都被剥离了。部分原因是WordPress目前还没有正式的SVG净化功能。这可能是7.1中高度自定义图标的最大限制因素。<svg><path><polygon>

目前正在进行永久居民的工作以解决这一限制。它添加了完整的元素集合,如 、 ,以及更多元素,同时对它们进行了净化处理。<circle><rect>

划画属性被剥离

与上述净化工单相关,目前不允许使用该属性,因此无法用它来样式SVG。这意味着你现在应该坚持用基于 的图标来定义你的图标颜色。strokefill

此外,从外部剥离,但存活于和。其理念是外部SVG元素应通过CSS样式(例如通过图标块或自定义CSS)进行样式化。fill<svg><path><polygon>

没有编辑器组件……还没

图标块是一个很好的开始,而一个合适的注册API让扩展器的功能更加强大。但如果说有什么让我更期待的,那就是用内置组件在其他方块内部添加图标。

该领域已有实验性工作,以下是下一个开发周期中值得关注的一些工作单:

当然,你随时可以自己构建一个自定义组件,并在此期间自己进行集成。有只读的 REST API 端点可用于图标。