
# 条件分支

工作流可以根据前一个步骤的输出跳转到指定名称的步骤。方法是在步骤的返回值中返回特殊的 `_next_step` 键。

如果你要根据工作流状态跳回较早的步骤，请参阅[重复](https://queuety.inline0.dev/zh/docs/workflows/repeats)。这样可以在工作流定义中明确表示回边，而不是将它隐藏在步骤类中。

## 命名步骤

使用 `->then()` 的第二个参数为步骤命名：

```php
use Queuety\Queuety;

Queuety::workflow( 'process_order' )
    ->then( ValidateOrderHandler::class, 'validate' )
    ->then( ChargePaymentHandler::class, 'charge' )
    ->then( FulfillOrderHandler::class, 'fulfill' )
    ->then( SendConfirmationHandler::class, 'confirm' )
    ->then( HandleFailureHandler::class, 'failure' )
    ->dispatch( [ 'order_id' => 123 ] );
```

如果未显式指定名称，步骤将按索引命名（`'0'`、`'1'`、`'2'` 等）。

## `_next_step` 键

步骤可以返回 `_next_step` 以跳转到指定名称的步骤，并跳过中间的所有步骤。跳转目标之后的步骤仍会按顺序运行：如果没有跳转，工作流只会继续执行列表中的下一步，因此在上面的示例中，`confirm` 步骤成功完成后会继续执行 `failure`，除非它返回 `_next_step` 跳过该步骤，或者 `HandleFailureHandler` 先检查 `error` 键：

```php
use Queuety\Step;

class ValidateOrderHandler implements Step {
    public function handle( array $state ): array {
        $order = wc_get_order( $state['order_id'] );

        if ( ! $order || $order->get_status() === 'cancelled' ) {
            return [
                'error'  => 'Order is invalid or cancelled',
                '_next_step'  => 'failure',
            ];
        }

        return [
            'order_total' => $order->get_total(),
            'customer_id' => $order->get_customer_id(),
        ];
    }

    public function config(): array {
        return [];
    }
}
```

当 `ValidateOrderHandler` 返回 `_next_step => 'failure'` 时，工作流会跳过 `charge`、`fulfill` 和 `confirm`，直接跳转到 `failure` 步骤。`_next_step` 键由工作流引擎使用，不会持久化到状态中。

## 分支模式

### 按条件跳过

```php
class CheckInventoryHandler implements Step {
    public function handle( array $state ): array {
        $in_stock = check_inventory( $state['sku'] );

        if ( ! $in_stock ) {
            return [
                'reason' => 'Out of stock',
                '_next_step'  => 'notify_backorder',
            ];
        }

        return [ 'inventory_reserved' => true ];
    }

    public function config(): array {
        return [];
    }
}
```

### 提前完成

跳转到最后一步，跳过不必要的处理：

```php
class CheckCacheHandler implements Step {
    public function handle( array $state ): array {
        $cached = get_transient( "report_{$state['user_id']}" );

        if ( $cached ) {
            return [
                'report_url' => $cached,
                '_next_step'      => 'done',
            ];
        }

        return [ 'cache_miss' => true ];
    }

    public function config(): array {
        return [];
    }
}
```

## 完整示例

```php
Queuety::workflow( 'content_pipeline' )
    ->then( CheckCacheHandler::class, 'check_cache' )
    ->then( FetchDataHandler::class, 'fetch' )
    ->then( CallLLMHandler::class, 'generate' )
    ->then( SaveResultHandler::class, 'save' )
    ->then( ReturnCachedHandler::class, 'done' )
    ->dispatch( [ 'user_id' => 42 ] );
```

如果缓存检查命中，工作流会从 `check_cache` 直接跳到 `done`，跳过 `fetch`、`generate` 和 `save`。如果未命中，则按顺序执行各步骤，并且 `save` 也会继续进入 `done`，因此 `ReturnCachedHandler` 必须同时处理这两种路径。
