Skip to content

Advanced Action Patterns

When to Use

Use advanced action patterns when integrating with external APIs, processing complex data structures with YAML configuration, validating external service responses, or implementing sophisticated error handling.

Decision

If you need... Pattern Why
API integration with config Service injection + YAML config Flexible configuration without hardcoding
Dynamic form options External service in buildConfigurationForm() Real-time option lists from APIs
Multiple related actions Plugin deriver Single class generates multiple plugin variants
Structured error responses Token data with success/error fields Downstream conditions can check results

Pattern

#[Action(
  id: 'my_module_api_call',
  label: new TranslatableMarkup('My Module: API Call'),
)]
#[EcaAction(version_introduced: '1.0.0')]
class ApiCallAction extends ConfigurableActionBase {

  protected HttpClientInterface $httpClient;
  protected YamlParser $yamlParser;

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->httpClient = $container->get('http_client');
    $instance->yamlParser = $container->get('eca.service.yaml_parser');
    return $instance;
  }

  public function execute(): void {
    try {
      $endpoint = $this->tokenService->getOrReplace($this->configuration['endpoint']);
      $api_config = $this->yamlParser->parse($this->configuration['api_config']) ?? [];

      $response = $this->httpClient->request('GET', $endpoint, $api_config);
      $data = json_decode($response->getBody()->getContents(), TRUE);

      $this->tokenService->addTokenData($this->configuration['result_token'], [
        'success' => 1,
        'data' => $data,
        'status_code' => $response->getStatusCode(),
      ]);
    }
    catch (\Exception $e) {
      $this->tokenService->addTokenData($this->configuration['result_token'], [
        'success' => 0,
        'error' => $e->getMessage(),
      ]);
      $this->logger->error('API call failed: @error', ['@error' => $e->getMessage()]);
    }
  }
}

Common Mistakes

  • Not handling API failures → Workflow crashes instead of graceful degradation (always use try-catch)
  • Hardcoding API configuration → Can't adapt to different environments (use YAML config fields)
  • Missing structured error responses → Conditions can't check if action succeeded
  • Not logging errors → Debugging becomes impossible (use $this->logger)
  • Injecting parent's services in child → Duplicates dependencies (parent already has them)

See Also

References: - Contrib example: Check ECA AI module for AI service integration patterns - Core: /modules/contrib/eca/src/Service/YamlParser.php