Dependency Injection Container eli DI-container tekee WordPress-pluginista huomattavasti modulaarisemman, testattavamman ja helpommin ylläpidettävän. Vaikka WordPress perustuu pitkälti globaaleihin funktioihin ja hookeihin, moderni plugin-kehitys hyötyy selkeästä service-rakenteesta ja dependency injection -mallista.
Huono tapa:...
Container hallitsee servicejä:...
WordPressissä ongelmat usein johtuvat:...
Perusmalli:...
$container->set('mailer', function() { return new Mailer(); }); 3. Dependency resolution $container->set('order_service', function($c) { return new OrderService( $c->get('mailer') ); }); 4. Plugin bootstrap Tyypillinen rakenne:...
$container->set('order_service', function($c) { return new OrderService( $c->get('mailer') ); }); 4. Plugin bootstrap Tyypillinen rakenne:...
Tyypillinen rakenne:...
Huono:...
$container->set('user_hooks', function() { return new UserHooks(); }); Bootissa:...
Container voi luoda servicet vasta tarvittaessa....
Moni container tukee shared servicejä:...
Paras käytäntö:...
DI tekee mockauksen helpoksi:...
Modernit containerit tukevat reflection-pohjaista autowiringia....
Suosittu ratkaisu:...
Hyvä rakenne isoihin plugineihin:...
Älä käytä:...
DI-container toimii hyvin yhdessä event-driven mallin kanssa:...
Huonoja käytäntöjä:...
Liian raskas container voi hidastaa bootstrapia....
Moderni WordPress-plugin:...
Hyvä idea kun:...
Dependency injection container tuo WordPress-plugin-kehitykseen modernin sovellusarkkitehtuurin. Sen avulla pluginit voidaan rakentaa modulaarisesti, testattavasti ja ilman globaalia spagettia....
Ilman DI-containeria pluginit muuttuvat helposti:
- vaikeasti testattaviksi
- tiukasti kytketyiksi
- sekaviksi singleton-rakenteiksi
- hankaliksi laajentaa
Hyvin rakennettu container taas mahdollistaa:
- service registrationin
- automaattisen dependency resolutionin
- lazy loadingin
- paremman arkkitehtuurin
Mitä dependency injection tarkoittaa
Huono tapa:
class OrderService {
public function create() {
$mailer = new Mailer();
}
}
Ongelma:
- luokka luo omat riippuvuutensa
- vaikea testata
- vaikea vaihtaa implementaatiota
Parempi:
class OrderService {
public function __construct(Mailer $mailer) {
$this->mailer = $mailer;
}
}
Nyt riippuvuus injektoidaan ulkopuolelta.
Mikä DI-container tekee
Container hallitsee servicejä:
Container
├── Mailer
├── Logger
├── API Client
└── OrderService
Container:
- luo objektit
- ratkaisee riippuvuudet
- hallitsee lifecycleä
Miksi DI-container kannattaa WordPressissä
WordPressissä ongelmat usein johtuvat:
- globaalista tilasta
- singleton-spagetista
- hookien hajautumisesta
DI-container auttaa rakentamaan:
- modulaarisen pluginin
- service-pohjaisen arkkitehtuurin
- testattavan koodin
1. Yksinkertainen custom container
Perusmalli:
class Container {
protected $services = [];
public function set($key, $resolver) {
$this->services[$key] = $resolver;
}
public function get($key) {
return $this->services[$key]($this);
}
}
2. Service registration
$container->set('mailer', function() {
return new Mailer();
});
3. Dependency resolution
$container->set('order_service', function($c) {
return new OrderService(
$c->get('mailer')
);
});
4. Plugin bootstrap
Tyypillinen rakenne:
plugin.php
src/
services/
container/
Bootstrap:
$container = new Container();
require 'services.php';
$app = $container->get('app');
$app->boot();
5. Hook registration serviceinä
Huono:
add_action(...);
add_action(...);
add_action(...);
ripoteltuna kaikkialle.
Parempi:
class UserHooks {
public function register() {
add_action('init', [$this, 'boot']);
}
}
6. Hook service containerissa
$container->set('user_hooks', function() {
return new UserHooks();
});
Bootissa:
$container->get('user_hooks')->register();
7. Lazy loading
Container voi luoda servicet vasta tarvittaessa.
Hyöty:
- pienempi memory footprint
- nopeampi bootstrap
8. Singleton vs shared services
Moni container tukee shared servicejä:
$container->singleton('logger', function() {
return new Logger();
});
Tällöin sama instanssi palautetaan aina.
9. Interface-pohjainen arkkitehtuuri
Paras käytäntö:
interface MailerInterface {}
Implementaatio:
class SMTPMailer implements MailerInterface {}
Container:
$container->set(
MailerInterface::class,
fn() => new SMTPMailer()
);
10. Testattavuus
DI tekee mockauksen helpoksi:
$mailer = $this->createMock(MailerInterface::class);
Ilman dependency injectionia tämä on vaikeaa.
11. Autowiring
Modernit containerit tukevat reflection-pohjaista autowiringia.
Esimerkkejä:
- PHP-DI
- Symfony Container
- Laravel Container
$container->get(OrderService::class);
Container ratkaisee dependencyt automaattisesti.
12. WordPress + PHP-DI
Suosittu ratkaisu:
composer require php-di/php-di
Käyttö:
$container = new \DI\Container();
13. Service provider -malli
Hyvä rakenne isoihin plugineihin:
AuthServiceProvider
APIServiceProvider
AdminServiceProvider
Jokainen rekisteröi omat servicensä.
14. Configuration injection
Älä käytä:
get_option() kaikkialla
Parempi:
new APIClient($config);
15. Event-driven plugin architecture
DI-container toimii hyvin yhdessä event-driven mallin kanssa:
Event Dispatcher
↓
Subscribers
↓
Services
16. Anti-patternit
Huonoja käytäntöjä:
- globaali
$containerkaikkialla - service locator abuse
- liian monimutkainen container pienessä pluginissa
- singleton-spagetti
- WordPress-funktiot business logicassa
17. Performance huomioitavaa
Liian raskas container voi hidastaa bootstrapia.
Optimoi:
- lazy loading
- cached definitions
- ei reflectionia productionissa tarvittaessa
18. Paras plugin-rakenne
Moderni WordPress-plugin:
src/
├── Application
├── Services
├── Infrastructure
├── Hooks
├── API
├── Domain
└── Container
19. Milloin DI-container kannattaa
Hyvä idea kun:
- plugin kasvaa suureksi
- useita servicejä
- paljon integraatioita
- testattavuus tärkeää
- useita kehittäjiä
Ei välttämättä tarpeen:
- pienissä utility plugineissa
Yhteenveto
Dependency injection container tuo WordPress-plugin-kehitykseen modernin sovellusarkkitehtuurin. Sen avulla pluginit voidaan rakentaa modulaarisesti, testattavasti ja ilman globaalia spagettia.
Kun servicet, hookit ja integraatiot erotetaan selkeiksi dependencyiksi, WordPress-pluginista tulee huomattavasti helpompi ylläpitää ja skaalata pitkällä aikavälillä.