5.2. Silex
这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。
PHP-DI in Silex
Installation
$ composer require php-di/silex-bridge
Usage
In order to benefit from PHP-DI's integration in Silex, you only need to use DI\Bridge\Silex\Application
instead of the original Silex\Application
.
Here is the classic Silex example updated:
<?php
require_once __DIR__.'/../vendor/autoload.php';
$app = new DI\Bridge\Silex\Application();
$app->get('/hello/{name}', function ($name) use ($app) {
return 'Hello '.$app->escape($name);
});
$app->run();
Benefits
Using PHP-DI in Silex allows you to use all the awesome features of PHP-DI to wire your dependencies (using the definition files, autowiring, annotations, …).
Another big benefit of the PHP-DI integration is the ability to use dependency injection inside controllers, middlewares and param converters:
class Mailer
{
// ...
}
$app->post('/register/{name}', function ($name, Mailer $mailer) {
$mailer->sendMail($name, 'Welcome!');
return 'You have received a new email';
});
// Injection works for middleware too
$app->before(function (Request $request, Mailer $mailer) {
// ...
});
// And param converters
$app->get('/users/{user}', function (User $user) {
return new JsonResponse($user);
})->convert('user', function ($user, UserManager $userManager) {
return $userManager->findById($user);
});
Dependency injection works using type-hinting:
- it can be mixed with request parameters (
$name
in the example above) - the order of parameters doesn't matter, they are resolved by type-hint (for dependency injection) and by name (for request parameters)
- it only works with objects that you can type-hint: you can't inject string/int values for example, and you can't inject container entries whose name is not a class/interface name (e.g.
twig
ordoctrine.entity_manager
)
Controllers as services
With Silex and Pimple, you can define controllers as services by installing the ServiceControllerServiceProvider
and using a specific notation.
With the PHP-DI bridge, you can natively define any type of callable based on services:
- object method:
class HelloController
{
public function helloAction($name)
{
// ...
}
}
$app->get('/{name}', [HelloController::class, 'helloAction']);
You will notice above that we give the class name and not an object: PHP-DI will instantiate the instance (and inject dependencies inside it) only if it is used.
class HelloController
{
public function __invoke($name)
{
// ...
}
}
$app->get('/{name}', HelloController::class);
Again you will notice that we pass the class name and not an instance. PHP-DI will correctly detect that this is an invokable class and will instantiate it.
Middlewares, route variable converters, error handlers and view handlers
The callable resolution described above (for "controllers as services") applies for registering other Silex objects:
For example you can define a middleware like so and let PHP-DI instantiate it:
class AuthMiddleware
{
public function beforeRoute(Request $request, Application $app)
{
// ...
}
}
$app->before([AuthMiddleware::class, 'beforeRoute']);
Configuring the container
You can configure PHP-DI's container by creating your own ContainerBuilder
and passing it to the application:
$containerBuilder = new DI\ContainerBuilder();
// E.g. setup a cache
$containerBuilder->setDefinitionCache(new ApcCache());
// Add definitions
$containerBuilder->addDefinitions([
// place your definitions here
]);
// Register a definition file
$containerBuilder->addDefinitions('config.php');
$app = new DI\Bridge\Silex\Application($containerBuilder);
Silex 服务提供商
Silex 提供了几个 “服务提供者” 来预配置一些第三方库,例如 Twig 或 Doctrine。 你仍然可以通过这种集成使用这些服务提供者(在较大的项目中你可能希望自己配置所有内容)。
下面是 Twig 服务提供者 的例子:
$app->register(new Silex\Provider\TwigServiceProvider(), [
'twig.path' => __DIR__ . '/views',
]);
$app->get('/', function () use ($app) {
return $app['twig']->render('home.twig');
});
由于 Twig 服务是使用自定义名称而不是实际类名注册的(例如,用twig
代替Twig_Environment
类名),你不能将此类依赖项注入到闭包中。 如果你想注入控制器闭包,你可以使用 PHP-DI 别名条目:
$builder = new ContainerBuilder();
$builder->addDefinitions([
'Twig_Environment' => \DI\get('twig'), // 别名
]);
// ...
// Twig 现在可以注入到闭包:
$app->post('/', function (Twig_Environment $twig) {
return $twig->render('home.twig');
});
更多
在 GitHub 上阅读有关 Silex-Bridge 项目 的更多信息。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。