服务容器...4.1翻译中

4.2 版本
维护中的版本

你的程序 全部是 各有用途的对象: 一个 "Mailer" 对象可以帮助你发送邮件,而另一个对象可以帮你把数据入库。 你程序中的几乎 所有 事都是由这些对象中的某一个来完成的。每当你安装一个新bundle,你就拥有了更多的对象!

在Symfony中,这些有用的对象被称为 services(服务),每一个服务都被存放于一个特殊的名为 service container(服务容器)之中。如果你有服务容器,那么你可以使用服务的id来取出服务:

1
2
$logger = $container->get('logger');
$entityManager = $container->get('doctrine.orm.entity_manager');

The container allows you to centralize the way objects are constructed. It makes your life easier, promotes a strong architecture and is super fast!

取得并使用服务 

The moment you start a Symfony app, your container already contains many services. These are like tools: waiting for you to take advantage of them. In your controller, you can "ask" for a service from the container by type-hinting an argument with the service's class or interface name. Want to log something? No problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Controller/ProductController.php
// ...
 
use Psr\Log\LoggerInterface;
 
/**
 * @Route("/products")
 */
public function listAction(LoggerInterface $logger)
{
    $logger->info('Look! I just used a service');
 
    // ...
}

3.3 New in version 3.3: The ability to type-hint a service in order to receive it was added in Symfony 3.3. See the controller chapter for more details.

What other services are available? Find out by running:

1
 php bin/console debug:container

This is just a small sample of the output:

Service ID Class name
doctrine Doctrine\Bundle\DoctrineBundle\Registry
filesystem Symfony\Component\Filesystem\Filesystem
form.factory Symfony\Component\Form\FormFactory
logger Symfony\Bridge\Monolog\Logger
request_stack Symfony\Component\HttpFoundation\RequestStack
router Symfony\Bundle\FrameworkBundle\Routing\Router
security.authorization_checker Symfony\Component\Security\Core\Authorization\AuthorizationChecker
security.password_encoder Symfony\Component\Security\Core\Encoder\UserPasswordEncoder
session Symfony\Component\HttpFoundation\Session\Session
translator Symfony\Component\Translation\DataCollectorTranslator
twig Twig_Environment
validator Symfony\Component\Validator\Validator\ValidatorInterface

You can also use the unique "Service ID" to access a service directly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/AppBundle/Controller/ProductController.php
namespace AppBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 
class ProductController extends Controller
{
    /**
     * @Route("/products")
     */
    public function listAction()
    {
        $logger = $this->container->get('logger');
        $logger->info('Look! I just used a service');
 
        // ...
    }
}

Fetching a service directly from the container like this only works if you extend the Controller class.

Throughout the docs, you'll see how to use the many different services that live in the container.

Container: Lazy-loaded for speed

Wait! Are all the services (objects) instantiated on every request? No! The container is lazy: it doesn't instantiate a service until (and unless) you ask for it. For example, if you never use the validator service during a request, the container will never instantiate it.

在容器中创建/配置服务 

Tip

The recommended way of configuring services changed in Symfony 3.3. For a deep explanation, see The Symfony 3.3 DI Container Changes Explained (autowiring, _defaults, etc).

You can also organize your own code into services. For example, suppose you need to show your users a random, happy message. If you put this code in your controller, it can't be re-used. Instead, you decide to create a new class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/AppBundle/Service/MessageGenerator.php
namespace AppBundle\Service;
 
class MessageGenerator
{
    public function getHappyMessage()
    {
        $messages = [
            'You did it! You updated the system! Amazing!',
            'That was one of the coolest updates I\'ve seen all day!',
            'Great work! Keep going!',
        ];
 
        $index = array_rand($messages);
 
        return $messages[$index];
    }
}

注入服务/配置成一个服务 

处理多个服务 

手动关联参数 

服务参数(Parameters) 

选择一个特殊服务 

Autowire自动关联选项 

Autoconfigure自动配置选项 

Public vs Private服务 

使用resource一次导入多个服务 

显式配置服务及其参数 

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)