lightsource/acf-groups


README

1. 这是什么?

这是一个composer包,提供了一种在代码中处理ACF组的替代方法。

2. 为什么我应该使用这个包而不是内置的ACF函数get/set_field?

ACF组有很好的管理界面,但当你使用代码中的get/set_field函数时,由于它会出现一些问题。最大的问题是

a) 类型问题

get_field函数用于获取所有类型的字段。
这意味着你总是应该记住返回的类型值(int/string/bool...),还要记住如果没有值,将返回NULL
这是一个容易犯错误的地方。

b) 同步问题

每个组的变化都必须与你的代码同步。
有一个很好的内置功能,本地.json文件,用于缓存(无需数据库请求)和在不同环境(如Dev/Live)之间的同步,但它无法解决这个问题。
例如,当你更改管理界面中的字段名称时,你必须在代码中找到所有使用该名称的地方并进行替换。IDE建议在这里不起作用。通常有很多组,有些字段的名称很相似。通常很难理解是要重命名的目标名称,还是另一个。所有其他更改,如类型更改或添加新字段,也会发生同样的事情。

3. 这个包建议什么?

  • OOP方式 - 每个组都有自己的类,每个类字段对应于一个组字段。
  • 字段有严格的PHP类型(int/string...)和公共可见性,因此不需要setter/getter(节省创建时间)。
  • 所有类字段将在构造函数中自动使用默认值进行初始化(取决于类型)
  • 使用源参数(如$postId)调用load()方法,并将值从数据库读取并保存到类字段中。
  • 如果你要修改值,只需更新公共字段并调用save()方法,它将找出与默认值之间的差异,并将其保存到数据库中。

该包提供了两种使用组的方式

a) 本地ACF组

将使用本地组的ACF功能(了解'acf_add_local_field_group'函数)。
这意味着该包将从类中获取有关组的所有必要信息,并创建一个本地ACF组。
这个组不会显示在管理界面组列表中,但会像普通组一样工作,因此字段将在选择的位置(帖子/页面屏幕...)显示,并可以从代码中读取。
在这种情况下,你不需要担心同步,例如,你只需在类中添加一个新字段,它就会应用于管理界面,并在你的代码中可用,无需进行数据库更改

b) 数据库表示

如果第一种方法不起作用或不适合你,例如对于旧组,或者你仍然想有管理界面组列表,那么你可以使用组类作为数据库组的表示,
这样就解决了类型问题,并部分解决了同步问题,这意味着代码更改仍然需要,但将在一个文件内完成,IDE将在这方面提供帮助

4. 如何使用

a) 安装包

composer require lightsource/acf-groups

b) 需要composer自动加载器

require_once __DIR__ . '/vendors/vendor/autoload.php';

c) 创建组(扩展AcfGroup类),使用创建器创建组实例并加载/保存值

use LightSource\AcfGroups\AcfGroup;
use LightSource\AcfGroups\Creator;

class MyGroup extends AcfGroup
{
    // this constant has sense only if you use the local acf groups way, see more in the Notes
    const LOCATION_RULES = [
        [
            'post_type == page',
        ],
    ];

    // supported simple types : string, int, float, bool
    public string $firstName;
    public string $lastName;
    // clones feature, more in the Notes
    public SecondGroup $secondGroup;
    // repeater of clones feature, more in the Notes
    /**
     * @item \Namespace\SecondGroup
     */
    public array $secondGroups;
}

////////

// use one creator instance for all groups
$creator = new Creator();
$myGroup = $creator->create(MyGroup::class);

$myGroup->load(21);
echo $myGroup->firstName;

$myGroup->firstName = 'NewName';
$myGroup->save();

d) 可选的。仅当使用本地ACF组方式时

在ACF中注册你的组

use LightSource\AcfGroups\Loader;

$loader  = new Loader();
$loader->signUpGroups('YOUR_NAMESPACE', 'YOUR_PATH');

5. 高级

Acf 群组位置规则

如果您使用本地 acf 群组方式,那么您必须覆盖群组类中的 LOCATION_RULES 常量来设置位置规则。有关常量值的

/**
     * Should be overridden to set up location rules
     * content sample :
     * [
     *      'post_type == x',
     *      'page_template == x',
     * ],
     * [
     *      'block == x',
     * ],
     * One sub-array = one rules group. All parts within will be combined with the 'AND' rule.
     * Rule groups between self will be combined with the 'OR' rule.
     * Every string contains from 3 parts, that combined by a space : 'ParamName Operator Value'
     */

如果您需要设置动态规则的机会,可以覆盖 getLocationRules() 方法。例如

protected static function getLocationRules(): array
{
    $blockName = 'x';
     return [
        [
            'post_type == ' . $blockName,
        ],
    ];
}

字段设置

任何 acf 字段参数都可以通过 phpDoc 注释设置。例如

/**
* @required 1
* @instructions First name. This field...
*/
public string $firstName;

有关可用设置的详细信息,请参阅 acf 文档。支持在参数值中的 Json,并将其解码 - 请参阅选择字段示例。您还可以使用 a-type 别名代替 type 参数(以避免 IDE 警告)。您可以使用 a-order 参数更改字段顺序(例如,对于扩展类很有用)

选项卡字段示例

/**
* @type tab
* @placement left
*/
public bool $general;

图像字段示例

// 'a-type' here just an alias for 'type', you can use what's preferred for you
/**
* @a-type image
* @return_format id
*/
public int $logo;

选择字段示例

// json in the choices argument will be decoded
/**
* @type select
* @choices {"left":"Left","center": "Center","right": "Right"}
* @default_value left
*/
public string $align;

默认字段值

如果 get_field 函数返回 NULL,则字段将以类型(0、''、false)的默认值进行初始化

克隆

Acf 克隆功能得到支持,因此一个群组可以包含另一个群组在字段中。默认情况下,克隆将包装在选项卡字段中以便舒适使用(可以通过在克隆字段的 phpDoc 中添加 '@a-no-tab 1' 来禁用它)

class FirstGroup extends AbstractAcfGroup{
    public SecondGroup $groupField;
}
class SecondGroup extends AbstractAcfGroup{
    public string $stringField;
}

幕后。在相关的 acf 字段设置中,将使用 clone 类型以及 prefix_name 功能,因此所有 SecondGroup 字段都将具有来自 FirstGroup 类的前缀,
并且 $stringField 字段的最终名称将为 PREFIX_first-group__group-field_PREFIX_second-group__string-field

克隆的重复项

Acf 重复功能得到支持(仅限克隆)。
为此,您应该声明一个具有数组类型的字段,并填写 php-doc @item 参数,它应指向目标群组类(包含您命名空间的全类名)。
您还可以为 IDE 建议设置 php-doc @var 参数,但这不是必需的。
(目前以这种方式无法拥有 ACF UI 中的简单字段重复项,但如果您在考虑这一点,您会理解这几乎是一样的,您只需为项目字段创建一个组)。默认情况下,重复项将包装在选项卡字段中以便舒适使用(可以通过在数组字段的 phpDoc 中添加 '@a-no-tab 1' 来禁用它)

class FirstGroup extends AbstractAcfGroup{
    /**
     * @var SecondGroup[]
     * @item \Namespace\SecondGroup
     */
    public array $groupField;
}
class SecondGroup extends AbstractAcfGroup{
    public string $stringField;
}

幕后。在 ACF 中,将创建一个具有一个指向目标群的克隆字段的重复字段。由于避免双重前缀,因此不使用 prefix_name 功能,所以最终字段名称将为:PREFIXfirst-group__groupField_0_PREFIXsecond-group__string-field。此外,重复项将包装在选项卡字段中以便舒适使用

Acf 群组名称

= PREFIX.'class-name'
Acf 群组名称将基于类名,将 ClassName 转换为 class-name。默认情况下,AbstractAcfGroup::GROUP_NAME_PREFIX 包含一个前缀并具有 local_ 值,它用于避免与您已存在的群组发生冲突。如果有理由更改它,您可以通过覆盖常量来更改它,有关详细信息,请参阅 附加常量 信息

Acf 字段名称

= $groupName.'__'.field-name'
Acf 字段名称将基于类名和字段名,将 fieldName 转换为 field-name。如果您需要获取 acf 字段名称(例如在数据库查询中使用) - 您应该使用 getAcfFieldName() 方法

Acf 字段标签

= Field Name
Acf 字段标签将基于字段名,将 fieldName 转换为 Field Name
您可以通过字段 phpDoc 中的 @label 参数或覆盖 getAcfFieldLabel() 方法来覆盖它

附加常量。

  • GROUP_NAME_PREFIX 默认为 local_,可以被更改为其他名称。如果您想更改多个组的名称前缀,可以创建一个包装器来覆盖常量并从包装器扩展所有组
  • IS_LOCAL_GROUP 常量可以被覆盖为 false,如果您使用本地 acf 组方式但想排除某些类自动加载
  • CUSTOM_GROUP_NAME 常量可以被覆盖,如果您的组名称不遵循上述的命名约定。仅用于支持旧版组的场景。在这种情况下,甚至将跳过 GROUP_NAME_PREFIX 常量