一个Craft感知的array_walk()方法,以及一些非常方便的控制台命令,用于轻松地在元素或值集合上调用Craft服务方法。

4.0.1 2022-05-16 08:14 UTC

This package is auto-updated.

Last update: 2024-09-16 13:33:45 UTC


README

提供一个Craft感知的array_walk()方法,以及一些非常方便的控制台命令,允许您轻松地在元素或值集合上调用Craft服务方法。

作者:Michael Rog

TL;DR.

您想对一组元素执行某些批量操作。

也许您想通过一个简单的控制台命令进行临时操作。

或者,也许您想在PHP的一行代码中,在自定义组件中执行此操作。

您想对几个不同的元素集合和几个不同的批量操作进行操作,而不需要每次都编写新代码。

Walk提供了一个特殊的Craft感知的array_walk方法,用于将Craft组件方法应用于列表中的每个元素。

安装

从项目目录中运行composer require topshelfcraft/walk以使用Composer安装。

然后,访问CP中的设置 > 插件页面,并点击安装Walk插件。

Walk是什么意思?

将方法应用于列表中的每个项称为“遍历”数组。实际上,PHP提供了一个方法——array_walk()——用于执行此操作。

然而,PHP的array_walk方法并不了解Craft的components的设置,也不知道关于Elements的任何信息。

因此,虽然PHP的array_walk对于将PHP方法应用于数组中的每个项很有用,但此插件提供了一个Craft感知的遍历函数——craftyArrayWalk()——来在列表中的每个项上运行Craft组件方法。

是的!这将为我节省几分钟!我如何开始?

首先,您需要有一个可调用的函数。可调用的函数是在列表中的每个项上运行的函数。

可调用的通过其名称作为字符串指定。使用此插件,可调用的可以是:

  • Craft的一个原生组件中的方法:'component.method'
  • 插件模块组件中的方法:'plugin.component.method'
  • 任何可访问的自定义函数:'myCustomMethod'
  • 任何原生PHP函数,例如:'strtolower'

其次,您需要一个项目列表(一个数组)。

然后,只需调用craftyArrayWalk()方法,如下所示

$success = WalkHelper::craftyArrayWalk($elements, $callable);

它的工作方式基本上与原生的array_walk方法相同

  • 可调用的函数为数组中的每个项运行一次。
  • 对于每个步骤,将作为第一个参数传递给方法。
  • 将数组索引作为第二个参数传递给方法。
  • 数组项通过引用传递,这意味着如果在方法内部更改变量,它将在源数组中更改。
  • craftyArrayWalk()返回一个布尔值:true表示成功,false表示存在问题。

在技术上,您可以将任何有效的PHP可调用对象提供给craftyArrayWalk方法。但如果您已经有了可调用对象,您可能不需要这个插件。这个插件的方法相比原生array_walk的优势在于,它可以识别那些特殊的可调用字符串,这些字符串代表Craft中的方法。

如果需要,您也可以通过添加第三个参数来提供额外的自定义数据,如下所示

$success = WalkHelper::craftyArrayWalk($elements, $callable, $userdata);

$userdata将作为每个步骤中可调用方法的第三个参数传递。

所以,从技术角度来说,一个可调用方法具有以下签名

public function myMethod( $element [, $index [, $userdata ]] )

我需要一个例子。

让我们从PHP的本地array_walk的一个例子开始

您可以这样做

$myArray = ["Michael", "Aaron", "Andrew", "Brad", "Brandon"]

foreach ($myArray as $key => $value)
{
    $myArray[$key] = strtolower($value);
}

但这更漂亮

array_walk($myArray, 'strtolower');

这两个例子实现了相同的功能:之后,数组中的每个字符串项都将转换为小写。

现在让我们看看一个Crafty的例子。

您可以这样做

$myEntries = Entry::find()->all();

foreach ($myEntries as $entry)
{
    Craft::$app->getElements->saveElement($entry);
}

但这更紧凑

WalkHelper::craftyArrayWalk($myEntries, 'elements.saveElement');

在这两个例子中,查询中的每个条目都将被重新保存。

很酷...但我不想写任何PHP。那么,有哪些控制台命令呢?

这正是我编写这个插件的原因:我需要一个快速、便捷的方式来执行大量的索引/重新保存操作,最好是来自CLI,而不必为每个工作/标准组合编写新的自定义命令。

所以,废话不多说,我给你带来了... walk CLI命令

./craft walk [list] [callable] --[options]=blah --asJob

让我们来分析一下

  • [list]
    • 一个元素类型标识符(assetsentries等)
    • 一个元素ID标识符(assetIdsentryIds等)
    • 一个"计数"指令(countAssetscountEntries等)
  • [callable]是您要在每个项目上运行的函数/任务,如上所述。
  • 有几个支持[options],如下所述。
  • 特殊(可选)的--asJob选项...我会稍后介绍。
  • 选项的顺序是任意的。

如果您想重新保存所有博客条目...

./craft walk entries --section=blog --limit=null elements.saveElement

如果您有一个自定义服务方法,并且您想在每个用户上运行一次

./craft walk users --limit=null myPlugin.myComponent.myMethod

如果您的自定义方法接受元素ID而不是元素对象呢?

./craft walk entryIds myModule.myComponent.methodThatTakesAnId

哇!

或者,也许您想获取标准中元素的数量,而不对它们做任何实际的操作?

./craft walk countEntries --section=blog

命令选项

以下元素标准属性可以通过CLI选项设置

  • id
  • limit(一个数字,或null表示没有限制)
  • title
  • slug
  • relatedTo
  • source
  • sourceId
  • kind
  • filename
  • folderId
  • size
  • group
  • groupId
  • authorGroup
  • authorGroupId
  • authorId
  • locale
  • section
  • status

(...对于电子商务订单...)

  • dateOrdered
  • datePaid
  • email
  • gatewayId
  • hasPurchasables
  • isCompleted
  • isPaid
  • isUnpaid
  • orderStatus
  • orderStatusId
  • customerId

它支持自定义元素类型吗?

Walk CLI命令提供了Craft内置元素类型的简单快捷方式。但是,您可以通过提供其[完全限定]类名以及相关元素查询的[完全限定]类名来使用Walk与任何元素类型一起使用。

./craft walk/elements "mynamespace\elements\MyElementClass" --queryClass="mynamespace\elements\db\MyElementQuery" myPlugin.myComponent.myMethod

./craft walk/element-ids "craft\commerce\elements\Donation" --queryClass="craft\commerce\elements\db\DonationQuery" myPlugin.myComponent.methodThatTakesAnId

./craft walk/count "craft\elements\Entry" --queryClass="craft\elements\db\EntryQuery" elements.saveElement

哦,您还提到了作业...

假设您有很多元素...或者您的可调用方法性能密集...或者您需要在CLI连接关闭时继续运行...或者您更喜欢使用Craft队列逐个调度任务...

Walk有几个方法可以帮助。

1. 使用CLI安排可调用作业

您可以使用特殊的 --asJob 命令选项 将每一步行走调度为一个任务

./craft walk entries elements.saveElement --asJob

./craft walk entryIds myModule.someComponent.aMethod --asJob

这仍然会在每个条件中的元素或ID上调用一次可调用对象,但它将在任务内部执行 - 即每个元素/步骤一个请求。

如果您想跟踪队列进度,或者想要方便地重新运行因错误而失败的任务,这将非常方便。

在控制面板侧边栏中,这些显示为 CallOnElementCallOnValue 任务。

2. 使用PHP方法通过任务作为 可调用对象

WalkHelper::spawnJobs(MyJob::class, $elementsOrIds, $settings = [], $valParam = 'elementId')

可以使用 spawnJobs 方法为提供的集合中的每个元素或ID调度指定任务的实例。

任务通过完整的类名指定,就像您使用 Craft::$app->queue->push() 一样。

您可以在 $settings 参数中提供额外的设置数组,这些设置将应用于每个任务。

指定的任务应期望接收到包含元素ID的 elementId 设置。或者,您也可以使用 $valParam 参数更改将接收元素ID的设置的名称。

我可以用这个功能与任何数组吗?它 必须 是元素/ID吗?

控制台命令旨在对元素或ID的集合执行批量操作。

然而,如果您感觉聪明,您可以使用 craftyArrayWalk() 辅助方法与任何数组一起使用。

例如,如果您有一个电子邮件地址数组,并且有一个接受电子邮件地址作为其第一个参数的 processEmailAddress 服务方法...

$success = WalkHelper::craftyArrayWalk($emailAddresses, 'myPlugin.myService.processEmailAddress');

如果您想创建自己的控制台命令来遍历其他集合(即不是元素或元素ID),只需查看 WalkController 的源代码。您会发现复制/粘贴您的成功之路非常简单!

这太棒了!我还有一些问题。

StackExchange 上提出问题,并通过电子邮件或Discord向我发送URL。

系统要求是什么?

Craft 3.0+ 和 PHP 7.0+

我发现了一个错误。

请打开GitHub问题,提交到 3.x.dev 分支的PR,或者只是给我发电子邮件。

贡献者