跳到正文
原文
WordPress 开发者博客· Justin Tadlock·· 2026-08-19精选编辑评分73

WordPress 7.1 图标注册 API 实战教程

Hands-on with the WordPress 7.1 Icon Registration API

编辑导读

WordPress 7.1 新增公开的 Icon Registration API,可通过 wp_register_icon_collection 和 wp_register_icon 注册图标集合与 SVG 图标。

推荐理由

文章从注册函数到完整插件逐步演示 WordPress 7.1 图标注册 API,并说明现有 SVG 元素和属性限制。

今年早些时候 WordPress 7.0 推出 Icon 区块时,那是我一段时间以来最令人兴奋的时刻之一。但它也多少让人有些失望,因为当时没有用于注册自定义图标的公开 API。对该区块的大多数创意用途而言,可选图标列表显得过于受限。 

好消息是:公开 API 将随 WordPress 7.1 一同推出!

它几乎实现了我在项目中真正使用它所需的所有功能,比如我一直在尝试的这个餐厅菜单创意:

WordPress post editor showing a restaurant menu in four groups of serving types. The Icon block is selected and its settings appear in the sidebar.

在本教程中,我会介绍其中的一些基础知识。随后,你将学习如何从头到尾构建一个完整的图标注册插件。

目录

  1. How to register icons
    1. 注册函数快速概览
    2. 图标集和图标示例
  2. Building an icon registration plugin
    1. 插件设置
    2. 在插件中打包图标
    3. 定义图标数据结构
    4. 向 WordPress 注册图标
    5. 加载插件文件并启动引导程序
    6. 输出图标
  3. The missing pieces: what you can’t yet do
    1. 元素允许列表
    2. Stroke 属性会被移除
    3. 尚无编辑器组件……

如何注册图标

本教程介绍了使用该 API 的入门知识,以及适用于大多数用例的相关部分。如需完整概览,请阅读《在 WordPress 7.1 中注册和渲染 SVG 图标》开发者说明。

注册函数快速概览

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

  • 注册一个自定义图标集,或者确定要为哪些图标注册内容的现有图标集的 slug。
  • 为特定图标集注册你的图标。

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

wp_register_icon_collection( string $slug, array $args );

该函数有两个参数,你需要为其传入参数:

  • $slug:插件中图标集的唯一键。理想情况下,应以插件或主题名称作为前缀(例如 plugin-collection)。
  • $args: An array of arguments for the collection:
    • label:图标集的易读国际化标签,用于界面显示。
    • description:描述该图标集的国际化字符串。

准备好图标集后,你可以使用 wp_register_icon() 注册单个图标:

wp_register_icon( string $icon_name, array $icon_properties );

它也有两个参数:

  • $icon_name:图标的集合命名空间标识符。它必须以图标集 slug 开头,后跟 /(例如 plugin-collection/icon-slug)。
  • $icon_properties: An array of arguments to define the icon:
    • label:图标的国际化易读标签。
    • content:图标的 SVG 标记(可选)。
    • file_path:SVG 标记文件的文件路径(可选)。

content 和 file_path 各自都是可选参数,但实际注册图标时必须选择其中之一。

图标集和图标示例

在本教程的后续内容中,你将学习如何构建一个包含餐厅图标集的完整插件。不过,我们先用一个简短示例来演示如何使用刚刚介绍过的这些函数。

注册图标集和图标时,应在 init 钩子上执行。以下代码可添加到插件文件或主题的 functions.php 中,它会在 Restaurant 图标集下注册一个 Cake 图标:

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>'
	]);
}

代码使用了上面的 content 属性,而不是 file_path。对于一次性示例,前者可能更合适,因为它会展示完整代码。你将在下面的完整插件示例中使用 file_path 属性。

要测试已注册的图标集和图标,请在文章编辑器或站点编辑器中插入 Icon 区块,然后点击区块工具栏中的 替换按钮。随后你会看到 图标库,其中包含新的 Restaurant选项卡(即图标集):

WordPress post editor with an Icon Library modal overlaying the screen. The Restaurant icon collection tab is selected, showing a single Cake icon.

选择 Cake 图标后,它会出现在 Icon 区块中,你可以使用现有的设计工具对其进行自定义。 

生成的区块标记如下:

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

如你所见,其中包含集合 slug 和图标 slug:devblog-restaurant/cake。你可以像使用其他任何区块一样,在模板或模式中使用这段标记。

就新开发功能而言,这项功能相当直接。对于 Icon Registration 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 文件的加载位置。在主题环境中,你可以跳过上述代码。

在插件中打包图标

在这个项目中,我使用了 Google 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 已经有枚举(enum)五年了(从 8.1 开始)。而在这种情况下,我更喜欢使用字符串支持的枚举,以获得编译时安全保障和自动补全。而且没有魔法字符串!

在插件的 src 文件夹中,创建一个名为 Icon.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 扩展名)。

你还需要为图标提供几项其他数据:

  • 集合 slug:devblog-restaurant。
  • 插件中图标存储位置的绝对路径,即你之前添加的 PLUGIN_DIR 常量加上 public/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() 返回当前枚举用例的国际化文本标签。

接下来,为枚举添加一个 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 常量。

使用字符串支持的枚举而不是数组,可以让 Icon 具备编译时类型安全性和自动补全。例如,Icon::Cake 是一个真实、可检查的类型,PHP 会对其进行验证,IDE 也能自动补全;而类似 $icons['cake'] 的数组键只是一个字符串,拼写错误可能悄无声息地导致问题,直到运行时才会报错。

枚举还可以让行为与数据放在一起。像 label()、handle() 和 filePath() 这样的方法可通过 match 为每个枚举值定义一次。添加新图标意味着添加一个枚举值以及每个方法中的一行代码;如果某个枚举值未处理,PHP 的 match 会通过静态分析或运行时 UnhandledMatchError 向你发出警告。

枚举使有效图标的完整集合封闭、可发现且自带文档说明,而不是一组散落在各数组中的开放式“魔法字符串”。

向 WordPress 注册图标

既然你已经用代码获得了类型安全、对 IDE 友好的图标表示,剩下的就是让 WordPress 知道这些图标。你可以创建一个职责单一的小类,用于注册图标。

在 src 下创建一个新文件,命名为 IconRegistrar.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()
			]);
		}
	}
}

该类有一个 boot() 方法,调用时会在 WordPress 的 init 钩子上添加 register() 操作。随后,它会注册图标集合及各个图标。

由于你使用了字符串支持的枚举,因此可以直接使用内置的静态 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();
});

现在,如果你查看之前看到的Icon Library → Restaurant选项卡,应该能看到已注册图标的完整列表:

WordPress post editor with an Icon Library modal overlaying the screen. The Restaurant icon collection tab is selected, showing various food-related icons in a grid.

输出图标

正如本文前面提到的,你可以在 Icon 块中通过名称引用已注册的图标:

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

对于大型集合来说,这通常会带来糟糕的开发体验,因为你必须记住确切的字符串名称。如果该字符串存放在其他位置的普通数组中,也不会获得自动补全。

使用枚举后,你可以轻松解决这一问题,无需担心确切名称。为确保获得正确的 Cake 图标,请这样引用:

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

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

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

缺失的部分:目前还无法实现的功能

Icon Registration API 到现在已经非常强大,可以注册满足大多数需求的图标。但仍有一些限制会随 WordPress 7.1 一同推出。这些功能目前正在为 7.2 及更高版本积极开发。

元素允许列表

目前,SVG 图标仅允许使用 <svg>、<path> 和 <polygon> 作为元素,其他所有内容都会被清除。部分原因是 WordPress 目前尚未提供用于清理 SVG 的正式函数。这很可能是 7.1 中高度自定义图标所面临的最大限制因素。

目前正在通过一个 PR 着手解决这一限制。该 PR 在进行清理的同时,添加了一整套元素,例如 <circle>、<rect> 等。

描边属性会被清除

与上述清理工单相关,目前 stroke 并不是允许使用的属性,因此无法使用它为 SVG 设置样式。这意味着,目前定义图标颜色时应使用基于 fill 的图标。

此外,fill 会从外层 <svg> 中清除,但会保留在 <path> 和 <polygon> 上。其思路是,外层 SVG 元素应通过 CSS 设置样式(例如通过 Icon 区块或自定义 CSS)。

尚无编辑器组件……

Icon 区块是一个很好的起点,而正式的注册 API 让扩展程序能够实现更强大的功能。但如果说有什么是我更加期待的,那就是使用内置组件在其他区块内添加图标。

这方面正在进行实验性工作,以下是下个开发周期值得关注的工单:

  • 将 IconPickerModal 移入 block-editor 以便重复使用
  • 添加更多折叠导航图标选项
  • 手风琴区块:区块使用加号而非 SVG 作为图标
  • 详情区块:允许从一组图标中进行选择

当然,在 meantime,您始终可以自行构建自定义组件并完成集成。目前已有专用于图标的只读 REST API 端点。

感谢 @bph 和 @welcher 审阅本文。

来源:WordPress 开发者博客 · https://developer.wordpress.org/news/2026/08/hands-on-with-the-wordpress-7-1-icon-registration-api/

部分链接为推广/关联链接。