Symfony 的自动装配在幕后是如何工作的?

fri*_*dde 3 php dependency-injection symfony symfony4

这不是关于说明(文档就足够了),而是关于事情如何运作的问题。

Symfony 4 的自动装配系统允许我们通过简单的类型提示自动注入服务

use App\Util\Rot13Transformer;

class TwitterClient
{
  public function __construct(Rot13Transformer $transformer)
  {
    $this->transformer = $transformer;
  }
}
Run Code Online (Sandbox Code Playgroud)

为了更深入地了解 PHP,我查看了 symfony-bundle 源代码,但找不到“魔法”发生的地方。

Symfony 如何防止 PHP 抗议没有足够的参数提供给构造函数(或任何使用自动装配的函数)?

Art*_*nix 6

他们使用反射

Symfony 如何防止 PHP 抗议没有足够的参数提供给构造函数

反射允许您检查 PHP 中其他“事物”的定义。其中包括类和它们的方法,以及这些方法的参数。

<?php
class bar
{
    //just a placeholder class
};

$bar = new bar(); //instance of bar

//class to inspect
class foo
{        
    public function __construct( bar $bar)
    {
        //do something fancy with $bar
    }        
}

//get the Reflection of the constructor from foo
$Method = new ReflectionMethod('foo', '__construct');

//get the parameters ( I call them arguments)
$Args = $Method->getParameters();

//get the first argument
$Arg = reset($Args);

//export the argument definition
$export = ReflectionParameter::export(
   array(
      $Arg->getDeclaringClass()->name, 
      $Arg->getDeclaringFunction()->name
   ), 
   $Arg->name, 
   true
);

//parse it for the typehint
$type = preg_replace('/.*?(\w+)\s+\$'.$Arg->name.'.*/', '\\1', $export);
echo "\nType: $type\n\n";

var_dump(is_a($bar, $type));
Run Code Online (Sandbox Code Playgroud)

输出:

Type: bar

bool(true)
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到

然后您只需使用is_a()或其他任何东西来查看“输入”对象是否bar作为其祖先之一。正如你在这个简化的例子中看到的,如果我们有对象 $bar,我们就会知道它非常适合作为我们构造函数的输入,因为它返回 true。

我应该注意到 SO 可能不是问这个问题的正确地方,但我可以在我的许多项目之一中使用它,所以我不介意弄清楚它。此外,我从未使用过 Symphony ......特别感谢这个 SO question 关于解析类型提示的最后一点:

PHP 反射 - 获取方法参数类型为字符串

也就是说,我会在大约 10 秒内弄清楚 Regx,导出方法没有那么多。

这是关于它的文档的范围

http://php.net/manual/en/reflectionparameter.export.php

字面上地

public static string ReflectionParameter::export ( string $function , string $parameter [, bool $return ] )
Run Code Online (Sandbox Code Playgroud)