php-di/silex-bridge

PHP-DI在Silex中的集成

2.0.0-beta1 2016-06-02 12:20 UTC

This package is auto-updated.

Last update: 2024-09-19 21:44:34 UTC


README

Build Status Coverage Status

安装

$ composer require php-di/silex-bridge

使用

为了从PHP-DI在Silex中的集成中受益,您只需使用DI\Bridge\Silex\Application而不是原始的Silex\Application

以下是一个更新的经典Silex示例

<?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();

优点

在Silex中使用PHP-DI允许您使用PHP-DI的所有优秀功能来绑定依赖项(使用定义文件、自动绑定、注解等)。

PHP-DI集成的另一个重大优点是能够在控制器、中间件和参数转换器内部使用依赖注入

class Mailer
{
    // ...
}

$app->post('/register/{name}', function ($name, Mailer $mailer) {
    $mailer->sendMail($name, 'Welcome!');

    return 'You have received a new email';
});

// You can also inject the whole request object like in a traditional Silex application
$app->post('/register/{name}', function (Request $request, Mailer $mailer) {
    // ...
});

// 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);
});

依赖注入使用类型提示

  • 它可以与请求参数(如上面的示例中的$name)混合使用
  • 参数的顺序不重要,它们通过类型提示(用于依赖注入)和名称(用于请求属性)来解决
  • 它仅适用于可以类型提示的对象:例如,您不能注入字符串/整数值,并且您不能注入容器条目,其名称不是类/接口名称(例如twigdoctrine.entity_manager

将控制器作为服务

使用Silex和Pimple,您可以通过安装ServiceControllerServiceProvider并使用特定语法来定义控制器作为服务

使用PHP-DI桥接器,您可以原生地基于服务定义任何类型的可调用对象

  • 对象方法
class HelloController
{
    public function helloAction($name)
    {
        // ...
    }
}

$app->get('/{name}', [HelloController::class, 'helloAction']);

您会注意到上面我们给出的是类名而不是对象:只有当它被使用时,PHP-DI才会实例化该实例(并在其中注入依赖项)。

class HelloController
{
    public function __invoke($name)
    {
        // ...
    }
}

$app->get('/{name}', HelloController::class);

同样,您会注意到我们传递的是类名而不是实例。PHP-DI会正确检测这是一个可调用的类并将其实例化。

中间件、路由变量转换器、错误处理程序和视图处理程序

上面描述的可调用对象解析(对于“将控制器作为服务”)也适用于注册其他Silex对象

例如,您可以定义如下中间件并让PHP-DI实例化它

class AuthMiddleware
{
    public function beforeRoute(Request $request, Application $app)
    {
        // ...
    }
}

$app->before([AuthMiddleware::class, 'beforeRoute']);

配置容器

您可以通过创建自己的ContainerBuilder并将其传递给应用程序来配置PHP-DI的容器

$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。您仍然可以使用这些服务提供程序与此集成(尽管在更大的项目中,您可能想自己配置一切)。

以下是一个TwigServiceProvider的示例

$app->register(new Silex\Provider\TwigServiceProvider(), [
    'twig.path' => __DIR__ . '/views',
]);

$app->get('/', function () use ($app) {
    return $app['twig']->render('home.twig');
});

由于使用自定义名称而不是实际类名(例如,使用twig而不是Twig_Environment类名)注册了Twig服务,因此您无法将这些依赖项注入到闭包中。如果要在控制器闭包中注入,则可以使用PHP-DI将条目别名化

$builder = new ContainerBuilder();

$builder->addDefinitions([
    'Twig_Environment' => \DI\get('twig'), // alias
]);

// ...

// Twig can now be injected in closures:
$app->post('/', function (Twig_Environment $twig) {
    return $twig->render('home.twig');
});