Container und Abhängigkeitsinjektion
Container und Abhängigkeitsinjektion (Container)
Abhängigkeitsinjektion wird durch Container implementiert, die eine automatische Einführung realisieren können referenzierte Klassen, Und das automatische Laden der abhängigen Objekte der Klasse
Abhängigkeitsinjektion bezieht sich auf die automatische Injektion von Abhängigkeiten in die Klasse durch den Konstruktor:
<?php namespace app\index\controller; use app\index\model\User; class Index { protected $user; // 通过依赖注入方式,实现User实例的自动注入到当前对象中 public function __construct(User $user) { $this->user = $user; } public function hello() { return 'Hello,' . $this->user->name . '!'; } }
Die Objektparameter der Abhängigkeitsinjektion unterstützen mehrere und Die Reihenfolge ist irrelevant.
Bindung
Abhängigkeitsinjizierte Klassen werden vom Container einheitlich verwaltet und in den meisten Fällen automatisch gebunden und instanziiert. Sie können die Klasse jedoch jederzeit manuell an den Container binden (normalerweise in der Registermethode der Serviceklasse), und es werden mehrere Bindungsmethoden unterstützt.
Klassenbezeichner binden
Sie können einen Bezeichner (eindeutig) für einen schnellen Aufruf an eine vorhandene Klassenbibliothek binden.
// 绑定类库标识 $this->app->bind('cache', 'think\Cache');
oder die mit der Hilfsfunktion
// 绑定类库标识 bind('cache', 'think\Cache');
gebundene Klassenkennung können Sie selbst definieren (sofern kein Konflikt vorliegt).
Verschluss binden
Sie können einen Verschluss an den Container binden
bind('sayHello', function ($name) { return 'hello,' . $name; });
Instanz binden
kann auch direkt gebunden werden Eine Instanz einer Klasse
$cache = new think\Cache; // 绑定类实例 bind('cache', $cache);
ist an die Schnittstellenimplementierung gebunden
Für die Abhängigkeitsinjektion mithilfe von Schnittstellenklassen müssen wir dem System mitteilen, welche spezifische Schnittstellenimplementierungsklasse verwendet werden soll Zum Injizieren kann diese Verwendung eine bestimmte Klasse an die Schnittstelle binden
// 绑定think\LoggerInterface接口实现到think\Log bind('think\LoggerInterface','think\Log');
Verwenden Sie die Schnittstelle als Typ der Abhängigkeitsinjektion
<?php namespace app\index\controller; use think\LoggerInterface; class Index { public function hello(LoggerInterface $log) { $log->record('hello,world!'); } }
Stapelbindung
Im eigentlichen Anwendungsentwicklungsprozess ist keine manuelle Bindung erforderlich. Wir müssen lediglich die Datei „provider.php“ im Anwendungsverzeichnis definieren (ein Array zurückgeben), und das System bindet die Klassenbibliothek automatisch stapelweise an den Container.
return [ 'route' => \think\Route::class, 'session' => \think\Session::class, 'url' => \think\Url::class, ];
Der Bindungsbezeichner unterscheidet beim Aufruf die Groß-/Kleinschreibung. Das System verfügt über integrierte Bindungen der allgemeinen Kernklassenbibliotheken, sodass diese nicht wiederholt gebunden werden müssen.
Das System ist integriert An den Container gebundene Klassenbibliotheken umfassen
系统类库 | 容器绑定标识 |
---|---|
thinkApp | app |
thinkCache | cache |
thinkConfig | config |
thinkCookie | cookie |
thinkConsole | console |
thinkDb | db |
thinkDebug | debug |
thinkEnv | env |
thinkEvent | event |
thinkHttp | http |
thinkLang | lang |
thinkLog | log |
thinkMiddleware | middleware |
thinkRequest | request |
thinkResponse | response |
thinkFilesystem | filesystem |
thinkRoute | route |
thinkSession | session |
thinkValidate | validate |
thinkView | view |
Analyse
Verwenden Sie die App-Hilfsfunktion, um Klassenanalyseaufrufe im Container durchzuführen. Für die gebundene Klassenkennung wird diese automatisch und schnell instanziiert
$cache = app('cache');
mit Parametern Instantiate call
$cache = app('cache',['file']);
pair Für ungebundene Klassen können Sie auch direkt analysieren
$arrayItem = app('org\utils\ArrayItem');
Die aufrufenden und bindenden Bezeichner müssen konsistent sein (einschließlich Groß- und Kleinschreibung)
Klassen, die im Container aufgerufen wurden, verwenden automatisch Singletons. es sei denn, Sie erzwingen eine erneute Instanziierung mit der folgenden Methode.
// 每次调用都会重新实例化 $cache = app('cache', [], true);
Objektisierter Aufruf
Verwenden Sie die App-Hilfsfunktion, um die Objektinstanz im Container abzurufen (unterstützt die Abhängigkeitsinjektion).
$app = app(); // 判断对象实例是否存在 isset($app->cache); // 注册容器对象实例 $app->cache = think\Cache::class; // 获取容器中的对象实例 $cache = $app->cache;
Das heißt, Sie können die app()-Methode überall verwenden, um jede Klasse im Container aufzurufen. In den meisten Fällen empfehlen wir jedoch die Verwendung der Abhängigkeitsinjektion.
// 调用配置类 app()->config->get('app_name'); // 调用session类 app()->session->get('user_name');
Automatische Injektion
Abhängigkeitsinjektion prüft zunächst, ob die Objektinstanz im Container registriert wurde , es wird automatisch instanziiert und dann automatisch injiziert, zum Beispiel:
Wir können die Modellobjektinstanz an die Route binden
Route::get('user/:id','index/Index/hello') ->model('\app\index\model\User');
dann Fügen Sie dann automatisch das Benutzermodell in die Operationsmethode ein.
<?php namespace app\index\controller; use app\index\model\User; class Index { public function hello(User $user) { return 'Hello,'.$user->name; } }
Benutzerdefinierte Instanziierung
Die Objektinstanziierung im Container unterstützt die Anpassung, die bei Bedarf verwendet werden kann Verlassen Sie sich auf Fügen Sie dem injizierten Objekt die Methodendefinition __make hinzu, zum Beispiel:
Wenn Sie möchten, dass die Benutzermodellklasse während der Abhängigkeitsinjektion verwendet wird Um die benutzerdefinierte Instanziierung zu verwenden, können Sie die folgende Methode verwenden.
<?php namespace app\index\model; use think\Model; use think\db\Query; class User extends Model { public static function __make(Query $query) { return (new self())->setQuery($query); } }
Rückrufmechanismus für Containerobjekte
Nachdem das Objekt im Container instanziiert wurde, unterstützt es einen Rückrufmechanismus, mit dem verwandte Funktionen wie Anmerkungsfunktionen implementiert werden können .
Sie können einen globalen Rückruf über die Auflösungsmethode registrieren
Container::getInstance()->resolving(function($instance,$container) { // ... });
Die Rückrufmethode unterstützt zwei Parameter, der erste Parameter ist die Containerobjektinstanz und der zweite Parameter ist die Containerinstanz selbst.
Oder separat einen Rückruf für ein Containerobjekt registrieren
Container::getInstance()->resolving(\think\Cache::class,function($instance,$container) { // ... });