Plugin vs Observer Overview
Plugins (Interceptors)
// Plugin on a public method
class ProductPlugin
{
public function beforeSave($subject, $product)
{
// Before method execution
$this->logger->log('Product saving: ' . $product->getSku());
return [$product]; // Modified arguments
}
public function afterSave($subject, $result)
{
// After method execution
$this->cache->invalidate('product_' . $product->getId());
return $result; // Can modify return value
}
public function aroundSave($subject, $callable)
{
// Around method - controls execution
$this->logger->log('Starting save');
$result = $callable(); // Execute original
$this->logger->log('Save completed');
return $result;
}
}
// di.xml declaration
<config>
<type name="Magento\Catalog\Model\Product">
<plugin name="product_plugin" type="Vendor\Module\Plugin\ProductPlugin"/>
</type>
</config>
Observers
// Observer for event
class ProductSaveObserver
{
public function execute(EventObserver $observer)
{
$product = $observer->getEvent()->getProduct();
$this->logger->log('Product saved: ' . $product->getSku());
$this->cache->invalidate('product_' . $product->getId());
}
}
// Event dispatch
$eventManager->dispatch('catalog_product_save_after', ['product' => $product]);
// events.xml declaration
<config>
<event name="catalog_product_save_after">
<observer name="product_save_observer" instance="Vendor\Module\Observer\ProductSaveObserver"/>
</event>
</config>
When to Use Each
Use Plugins When:
// 1. Need to modify method arguments
public function beforeSave($subject, $product)
{
// Modify product before save
$product->setData('custom_field', 'modified');
return [$product];
}
// 2. Need to modify return value
public function afterSave($subject, $result)
{
// Modify result after save
$result->setCustomAttribute('processed');
return $result;
}
// 3. Need to control execution
public function aroundSave($subject, $callable)
{
// Skip execution based on condition
if ($this->shouldSkip()) {
return null;
}
return $callable();
}
// 4. Need specific method interception
// Plugin targets specific method: save()
Use Observers When:
// 1. React to events without modifying behavior
public function execute(EventObserver $observer)
{
$product = $observer->getEvent()->getProduct();
// Log, notify, sync - no modification needed
}
// 2. Multiple listeners for same event
// Observer A: Send email notification
// Observer B: Update search index
// Observer C: Sync to external system
// 3. Custom events
$eventManager->dispatch('my_custom_event', ['data' => $data]);
// 4. Decoupled architecture
// Observer doesn't know about other observers
// Easy to add/remove listeners
Performance Comparison
Execution Overhead
// Plugin overhead
// 1. Method lookup
// 2. Plugin chain execution
// 3. Argument/return modification
// ~0.1ms per plugin
// Observer overhead
// 1. Event dispatch
// 2. Observer instantiation
// 3. Method execution
// ~0.2ms per observer
// Benchmark: Product save with 5 extensions
// Plugins: 5.2ms total
// Observers: 6.8ms total
// Direct call: 3.1ms
Memory Usage
// Plugins: Lazy-loaded, per-request
// Each plugin instance created on demand
// Memory: ~1KB per plugin
// Observers: Event manager maintains list
// All observers instantiated per event
// Memory: ~2KB per observer
// High-traffic scenario (1000 req/sec)
// Plugins: 1KB × 5 plugins × 1000 = 5MB
// Observers: 2KB × 5 observers × 1000 = 10MB
Caching Impact
// Plugins: Can affect cache key generation
// Plugin modifies product → cache invalidated
// Observers: Post-cache operations
// Observer runs after cache read/write
// Less impact on cache performance
// Recommendation:
// - Cache-affecting logic: Use plugins
// - Post-cache operations: Use observers
Maintenance Considerations
Plugin Maintenance
// Plugin dependencies
<type name="Magento\Catalog\Model\Product">
<plugin name="plugin_a" type="Vendor\A\Plugin\ProductPlugin"/>
<plugin name="plugin_b" type="Vendor\B\Plugin\ProductPlugin"/>
</type>
// Execution order matters
// plugin_a → plugin_b → original method
// Breaking changes risk
// If Product::save() signature changes
// All plugins need update
// Testing complexity
// Each plugin needs isolation testing
// Plugin chain interaction testing
Observer Maintenance
// Observer independence
<event name="catalog_product_save_after">
<observer name="observer_a" instance="Vendor\A\Observer\ProductObserver"/>
<observer name="observer_b" instance="Vendor\B\Observer\ProductObserver"/>
</event>
// Observers don't depend on each other
// Easy to add/remove observers
// No execution order dependency
// Testing simplicity
// Each observer tested independently
// No interaction testing needed
Decision Matrix
| Factor | Plugins | Observers |
|---|---|---|
| Modify arguments | Yes | No |
| Modify return | Yes | No |
| Control execution | Yes (around) | No |
| Multiple listeners | Limited | Yes |
| Execution order | Critical | Flexible |
| Testing complexity | High | Low |
| Performance | Slightly better | Slightly worse |
Practice Problems
Design an extension strategy for adding custom validation, logging, and email notifications on product save.
Solution
// Strategy:
// 1. Validation: Plugin (beforeSave)
// - Modify/validate arguments
// - Reject invalid data
// 2. Logging: Observer (catalog_product_save_after)
// - Decoupled, multiple listeners
// - No modification needed
// 3. Email: Observer (catalog_product_save_after)
// - Independent operation
// - Can add/remove without affecting others Quiz
1. When should you use a plugin instead of an observer?
2. What is the main advantage of observers over plugins?
3. How does plugin execution order work?
4. Which has lower memory overhead in high-traffic scenarios?
Flashcards
Question
Plugin types?
Click to reveal answer
Answer
before (modify args), after (modify return), around (control execution)
Question
Observer use case?
Click to reveal answer
Answer
React to events without modifying behavior, multiple listeners
Question
Plugin execution order?
Click to reveal answer
Answer
before → original → after (around wraps all)
Question
Plugin vs Observer performance?
Click to reveal answer
Answer
Plugins slightly faster, observers slightly more memory
Question
When to use observers?
Click to reveal answer
Answer
Logging, notifications, index updates, decoupled operations
Revision Notes
Key Takeaways
- 1. Plugins: Modify arguments/return, control execution, order matters
- 2. Observers: React to events, multiple listeners, decoupled
- 3. Plugins: Better for cache-affecting logic
- 4. Observers: Better for post-cache operations
- 5. Choose based on: modification need, coupling, testing complexity
Interview Tips
- • Explain plugin types (before/after/around)
- • Compare plugin vs observer use cases
- • Discuss execution order and priority
- • Know when to use each approach
Cheat Sheet
Plugin vs Observer
- Plugin: Modify args/return, control execution
- Observer: React to events, multiple listeners
- Plugin: before→after→around
- Observer: No execution order dependency
- Plugin: Cache-affecting logic
- Observer: Logging, notifications, sync
- Plugin: Tighter coupling, more complex testing