生成与调度
要生成所有已启用的 Feed,请使用控制台命令:
php artisan feed:generate
执行后,feeds 表中所有已启用的 Feed(is_active = true)都会运行。也可以使用 config/feeds.php 文件中指定的表。
不带参数调用命令时,控制台会显示所有 Feed 的链接,包括 is_active 属性设为 false 的 Feed。
但这些 Feed 不会运行,而会被标记为 SKIP 状态。
单个 Feed
即使指定的 Feed 在数据库的 feeds 表中已禁用,它也仍会运行。
要生成指定 Feed,请调用 feed:generate 控制台命令,并将 feeds 表中的 Feed slug 作为参数传入:
php artisan feed:generate products
生成所选输出文件
对于配置了独立输出文件的 Feed,注册 slug 用于选择 Feed 类,目标键用于选择一个合作方、商店、语言区域或其他输出。
不传入 --target 运行该 Feed 时,会惰性消费 targets() 并生成全部目标:
php artisan feed:generate products
重复传入 --target 选项可仅生成所选目标:
php artisan feed:generate products --target=42
php artisan feed:generate products --target=42 --target=81
显式键使用 findTarget(),不会枚举 targets()。重复键只处理一次,并保留第一次出现的顺序。生成开始前会先解析全部请求键。
使用 --target 时必须提供一个 Feed 注册 slug。空键、未知键,以及对未实现 HasFeedTargets 的 Feed 选择目标都会被命令拒绝。
完整目标枚举采用流式处理,并非原子操作。如果 targets() 在生成若干值后失败,先前的目标可能已经生成或进入队列。空的可迭代对象不会生成任何内容,也不会创建隐式默认目标。
AI 代理输出
当 feed:generate 在 Laravel Agent Detector 识别到的 AI 编码代理中运行时,命令会自动输出单个 JSON 对象,而不是进度条和格式化状态行。不需要额外的命令选项。在未识别为代理的环境中,常规控制台输出保持不变。
直接生成时,每个已生成的 Feed 都会包含所有已发布文件及其记录数:
{
"tool": "feed:generate",
"result": "success",
"feeds": [
{
"class": "App\\Feeds\\SitemapFeed",
"status": "generated",
"files": [
{
"path": "/var/www/html/storage/app/public/sitemap.xml",
"records": 1250
}
]
},
{
"class": "App\\Feeds\\DisabledFeed",
"status": "skipped"
}
]
}
命令实际会在一行中输出紧凑的 JSON。上面的示例仅为便于阅读而进行了格式化。
| 状态 | 含义 | 附加字段 |
|---|---|---|
generated | 直接生成了 Feed 文件。 | files,其中包含每个文件的 path 和 records |
queued | 已启用队列模式,并为代理同步执行了 Feed 任务。 | 无 |
skipped | Feed 未启用,并且命令运行时未传入 Feed slug。 | 无 |
每个目标 Feed 的 generated 或 queued 条目还包含 target 字段,其值为所选目标键。
在队列模式下,代理专用执行路径会先同步运行每个已启用的任务,再返回 JSON 结果。面向人工阅读的常规执行路径仍会通过配置的队列连接分派任务。
此 JSON 封装仅用于成功执行。如果生成过程抛出异常,Laravel 会照常处理命令错误,并且不会输出 JSON 错误封装。
队列
默认情况下,Feed 生成任务在控制台进程中运行。对于耗时较长或占用大量内存的 Feed,请在环境中启用 Laravel Queue 模式:
FEED_QUEUE_ENABLED=true
FEED_QUEUE_CONNECTION=redis
FEED_QUEUE_NAME=feeds
FEED_QUEUE_UNIQUE_TTL=3600
启用队列模式后,feed:generate 会为每个已启用的普通 Feed 分派一个任务,并为目标 Feed 的每个所选目标分派一个任务。使用异步连接时,任务分派完成后命令便会返回。请为所选连接和队列启动队列工作进程来处理这些任务。
FEED_QUEUE_CONNECTION选择队列连接。未设置时依次回退到QUEUE_CONNECTION和database。FEED_QUEUE_NAME选择该连接上的队列。留空时使用连接的默认队列。FEED_QUEUE_UNIQUE_TTL设置唯一性锁的最长有效时间,单位为秒。普通任务按 Feed 类保持唯一;目标任务按 Feed 类和目标键保持唯一,目标参数不会改变该标识。
sync 连接会在控制台进程中立即执行每个任务。选择异步连接可将生成任务交给工作进程。设置 FEED_QUEUE_ENABLED=false 可直接生成 Feed,而不分派任务。
调度
注册表达式
创建 Feed 注册记录时,可以直接传入原始 cron 表达式字符串,也可以传入以链式方式构建的 DragonCode\LaravelFeed\Scheduling\Expression。
use App\Feeds\ProductFeed;
use DragonCode\LaravelFeed\Queries\FeedQuery;
use DragonCode\LaravelFeed\Scheduling\Expression;
app(FeedQuery::class)->create(
class: ProductFeed::class,
title: 'Products',
expression: (new Expression)
->weekly()
->mondays()
->at('13:00'),
);
链式调用示例会保存 0 13 * * 1。仍然支持原始字符串,包括 dragonmantank/cron-expression 支持的 @daily 等别名。
可用的链式方法取决于已安装 Laravel 版本提供的调度频率选项。当前列表请参阅 Laravel 13 频率参考。只有结果能保存为稳定五字段 cron 表达式的方法才会公开。此值对象不支持少于一分钟的间隔、时区、时间窗口约束以及 lastDayOfMonth()。
自动调度
要自动生成 Feed,请使用任务调度。在 routes/console.php 文件中调用辅助类即可;除非已更改配置,否则这是默认路径:
use DragonCode\LaravelFeed\Helpers\ScheduleFeedHelper;
use Illuminate\Support\Facades\Schedule;
ScheduleFeedHelper::register();
Schedule::call(function () {
// ... other action
})->everySecond();
这会根据数据库 expression 列中的计划注册所有已启用的 Feed。已调度的目标 Feed 会生成 targets() 返回的每个值。
手动调度
也可以按自定义规则直接指定计划。此时只会运行指定的 Feed。
use DragonCode\LaravelFeed\Commands\FeedGenerateCommand;
use Illuminate\Support\Facades\Schedule;
Schedule::command(FeedGenerateCommand::class, ['products'])
->withoutOverlapping()
->runInBackground()
->daily();
Schedule::command(FeedGenerateCommand::class, ['sitemap'])
->withoutOverlapping()
->runInBackground()
->hourly();
Schedule::call(function () {
// ... other action
})->everySecond();