topshelfcraft / walk
一个Craft感知的array_walk()方法,以及一些非常方便的控制台命令,用于轻松地在元素或值集合上调用Craft服务方法。
Requires
- craftcms/cms: ^4.0
- topshelfcraft/base: ^4.0.1
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]
是- 一个元素类型标识符(
assets
、entries
等) - 一个元素ID标识符(
assetIds
、entryIds
等) - 一个"计数"指令(
countAssets
、countEntries
等)
- 一个元素类型标识符(
[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上调用一次可调用对象,但它将在任务内部执行 - 即每个元素/步骤一个请求。
如果您想跟踪队列进度,或者想要方便地重新运行因错误而失败的任务,这将非常方便。
在控制面板侧边栏中,这些显示为 CallOnElement
和 CallOnValue
任务。
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,或者只是给我发电子邮件。
贡献者
- 插件开发: Michael Rog / @michaelrog
- 图标: Margot Nadot,通过 The Noun Project