Contributed by
Nicolas Grekas
in #26499.
在 Symfony 3.4 中我们令 所有服务默认为私有,意味着你不能够再在控制器中调用 $this->get('my_service_id')
来快速获取某些服务。
做出如此改变,是因为直接使用服务容器被认为是一个不好的实践,因为它藏匿了你的类的依赖,对外部配置来说强化了耦合,更令测试变得困难,也难以读懂。
任何时候当我们删除类似功能时,提供一个备选方案被认为是较合理的,而且,如果可能,要像之前的一样简单。这就是为什么 controller 允许在action方法以及constructor中 利用type hints(类型提示)注入服务。
"默认为private services" 的唯一欠点在于,测试比以前困难了。一些开发者甚至在 test
环境下定义了一些配置信息来让所有服务在测试时公有。在 Symfony 4.1 中我们做了同样的事,现在,默认是 测试时可以取出私有服务。
实践中,基于 WebTestCase
和 KernelTestCase
的测试,现在可以通过 $client->getContainer()
或 static::$container
属性访问到特殊的容器,它们允许取出 non-removed private services(不会被删除的私有服务):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Console\Tester\CommandTester;
class AddUserCommandTest extends WebTestCase
{
private function assertUserCreated()
{
self::bootKernel();
// returns the real and unchanged service container
// 返回真正的未有变化的服务容器
$container = self::$kernel->getContainer();
// returns the special container that allows fetching private services
// 返回特殊容器,其允许取出私有服务
$client = static::createClient();
$container = $client->getContainer();
// alternative way to get the special container:
// 另一个拿到特殊容器的方式
// $container = self::$container;
$user = self::$container->get('doctrine')->getRepository(User::class)->findOneByEmail('...');
$this->assertTrue(self::$container->get('security.password_encoder')->isPasswordValid($user, '...');
// ...
} |