社区新闻

[一钩定乾坤:区块分类的多种玩法]

查看官方原文 ↗ 发布于

你可能已经注意到WordPress区块是按分类组织的。但你知道吗?你并非必须接受这些默认分类。你可以调整它们,让它们为你所用。

你可以重命名它们。重新排序它们。添加全新的分类,包括为你的自定义区块创建新分类。甚至可能做到你我尚未想到的事情。

而这一切,你都可以通过一个钩子实现:block_categories_all

这个钩子是一个多功能工具,允许开发者自定义区块分类的组织方式。在本文中,你将学习如何使用这个钩子,并构建函数来添加、重新排序和重命名单个或多个区块分类。

在深入之前,需要注意的是,每个函数都接受一个参数,该参数应为现有区块分类的数组。在本文中,它被定义为 $categories

添加分类

如果你构建自定义区块,可能希望将它们放入一些自定义分类中。自定义分类也可能有其他用途——也许你正在构建一些具有自定义样式的区块。无论出于何种原因,这里有三种方法:

创建新分类

以下是如何使用 array_merge 将一个名为“自定义区块”的新分类添加到现有分类数组的末尾。

add_filter( 'block_categories_all', 'add_block_category', 10, 2 );

function add_block_category( $categories ) {
    $custom_category = array(
        array(
            'slug'  => 'custom-blocks',
            'title' => __( 'Custom Blocks', 'your-text-domain' ),
            'icon'  => null,
        ),
    );

    return array_merge( $categories, $custom_category );
}

首先创建一个接受单个参数的函数——记住,它期望的是现有 $categories 列表。在函数内部,创建一个名为 $custom_category 的变量,并分配一个包含以下键值对的数组:

  • slug — 分类的唯一标识符
  • title — 分类的显示名称
  • icon — 一个Dashicon或自定义SVG

注意:据我所知,我们目前没有在任何地方使用或显示 icon,因此在此示例中,你可以将其设置为 null。

然后,你将使用 array_merge 函数将 $custom_category 与现有的 $categories 列表合并。你可以根据将每个变量传递给 array_merge 的顺序,将新分类放在 $categories 之前或之后。

这是一个添加到区块插入器的自定义区块分类示例。

定位新分类

以下是如何使用 array_splice 将一个名为“自定义区块”的新分类添加到 $categories 的第二个位置(索引 1)。

add_filter( 'block_categories_all', 'add_order_block_category', 10, 2 );

function add_order_block_category( $categories ) {
    $custom_category = array(
        'slug'     => 'custom-blocks',
        'title'    => __( 'Custom Blocks', 'your-text-domain' ),
        'icon'     => null,
        'position' => 1,
    );

    // 从自定义分类数组中提取位置。
    $position = $custom_category['position'];

    // 从自定义分类数组中移除位置。
    unset( $custom_category['position'] );

    // 在期望的位置插入自定义分类。
    array_splice( $categories, $position, 0, array( $custom_category ) );

    return $categories;
}

首先创建一个函数和一个新的分类数组,类似于上一个示例。但这次你将添加一个 position 键,其值指定你希望新分类在 $categories 中的位置。

然后,你将提取 position 并将其设置为一个变量,以便在 array_splice 中使用,但在此之前,使用 unset 将位置从数组中移除——你不需要它。

最后,使用 array_splice 函数,它接受 4 个参数:

  1. 数组: 你想要修改的数组
  2. 偏移量: 你希望插入的位置
  3. 长度: 指定在偏移量之后要移除的项目数量
  4. 替换: 要在指定位置添加的元素数组

在你的 array_splice 中,传入 $categories、你在新分类数组中指定的位置、长度(在本例中为 0,因为我们不想移除任何内容),然后是你的新分类数组。

这是一个已添加并定位在文本区块分类下方的自定义区块分类在区块插入器中的示例。

添加并定位多个新分类

现在让我们一次性添加并定位一些分类。以下是如何将两个自定义分类插入到 $categories 的第二和第四位置。

add_filter( 'block_categories_all', 'add_order_multiple_block_categories', 10, 2 );

function add_order_multiple_block_categories( $categories ) {
    $custom_categories = array(
        array(
            'slug'     => 'custom-category-1',
            'title'    => __( 'Custom Category 1', 'your-text-domain' ),
            'icon'     => null,
            'position' => 1,
        ),
        array(
            'slug'     => 'custom-category-2',
            'title'    => __( 'Custom Category 2', 'your-text-domain' ),
            'icon'     => null,
            'position' => 3,
        ),
    );

    $added_categories = array();

    // 准备一个以位置为键的关联数组。
    foreach ( $custom_categories as $custom_category ) {
        $position = $custom_category['position'];
        unset( $custom_category['position'] );
        $added_categories[ $position ] = $custom_category;
    }

    // 按位置/键对要插入的分类进行排序。
    ksort( $added_categories );

    // 将排序后的分类插入到现有分类数组中。
    foreach ( $added_categories as $position => $custom_category ) {
        array_splice( $categories, $position, 0, array( $custom_category ) );
    }

    return $categories;
}

创建一个函数。在内部,创建一个名为 $custom_categories 的新分类数组,包括每个项目的期望位置。创建一个空数组以在下一步存储数据,将其命名为 $added_categories

接下来,遍历 $custom_categories 以提取并移除位置,并将其存储在 $added_categories 中,以新位置作为其键。然后添加一个 ksort 函数,以确保存储在 $added_categories 中的分类按其键排序。

最后添加 foreach 并遍历 $added_categories,使用 array_splice 将每个分类插入到期望的位置。最后,使用 array_values 重新索引分类,以确保新分类列表中的顺序正确。

这是一个在区块插入器中,多个自定义区块分类被添加并定位在媒体区块分类上方和下方的示例。

重新排序分类

你也可以使用 block_categories_all 钩子来重新排序区块编辑器中的现有分类列表。无论你是想移动单个分类还是重新排列多个分类,这里有一些方法可以让你更好地控制两者。

重新排序单个分类

以下是如何通过移除并重新插入,使用 array_splice PHP 函数将现有数组中的 设计 分类重新排序到第二个位置。

add_filter( 'block_categories_all', 'reorder_design_category', 10, 2 );

function reorder_design_category( $categories ) {
    $design_category = null;
    $new_position    = 1;

    // 从现有分类中移除设计分类。
    foreach ( $categories as $key => $category ) {
        if ( 'design' === $category['slug'] ) {
            $design_category = $category;
            unset( $categories[ $key ] );
            break;
        }
    }

    // 如果设计分类存在,将其插入到新位置。
    if ( $design_category ) {
        array_splice( $categories, $new_position, 0, array( $design_category ) );
    }

    // 重新索引数组。
    return array_values( $categories );
}

首先在函数内部设置两个变量,一个名为 $design_category 设置为 null,稍后你将用它来存储设计分类(或你希望移动的任何分类),另一个名为 $position,指定你想要移动到的位置。然后,添加一个 foreach,它将遍历现有分类以查找匹配的分类 slug,将其存储在 $design_category 中,并使用 unset 将其从现有列表中移除。

现在检查是否有任何数据存储在你的变量中,并使用 array_splice 将分类插入到期望的位置,就像你在上面的新分类函数中所做的那样。最后,使用 array_values 重新索引分类,以确保顺序正确。

这是一个设计分类被重新定位到文本分类下方在区块插入器中的示例。

重新排序多个分类

以下是如何通过移除和重新插入,使用 array_splice设计文本 分类重新排序到第一和第四位置。

add_filter( 'block_categories_all', 'reorder_multiple_categories', 10, 2 );

function reorder_multiple_categories( $categories ) {
    $reorder_categories = array(
        'design' => 0,
        'text'   => 3,
    );

    $moved_categories = array();

    // 遍历现有分类,添加/移除需要重新排序的分类。
    foreach ( $categories as $key => $category ) {
        if ( array_key_exists( $category['slug'], $reorder_categories ) ) {
            $moved_categories[ $reorder_categories[ $category['slug'] ] ] = $category;
            unset( $categories[ $key ] );
        }
    }

    // 按新位置对移动的分类进行排序。
    ksort( $moved_categories );

    // 将移动的分类插入到它们的新位置。
    foreach ( $moved_categories as $position => $category ) {
        array_splice( $categories, $position, 0, array( $category ) );
    }

    // 重新索引数组。
    $categories = array_values( $categories );

    return $categories;
}

首先在函数内部创建一个名为 $reorder_categories 的关联数组。键可以是你要重新排序的分类,值则是它们的新位置。你还需要创建一个空数组以在下一步存储数据,将其命名为 $moved_categories

当检查找到匹配项时,函数会将分类添加到 $moved_categories 中,以你指定的位置作为其键。unset 函数会将该分类从 $categories 中移除。

现在添加一个 ksort 函数来按键对分类进行排序。

添加一个 foreach 来遍历 $moved_categories,使用 array_splice 将每个分类插入到其适当的位置。最后,使用 array_values 重新索引分类,以便新的 $categories 列表中的顺序正确。

这是一个设计分类移动到区块插入器顶部,而文本分类移动到媒体下方第三位置的示例。

重命名分类

你也可以使用 block_categories_all 来重命名区块编辑器中的分类列表。想重命名一个分类?想重命名所有分类?这里有一些方法可以让你完全掌控。

重命名一个分类

也许你想将 文本 分类重命名为 文本元素

add_filter( 'block_categories_all', 'rename_text_category', 10, 2 );

function rename_text_category( $categories ) {
    foreach ( $categories as &$category ) {
        if ( $category['slug'] === 'text' ) {
            $category['title'] = __( 'Text Elements', 'your-text-domain' );
        }
    }

    return $categories;
}

首先使用一个 foreach。遍历 $categories,寻找 slug 等于 text 的分类。如果 text 存在,则将分类标题重命名为 Text Elements

这是一个将文本分类重命名为文本元素在区块插入器中的示例。

重命名多个分类

或者,你可能真的想将 文本媒体 分类重命名为 文本元素媒体和文本元素

add_filter( 'block_categories_all', 'rename_multiple_categories', 10, 2 );

function rename_multiple_categories( $categories ) {
    foreach ( $categories as &$category ) {
        if ( $category['slug'] === 'text' ) {
            $category['title'] = __( 'Text Elements', 'your-text-domain' );
        }
        if ( $category['slug'] === 'media' ) {
            $category['title'] = __( 'Media and Text Elements', 'your-text-domain' );
        }
    }

    return $categories;
}

要在一个函数中重命名多个分类,请遵循与重命名单个分类相同的步骤。只需根据需要添加尽可能多的分类 slug 检查。

这是一个文本分类被重命名为文本元素,媒体分类被重命名为媒体和文本元素在区块插入器中的示例。

整合所有功能

最后。这里你拥有了一切——完全控制现有分类的名称和位置,以及添加新分类的能力。

add_filter( 'block_categories_all', 'modify_block_categories', 10, 2 );

function modify_block_categories( $categories ) {
    $new_category_order = array(
        array(
            'slug'     => 'media',
            'title'    => __( 'Media and Text Elements', 'your-text-domain' ),
            'position' => 0,
        ),
        array(
            'slug'     => 'custom-blocks',
            'title'    => __( 'Custom Blocks', 'your-text-domain' ),
            'position' => 1,
        ),
        array(
            'slug'     => 'text',
            'title'    => __( 'Text Elements', 'your-text-domain' ),
            'position' => 2,
        ),
        array(
            'slug'     => 'embed',
            'position' => 3,
        ),
        array(
            'slug'     => 'design',
            'position' => 4,
        ),
    );

    // 创建一个以slug为键的区块分类关联数组。
    $current_block_categories = array_column( $categories, 'title', 'slug' );

    // 检查新分类顺序是否设置了标题,否则使用默认标题。
    foreach ( $new_category_order as &$new_category ) {
        $new_category['title'] = $new_category['title'] ?? $current_block_categories[ $new_category['slug'] ] ?? __( 'Untitled', 'your-text-domain' );
    }

    // 从新分类顺序创建一个slug数组。
    $new_category_slugs = array_column( $new_category_order, 'slug' );

    // 过滤掉不在新顺序中的剩余区块分类。
    $remaining_categories = array_filter( $categories, function ( $category ) use ( $new_category_slugs ) {
        return ! in_array( $category['slug'], $new_category_slugs, true );
    } );

    // 将新分类顺序与剩余分类合并。
    return array_merge( $new_category_order, $remaining_categories );
}

首先定义一个名为 $new_category_order 的分类数组,其中包含你想要添加、重新排序或重命名的分类。现在,slug 是标识每个条目所必需的。根据你想要修改的内容,titleposition 是可选的。

首先,通过使用 array_column$categories 创建一个名为 $current_block_categories 的关联数组(以分类 slug 为键)来更新任何分类标题。然后使用 foreach 遍历 $new_category_order,检查数组中是否有任何项目设置了新标题,并在必要时更新它们。如果没有设置新的 title,它将根据 slug$current_block_categories 中提取。如果由于某种原因没有找到 slug,则将使用 Untitled

现在,通过遍历 $new_category_order,检查任何具有新位置的分类,然后将其作为键添加到名为 $moved_categories 的数组中,来构建一个分类的关联数组。

然后使用 ksort 根据位置对 $moved_categories 进行排序。添加一个 foreach 并遍历 $moved_categories,使用 array_splice 将每个分类插入到位置。

现在新的标题和位置已经处理完毕,是时候过滤掉剩余的分类,以便将所有内容重新整合在一起。首先,使用 array_column$new_category_order 创建一个名为 $new_category_slugs 的 slug 数组。然后创建一个名为 $remaining_categories 的变量,它使用 array_filter$categories 中移除那些 slug 不在 $new_category_slugs 中的项目。

最后,使用 array_merge 将新分类顺序与 $remaining_categories 合并,以返回一个完整的修改后的区块分类列表。

这是一个主函数示例,它重命名并重新排序了文本和媒体分类,同时添加了一个自定义区块分类,以及这在区块插入器中的样子。

结论

block_categories_all 钩子让你可以按照你需要的任何方式让区块分类工作——为你的项目和你的用户,以及他们将创建的所有内容。

而且,说真的,这些函数仅仅是个开始。你将如何使用它们?你还有其他方法吗,或者你能看到它们有创意的变体吗?留下评论吧!