We all know that Laravel’s IOC Container can automatically resolve dependencies, which is amazing, right? What is the implementation principle behind it? What’s rocket science in it?

The reflection API, also known as the Reflection API, can parse classes, methods, extensions, etc., submitted to it in reverse.

Based on this information, you can figure out the type of a class, which dependencies it needs, which attributes it has, which parent classes it has, and so on, and then build instances accordingly to implement Laravel’s automatic dependency resolution.

Instead of looking at the code for laravel’s automatic dependency resolution, let’s take a look at PHP’s Reflection API, in particular its ReflectionClass, which is specifically designed to reverse class resolution.

class Foo { public $name = 'pilishen'; public $project = 'laravel'; protected $bar; //Constructor public function __construct(Bar $bar) { $this->bar = $bar; } public function name() { echo $this->name."\n"; } public function project() { echo $this->project."\n"; }}Copy the code

Get class name, namespace, filename:

$reflection = new ReflectionClass('Foo');
echo $reflection->getName();
Copy the code

Foo, which is the name of the class, and obviously getShortName().

If you want to get the path and name of the file where the class resides, you can use the getFileName() method, such as my display:

string '/home/vagrant/Code/php-test/index.php' (length=37)
Copy the code

Of course, getting a namespace is getNamespaceName()

Get various attributes or parameters:

var_dump($reflection->getDefaultProperties());
Copy the code

Get its default properties and values:

array (size=3)
  'name' => string 'pilishen' (length=8)
  'project' => string 'laravel' (length=7)
  'bar' => null
Copy the code

You might think of get_class_vars or get_object_vars. What if we only wanted to get its protected property at this point?

$props = $reflection->getProperties(ReflectionProperty::IS_PROTECTED);
var_dump($props);
Copy the code

This time shows:

array (size=1)
  0 => 
    object(ReflectionProperty)[2]
      public 'name' => string 'bar' (length=3)
      public 'class' => string 'Foo' (length=3)
Copy the code

You can filter the properties you want by passing the filter parameter in getProperties(). In practice, you can get the name of each property as follows:

foreach ($props as $prop) {
    print $prop->getName() . "\n";
}
Copy the code

Other property-related methods:

  • GetProperty () : Gets a specific property, such as $class->getProperty(‘name’);
  • GetStaticProperties () : Gets all static properties
  • GetStaticPropertyValue () : Gets the value of a specific static property
  • SetStaticPropertyValue () : Sets an existing static property value to a new value. It must be an existing property, you cannot add a new static property
  • HasProperty () : Checks to see if a particular property exists
  • HasConstant () : Checks whether a particular constant (const) exists

Get constructor information: Once constructor is obtained, it is usually possible to know what the class’s dependencies are.

var_dump($reflection->getConstructor());
Copy the code

You can see:

object(ReflectionMethod)[2]
  public 'name' => string '__construct' (length=11)
  public 'class' => string 'Foo' (length=3)
Copy the code

Constructor returns null if none is present, so in practice you can go further by is_null(). Next, execute:

$constructor = $reflection->getConstructor();
var_dump($constructor->getParameters());
Copy the code

Constructor returns concrete information as an array, each of which is an object:

array (size=1)
  0 => 
    object(ReflectionParameter)[3]
      public 'name' => string 'bar' (length=3)
Copy the code

We can then iterate over each parameter and get the corresponding type declaration on each parameter.

$constructor = $reflection->getConstructor();
$parameters = $constructor->getParameters();
foreach ($parameters as $parameter) {
    var_dump($parameter->getClass());
}
Copy the code

You can see:

object(ReflectionClass)[4]
  public 'name' => string 'Bar' (length=3)
Copy the code

If there is no class, then null is returned, indicating that a normal parameter is passed and no class declaration is made, and other operations can be performed.

For example, you can call isDefaultValueAvailable() to determine if there is a default value for this parameter, and then getDefaultValue() to get its default value. And return

class =

Class =parameter->getClass(), then $class->name to get its class name, and build dependent instances accordingly.

Other methods related to automatically building instances:

IsInstantiable () : For example, interface and Abstract classes cannot be instantiated. This is usually used at the beginning of a reverse lookup. For example, if the Class cannot be instantiated, there is no need to obtain information about its constructor.

NewInstanceArgs () : Creates a new instance based on the parameters you pass in. The parameters passed in (constructor) need to be the same as those passed in.

With that in mind, you can try to reverse parse a class, analyze its dependent dependencies, and return a class instance that automatically builds the dependencies.