33%
翻译进度
3
分块数量
1
参与人数

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 or doctrine.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 项目 的更多信息。

郁雁 翻译于 3 年前

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~