本章节详细介绍 FastD Container 的安装配置、快速入门和最佳实践。
- 最低要求: PHP 8.2 或更高版本
- 推荐版本: PHP 8.3+
FastD Container 本身不依赖额外的PHP扩展,但某些使用场景可能需要:
json- JSON配置文件解析pdo- 数据库相关服务redis- Redis缓存服务
composer require fastd/container- 下载源码到项目目录
- 在项目中配置自动加载:
{
"autoload": {
"psr-4": {
"FastD\\Container\\": "path/to/container/src/"
}
}
}- 运行
composer dump-autoload
<?php
require_once 'vendor/autoload.php';
use FastD\Container\Container;
// 1. 创建容器实例
$container = new Container();
// 2. 注册服务
$container->add('logger', Monolog\Logger::class);
$container->add('config', [
'app_name' => 'My Application',
'debug' => true
]);
// 3. 获取服务实例
$logger = $container->got('logger');
$config = $container->got('config');
echo $config['app_name']; // 输出: My Application<?php
use FastD\Container\Container;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class Application
{
private Container $container;
public function __construct()
{
$this->container = new Container();
$this->registerServices();
}
private function registerServices(): void
{
// 配置服务
$this->container->add('config', [
'database' => [
'host' => $_ENV['DB_HOST'] ?? 'localhost',
'name' => $_ENV['DB_NAME'] ?? 'myapp'
]
]);
// 数据库服务
$this->container->add('database', function($container) {
$config = $container->got('config')['database'];
return new PDO(
"mysql:host={$config['host']};dbname={$config['name']}",
$_ENV['DB_USER'],
$_ENV['DB_PASS']
);
});
// 路由服务
$this->container->add('router', function($container) {
return new Router($container->got('logger'));
});
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$route = $this->container->got('router')->match($request);
$handler = $this->container->got($route->getHandler());
return $handler->handle($request);
}
}use FastD\Container\Container;
$container = new Container();
// 简单配置
$container->add('app.config', [
'name' => 'My App',
'version' => '1.0.0',
'debug' => true
]);
// 环境相关配置
$container->add('env.config', [
'development' => [
'log_level' => 'debug',
'cache_driver' => 'file'
],
'production' => [
'log_level' => 'error',
'cache_driver' => 'redis'
]
]);
// 动态配置
$container->add('dynamic.config', function() {
return [
'timestamp' => time(),
'memory_usage' => memory_get_usage(),
'loaded_extensions' => get_loaded_extensions()
];
});class ConfigLoader
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function loadFromFile(string $filePath): void
{
if (!file_exists($filePath)) {
throw new RuntimeException("Config file not found: {$filePath}");
}
$config = require $filePath;
$this->container->add('app.config', $config);
}
public function loadFromDirectory(string $directory): void
{
$files = glob($directory . '/*.php');
$config = [];
foreach ($files as $file) {
$key = basename($file, '.php');
$config[$key] = require $file;
}
$this->container->add('app.config', $config);
}
}
// 使用示例
$loader = new ConfigLoader($container);
$loader->loadFromDirectory(__DIR__ . '/config');// 注册具体的类
$container->add('user.repository', UserRepository::class);
// 注册闭包
$container->add('mailer', function() {
return new Mailer($_ENV['SMTP_HOST']);
});
// 注册预创建的对象
$cache = new RedisCache();
$container->add('cache', $cache);class ServiceRegistrar
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function registerMultiple(array $services): void
{
foreach ($services as $id => $service) {
$this->container->add($id, $service);
}
}
}
// 使用示例
$registrar = new ServiceRegistrar($container);
$registrar->registerMultiple([
'logger' => Monolog\Logger::class,
'cache' => RedisCache::class,
'database' => DatabaseConnection::class
]);class UserService
{
private UserRepository $repository;
private Logger $logger;
public function __construct(UserRepository $repository, Logger $logger)
{
$this->repository = $repository;
$this->logger = $logger;
}
public function getUser(int $id): ?User
{
$this->logger->info("Fetching user {$id}");
return $this->repository->findById($id);
}
}
// 容器配置
$container->add('user.repository', UserRepository::class);
$container->add('logger', Monolog\Logger::class);
$container->add('user.service', function($container) {
return new UserService(
$container->got('user.repository'),
$container->got('logger')
);
});
// 使用服务
$userService = $container->got('user.service');
$user = $userService->getUser(123);class OrderService
{
private ?PaymentGateway $paymentGateway = null;
private ?EmailService $emailService = null;
public function setPaymentGateway(PaymentGateway $gateway): void
{
$this->paymentGateway = $gateway;
}
public function setEmailService(EmailService $email): void
{
$this->emailService = $email;
}
public function processOrder(Order $order): bool
{
// 处理订单逻辑
return true;
}
}
// 容器配置
$container->add('payment.gateway', StripeGateway::class);
$container->add('email.service', SendGridService::class);
$container->add('order.service', function($container) {
$service = new OrderService();
$service->setPaymentGateway($container->got('payment.gateway'));
$service->setEmailService($container->got('email.service'));
return $service;
});class ServiceFactory
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function createDatabaseConnection(): PDO
{
$config = $this->container->got('database.config');
return new PDO(
"mysql:host={$config['host']};dbname={$config['name']}",
$config['username'],
$config['password']
);
}
public function createUserRepository(): UserRepository
{
return new UserRepository(
$this->createDatabaseConnection(),
$this->container->got('logger')
);
}
}
// 容器配置
$container->add('service.factory', function($container) {
return new ServiceFactory($container);
});
$container->add('user.repository', function($container) {
return $container->got('service.factory')->createUserRepository();
});interface CacheInterface
{
public function get(string $key);
public function set(string $key, $value, int $ttl = 3600);
}
class RedisCache implements CacheInterface
{
public function get(string $key) { /* ... */ }
public function set(string $key, $value, int $ttl = 3600) { /* ... */ }
}
class CacheDecorator implements CacheInterface
{
private CacheInterface $cache;
private Logger $logger;
public function __construct(CacheInterface $cache, Logger $logger)
{
$this->cache = $cache;
$this->logger = $logger;
}
public function get(string $key)
{
$this->logger->info("Cache GET: {$key}");
return $this->cache->get($key);
}
public function set(string $key, $value, int $ttl = 3600)
{
$this->logger->info("Cache SET: {$key}");
return $this->cache->set($key, $value, $ttl);
}
}
// 容器配置
$container->add('cache.real', RedisCache::class);
$container->add('logger', Monolog\Logger::class);
$container->add('cache', function($container) {
return new CacheDecorator(
$container->got('cache.real'),
$container->got('logger')
);
});class ConditionalServiceRegistrar
{
private Container $container;
private array $environment;
public function __construct(Container $container, array $environment = [])
{
$this->container = $container;
$this->environment = $environment;
}
public function registerServices(): void
{
// 根据环境注册不同的服务
if ($this->environment['APP_ENV'] === 'production') {
$this->container->add('cache.driver', RedisCache::class);
$this->container->add('logger.handler', SyslogHandler::class);
} else {
$this->container->add('cache.driver', ArrayCache::class);
$this->container->add('logger.handler', StreamHandler::class);
}
// 根据功能开关注册服务
if ($this->environment['FEATURE_EMAIL'] ?? false) {
$this->container->add('email.service', SendGridService::class);
}
// 根据配置注册服务
$dbEnabled = $this->environment['DATABASE_ENABLED'] ?? true;
if ($dbEnabled) {
$this->container->add('database', DatabaseConnection::class);
}
}
}
// 使用示例
$registrar = new ConditionalServiceRegistrar($container, $_ENV);
$registrar->registerServices();use PHPUnit\Framework\TestCase;
use FastD\Container\Container;
class ServiceTestCase extends TestCase
{
protected Container $container;
protected function setUp(): void
{
$this->container = new Container();
$this->setUpContainer();
}
protected function setUpContainer(): void
{
// 注册测试专用的服务
$this->container->add('logger', TestLogger::class);
$this->container->add('database', TestDatabase::class);
$this->container->add('config', [
'test_mode' => true,
'fixtures_path' => __DIR__ . '/fixtures'
]);
}
protected function getService(string $id)
{
return $this->container->got($id);
}
}
class UserServiceTest extends ServiceTestCase
{
public function testCreateUser()
{
$userService = $this->getService('user.service');
$user = $userService->create([
'name' => 'John Doe',
'email' => 'john@example.com'
]);
$this->assertInstanceOf(User::class, $user);
$this->assertEquals('John Doe', $user->getName());
}
}use PHPUnit\Framework\MockObject\MockBuilder;
class MockServiceHelper
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function mockService(string $id, $mock): void
{
$this->container->add($id, $mock);
}
public function mockDatabaseResults(array $results): void
{
$mockDb = $this->createMock(DatabaseInterface::class);
$mockDb->expects($this->any())
->method('query')
->willReturn($results);
$this->mockService('database', $mockDb);
}
public function mockHttpClient(array $responses): void
{
$mockClient = $this->createMock(HttpClientInterface::class);
$mockClient->expects($this->any())
->method('request')
->willReturnCallback(function($method, $url) use ($responses) {
return $responses[$url] ?? null;
});
$this->mockService('http.client', $mockClient);
}
}class ServicePreloader
{
private Container $container;
private array $preloadList;
public function __construct(Container $container, array $preloadList = [])
{
$this->container = $container;
$this->preloadList = $preloadList;
}
public function preload(): void
{
foreach ($this->preloadList as $serviceId) {
if ($this->container->has($serviceId)) {
$this->container->got($serviceId);
}
}
}
}
// 使用示例
$preloader = new ServicePreloader($container, [
'database.connection',
'logger',
'cache.driver'
]);
$preloader->preload(); // 预加载关键服务class ContainerCache
{
private string $cacheFile;
public function __construct(string $cacheFile = '/tmp/container_cache.php')
{
$this->cacheFile = $cacheFile;
}
public function save(Container $container): void
{
$services = [];
foreach ($container as $id => $definition) {
// 只缓存可序列化的服务定义
if ($this->isSerializable($definition)) {
$services[$id] = $definition;
}
}
file_put_contents($this->cacheFile, '<?php return ' . var_export($services, true) . ';');
}
public function load(Container $container): bool
{
if (!file_exists($this->cacheFile)) {
return false;
}
$cachedServices = require $this->cacheFile;
foreach ($cachedServices as $id => $definition) {
$container->add($id, $definition['service']);
}
return true;
}
private function isSerializable(array $definition): bool
{
return !in_array($definition['type'], ['closure', 'object']);
}
}class ProductionContainerSetup
{
public static function configure(Container $container): void
{
// 启用服务缓存
$container->add('cache.enabled', true);
// 设置生产环境配置
$container->add('app.env', 'production');
// 注册生产专用服务
$container->add('error.handler', ProductionErrorHandler::class);
$container->add('logger', function() {
return new Monolog\Logger('app', [
new Monolog\Handler\SyslogHandler('app')
]);
});
// 禁用调试服务
$container->add('debug.mode', false);
}
}class DevelopmentContainerSetup
{
public static function configure(Container $container): void
{
// 启用调试服务
$container->add('debug.mode', true);
$container->add('debug.bar', DebugBar::class);
// 注册开发专用服务
$container->add('logger', function() {
return new Monolog\Logger('app', [
new Monolog\Handler\StreamHandler('php://stderr')
]);
});
// 启用详细错误报告
$container->add('error.handler', DevelopmentErrorHandler::class);
}
}这些配置和使用模式可以帮助您更好地在项目中集成和使用FastD Container。