Request services via contracts. The container resolves dependencies automatically — you declare, we inject.
List the services your module needs in the "services" array of module.json. Available services include: settings, logger, cache, http, events, and scheduler.
{
"slug": "analytics",
"services": ["settings", "logger", "cache", "http"]
}The container matches service names to their contract interfaces and injects them into your constructor. Type-hint the interface — the container resolves the implementation.
<?php
use Meteorack\SDK\Contracts\CacheInterface;
use Meteorack\SDK\Contracts\HttpInterface;
class Analytics_Module implements ModuleInterface {
public function __construct(
private readonly CacheInterface $cache,
private readonly HttpInterface $http,
) {}
public function boot(): void {
add_action('wp_footer', [$this, 'track']);
}
public function track(): void {
$key = 'pageview:' . get_the_ID();
// Cache prevents duplicate tracking
if ($this->cache->has($key)) {
return;
}
$this->http->post('/api/track', [
'page_id' => get_the_ID(),
'timestamp' => time(),
]);
$this->cache->set($key, true, 300);
}
}Every service has a corresponding contract interface in the SDK. Your module depends on the interface, never on the concrete implementation. This makes testing trivial — mock the interface, test your logic.