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

不言
Freigeben: 2023-04-03 17:58:01
Original
4381 Leute haben es durchsucht

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,
    ...
]);
Nach dem Login kopieren

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方法,在该方法里调用反射等实现类的实例化,过程如下:
Nach dem Login kopieren
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;
}
Nach dem Login kopieren
/**
 * 调用反射执行类的实例化 支持依赖注入
 * @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);
}
Nach dem Login kopieren
/**
 * 执行函数或者闭包方法 支持参数调用
 * @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);
}
Nach dem Login kopieren

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');
Nach dem Login kopieren

Analysieren wir die Implementierung:

// thinkphp\library\facade\Config 类
Nach dem Login kopieren
namespace think\facade;

use think\Facade;

class Config extends Facade
{
}
Nach dem Login kopieren

// 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);
}
Nach dem Login kopieren

// 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);
}
Nach dem Login kopieren

//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 这个标识
Nach dem Login kopieren
// 在容器的make方法中,根据config标识,找到绑定的 think\Config 类,并调用其动态方法 get。

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

// 最后调用的是:

(new think\Config())->get('app_debug');
Nach dem Login kopieren

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!