Skip to content

Provider Plugin Pattern

When to Use

Use Provider Plugin when creating new service abstraction across diverse external providers. Use Foundation+Extension when mature plugin ecosystem exists. Use Service Collector when building REST API-first integrations.

Decision

Situation Choose Why
No existing plugin ecosystem for service category Provider Plugin Create standardized abstraction from scratch
Need service abstraction across providers Provider Plugin Consistent interfaces for diverse implementations
Want cross-cutting infrastructure Provider Plugin Proxy, events, caching, monitoring in main module
Provider-agnostic consumers Provider Plugin Consumers work with any implementation
External API integrations Provider Plugin Standardize different external service interfaces
User choice between providers Provider Plugin Configuration-driven provider selection
REST API-first external integration Service Collector Built-in REST endpoints, minimal overhead

Pattern

Main Module creates provider abstraction:

# Provider pattern service definition
services:
  my_module.service_provider:
    class: Drupal\my_module\ServiceProviderPluginManager
    parent: default_plugin_manager
    arguments: ['@service_container']

Provider Module implements specific service:

// Consumer code works with any provider
$result = $this->myModuleService->executeOperation('text_generation', [
  'prompt' => 'Write a summary',
  'max_tokens' => 100
]);

// Different providers handle same operation differently:
// OpenAI Provider: Uses GPT-4 API
// Anthropic Provider: Uses Claude API
// Local Provider: Uses local LLM

Critical Pattern Elements: 1. Standardized Provider Interface - All providers implement same contract 2. Service Proxy - Wraps provider execution with events, logging, retry 3. DTOs for Data Exchange - Input/Output objects abstract data structures 4. Capability-Based Discovery - getProvidersByCapability() method 5. Default Provider Configuration - Per-operation-type defaults

Common Mistakes

  • Wrong: Creating provider plugin when Foundation+Extension exists → Right: Extend mature ecosystem (e.g., Commerce Payment)
  • Wrong: No service proxy layer → Right: Implement proxy for events, error handling, retry logic
  • Wrong: Direct provider implementation in consumers → Right: Consumers use provider-agnostic service interface
  • Wrong: Provider-specific DTOs → Right: Standardized Input/Output objects across all providers

See Also