Heim  >  Artikel  >  Backend-Entwicklung  >  Was sind Container und Fassaden? Eine kurze Analyse von Containern und Fassaden in thinkphp5.1

Was sind Container und Fassaden? Eine kurze Analyse von Containern und Fassaden in thinkphp5.1

不言
不言Original
2018-08-10 10:57:574388Durchsuche

In diesem Artikel erfahren Sie, was ein Container (Container) und eine Fassade (Fassade) ist. Die kurze Analyse von Containern und Fassaden in thinkphp5.1 hat einen gewissen Referenzwert. Ich hoffe, dass sie für Sie hilfreich ist.

P5.1 führte zwei neue Klassen ein, Container (Container) und Fassade (Facade).

Das offizielle Dokument hat die Definition angegeben:

Container (Container) zur Vereinheitlichung Verwaltung von Klassen und Gewährleistung der Einzigartigkeit von Objektinstanzen.

Facade bietet eine statische Aufrufschnittstelle für Klassen im Container (Container) und bietet eine bessere Testbarkeit und Skalierbarkeit. Sie können eine Fassadenklasse definieren.

Lassen Sie uns einen Blick tief in den Quellcode werfen, wie er implementiert ist:

// 在框架目录下的base.php文件

// 注册核心类到容器
Container::getInstance()->bind([
    'app'                   => App::class,
    'build'                 => Build::class,
    'cache'                 => Cache::class,
    'config'                => Config::class,
    ...
]);

// 注册核心类的静态代理
Facade::bind([
    facade\App::class      => App::class,
    facade\Build::class    => Build::class,
    facade\Cache::class    => Cache::class,
    facade\Config::class   => Config::class,
    ...
]);

// 注册类库别名
Loader::addClassAlias([
    'App'      => facade\App::class,
    'Build'    => facade\Build::class,
    'Cache'    => facade\Cache::class,
    'Config'   => facade\Config::class,
    ...
]);

Container-Implementierung:

Hier hat uns das Framework dabei geholfen, gängige Systemklassen daran zu binden Der Container Wenn Sie ihn später verwenden, müssen Sie nur die Hilfsfunktion app() aufrufen, um Klassenanalyseaufrufe im Container durchzuführen. Die gebundene Klassenkennung wird automatisch und schnell instanziiert.

// 实例化缓存类

app('cache'); 
// app('cache', ['file']); 参数化调用

// 相当于执行了
Container::get('cache');

// 查看源码,Container调用的其实是make方法,在该方法里调用反射等实现类的实例化,过程如下:
public function make($abstract, $vars = [], $newInstance = false)
{
    if (true === $vars) {
        // 总是创建新的实例化对象
        $newInstance = true;
        $vars        = [];
    }

    if (isset($this->instances[$abstract]) && !$newInstance) {
        $object = $this->instances[$abstract];
    } else {
        if (isset($this->bind[$abstract])) {
            $concrete = $this->bind[$abstract];
       // 闭包实现
            if ($concrete instanceof \Closure) {
                $object = $this->invokeFunction($concrete, $vars);
            } else {
                $object = $this->make($concrete, $vars, $newInstance);
            }
        } else {
       // 反射实现
            $object = $this->invokeClass($abstract, $vars);
        }

        if (!$newInstance) {
            $this->instances[$abstract] = $object;
        }
    }

    return $object;
}
/**
 * 调用反射执行类的实例化 支持依赖注入
 * @access public
 * @param  string    $class 类名
 * @param  array     $vars  变量
 * @return mixed
 */
public function invokeClass($class, $vars = [])
{
    $reflect     = new \ReflectionClass($class);
    $constructor = $reflect->getConstructor();

    if ($constructor) {
        $args = $this->bindParams($constructor, $vars);
    } else {
        $args = [];
    }

    return $reflect->newInstanceArgs($args);
}
/**
 * 执行函数或者闭包方法 支持参数调用
 * @access public
 * @param  string|array|\Closure $function 函数或者闭包
 * @param  array                 $vars     变量
 * @return mixed
 */
public function invokeFunction($function, $vars = [])
{
    $reflect = new \ReflectionFunction($function);
    $args    = $this->bindParams($reflect, $vars);

    return $reflect->invokeArgs($args);
}

Kurz gesagt, die Instanziierung von Klassen wird innerhalb des Containers durch Reflexionsklassen oder Abschlüsse implementiert.

Fassadenimplementierung:

Analysieren wir es anhand eines Beispiels:

facade\Config::get('app_debug');

Analysieren wir die Implementierung:

// thinkphp\library\facade\Config 类
namespace think\facade;

use think\Facade;

class Config extends Facade
{
}

// Aus dem Quellcode Es gibt keine Methode in Config selbst. Sie erbt die Methode von Facade, aber Facade erhält diese statische Methode nicht
// Zu diesem Zeitpunkt löst das System automatisch die magische Methode aus: __callStatic() und Facade schreibt diese Methode neu:

public static function __callStatic($method, $params)
{
    return call_user_func_array([static::createFacade(), $method], $params);
}

// Es ist ersichtlich, dass der letzte Aufruf die benutzerdefinierte Funktion ist: call_user_func_array([instance, method], parameter Um die Config-Instanz zu erhalten, definiert Facade eine Methode zum Abrufen des Objekts:

/**
 * 创建Facade实例
 * @static
 * @access protected
 * @param  string    $class          类名或标识
 * @param  array     $args           变量
 * @param  bool      $newInstance    是否每次创建新的实例
 * @return object
 */
protected static function createFacade($class = '', $args = [], $newInstance = false)
{
    $class       = $class ?: static::class;
    $facadeClass = static::getFacadeClass();

    if ($facadeClass) {
        $class = $facadeClass;
    } elseif (isset(self::$bind[$class])) {
        $class = self::$bind[$class];
    }

    if (static::$alwaysNewInstance) {
        $newInstance = true;
    }

    return Container::getInstance()->make($class, $args, $newInstance);
}

//Das Objekt wird intern über den Container instanziiert
// Da die thinkConfig-Klasse an die Konfigurationskennung in base.php gebunden wurde

Container::getInstance()->bind([
  'config'  => Config::class
])

// 在 createFacade 方法中,获取类的名称:$class = $class ?: static::class; 即得到 config 这个标识
// 在容器的make方法中,根据config标识,找到绑定的 think\Config 类,并调用其动态方法 get。

facade\Config::get('app_debug'); 

// 最后调用的是:

(new think\Config())->get('app_debug');

Kurz gesagt, die Fassade Die Implementierung erfolgt über die magische Methode __callStatic von PHP und arbeitet dann mit dem Container zusammen, um den statischen Aufruf dynamischer Klassen zu realisieren.

Verwandte Empfehlungen:

So beurteilen Sie, ob es sich bei der thinkphp-Vorlage um eine mobile WeChat-Zahlung oder eine WeChat-Scancode-Zahlung handelt

PHP möchte dies realisieren Seitensprung Wie funktioniert die Funktion? (Beispiel für ein Funktions-Tag)

Das obige ist der detaillierte Inhalt vonWas sind Container und Fassaden? Eine kurze Analyse von Containern und Fassaden in thinkphp5.1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn