亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

annuaire recherche
閱讀前篇 簡(jiǎn)介 Yii 是什么 從 Yii 1.1 升級(jí) 入門(mén) 安裝 Yii 運(yùn)行應(yīng)用 第一次問(wèn)候 使用Forms 數(shù)據(jù)庫(kù)應(yīng)用 使用 Gii 生成代碼 進(jìn)階 應(yīng)用結(jié)構(gòu) 概述 入口腳本 應(yīng)用(Applications) 應(yīng)用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過(guò)濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴(kuò)展(Extensions) 請(qǐng)求處理 運(yùn)行概述 啟動(dòng)引導(dǎo)(Bootstrapping) 路由和創(chuàng)建URL 請(qǐng)求(Requests) 響應(yīng)(Responses) Sessions 和 Cookies 錯(cuò)誤處理(Handling Errors) 日志(Logging) 關(guān)鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類(lèi)自動(dòng)加載(Autoloading) 服務(wù)定位器(Service Locator) 依賴(lài)注入容器(Dependency Injection Container) 配合數(shù)據(jù)庫(kù)工作 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn) (Data Access Objects) 查詢(xún)生成器(Query Builder) 活動(dòng)記錄(Active Record) 數(shù)據(jù)庫(kù)遷移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用戶(hù)數(shù)據(jù) 創(chuàng)建表單(Creating Forms) 輸入驗(yàn)證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復(fù)合表單(Getting Data for Multiple Models) 顯示數(shù)據(jù) 格式化輸出數(shù)據(jù)(Data Formatting) 分頁(yè)(Pagination) 排序(Sorting) 數(shù)據(jù)提供器(Data Providers) 數(shù)據(jù)小部件(Data Widgets) 客戶(hù)端腳本使用(Working with Client Scripts) 主題(Theming) 安全 認(rèn)證(Authentication) 授權(quán)(Authorization) 處理密碼(Working with Passwords) 客戶(hù)端認(rèn)證(Auth Clients) 最佳安全實(shí)踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁(yè)面緩存 HTTP 緩存 RESTfull Web服務(wù) 快速入門(mén)(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(yīng)(Response Formatting) 授權(quán)認(rèn)證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯(cuò)誤處理(Error Handling) 開(kāi)發(fā)工具 調(diào)試工具欄和調(diào)試器 使用Gii生成代碼 生成API文檔 測(cè)試 概述(Overview) 配置測(cè)試環(huán)境(Testing environment setup) 單元測(cè)試(Unit Tests) 功能測(cè)試(Function Tests) 驗(yàn)收測(cè)試(Acceptance Tests) 測(cè)試夾具(Fixtures) 高級(jí)專(zhuān)題 高級(jí)應(yīng)用模板 創(chuàng)建自定義應(yīng)用程序結(jié)構(gòu) 控制臺(tái)命令 核心驗(yàn)證器(Core Validators) 國(guó)際化 收發(fā)郵件 性能優(yōu)化 共享主機(jī)環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類(lèi) 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
personnages

依賴(lài)注入容器

依賴(lài)注入容器

依賴(lài)注入(Dependency Injection,DI)容器就是一個(gè)對(duì)象,它知道怎樣初始化并配置對(duì)象及其依賴(lài)的所有對(duì)象。Martin 的文章?已經(jīng)解釋了 DI 容器為什么很有用。這里我們主要講解 Yii 提供的 DI 容器的使用方法。

依賴(lài)注入

Yii 通過(guò) yii\di\Container 類(lèi)提供 DI 容器特性。它支持如下幾種類(lèi)型的依賴(lài)注入:

  • 構(gòu)造方法注入;
  • Setter 和屬性注入;
  • PHP 回調(diào)注入.

構(gòu)造方法注入

在參數(shù)類(lèi)型提示的幫助下,DI 容器實(shí)現(xiàn)了構(gòu)造方法注入。當(dāng)容器被用于創(chuàng)建一個(gè)新對(duì)象時(shí),類(lèi)型提示會(huì)告訴它要依賴(lài)什么類(lèi)或接口。容器會(huì)嘗試獲取它所依賴(lài)的類(lèi)或接口的實(shí)例,然后通過(guò)構(gòu)造器將其注入新的對(duì)象。例如:

class Foo{
    public function __construct(Bar $bar)
    {
    }
}

$foo = $container->get('Foo');
// 上面的代碼等價(jià)于:$bar = new Bar;
$foo = new Foo($bar);

Setter 和屬性注入

Setter 和屬性注入是通過(guò)配置提供支持的。當(dāng)注冊(cè)一個(gè)依賴(lài)或創(chuàng)建一個(gè)新對(duì)象時(shí),你可以提供一個(gè)配置,該配置會(huì)提供給容器用于通過(guò)相應(yīng)的 Setter 或?qū)傩宰⑷胍蕾?lài)。例如:

use yii\base\Object;

class Foo extends Object{
    public $bar;

    private $_qux;

    public function getQux()
    {
        return $this->_qux;
    }

    public function setQux(Qux $qux)
    {
        $this->_qux = $qux;
    }
}

$container->get('Foo', [], [
    'bar' => $container->get('Bar'),
    'qux' => $container->get('Qux'),
]);

PHP 回調(diào)注入

這種情況下,容器將使用一個(gè)注冊(cè)過(guò)的 PHP 回調(diào)創(chuàng)建一個(gè)類(lèi)的新實(shí)例?;卣{(diào)負(fù)責(zé)解決依賴(lài)并將其恰當(dāng)?shù)刈⑷胄聞?chuàng)建的對(duì)象。例如:

$container->set('Foo', function () {
    return new Foo(new Bar);
});

$foo = $container->get('Foo');

注冊(cè)依賴(lài)關(guān)系

可以用 yii\di\Container::set() 注冊(cè)依賴(lài)關(guān)系。注冊(cè)會(huì)用到一個(gè)依賴(lài)關(guān)系名稱(chēng)和一個(gè)依賴(lài)關(guān)系的定義。依賴(lài)關(guān)系名稱(chēng)可以是一個(gè)類(lèi)名,一個(gè)接口名或一個(gè)別名。依賴(lài)關(guān)系的定義可以是一個(gè)類(lèi)名,一個(gè)配置數(shù)組,或者一個(gè) PHP 回調(diào)。

$container = new \yii\di\Container;

// 注冊(cè)一個(gè)同類(lèi)名一樣的依賴(lài)關(guān)系,這個(gè)可以省略。$container->set('yii\db\Connection');

// 注冊(cè)一個(gè)接口// 當(dāng)一個(gè)類(lèi)依賴(lài)這個(gè)接口時(shí),相應(yīng)的類(lèi)會(huì)被初始化作為依賴(lài)對(duì)象。$container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer');

// 注冊(cè)一個(gè)別名。// 你可以使用 $container->get('foo') 創(chuàng)建一個(gè) Connection 實(shí)例$container->set('foo', 'yii\db\Connection');

// 通過(guò)配置注冊(cè)一個(gè)類(lèi)// 通過(guò) get() 初始化時(shí),配置將會(huì)被使用。$container->set('yii\db\Connection', [
    'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
]);

// 通過(guò)類(lèi)的配置注冊(cè)一個(gè)別名// 這種情況下,需要通過(guò)一個(gè) “class” 元素指定這個(gè)類(lèi)$container->set('db', [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
]);

// 注冊(cè)一個(gè) PHP 回調(diào)// 每次調(diào)用 $container->get('db') 時(shí),回調(diào)函數(shù)都會(huì)被執(zhí)行。$container->set('db', function ($container, $params, $config) {
    return new \yii\db\Connection($config);
});

// 注冊(cè)一個(gè)組件實(shí)例// $container->get('pageCache') 每次被調(diào)用時(shí)都會(huì)返回同一個(gè)實(shí)例。$container->set('pageCache', new FileCache);

Tip: 如果依賴(lài)關(guān)系名稱(chēng)和依賴(lài)關(guān)系的定義相同,則不需要通過(guò) DI 容器注冊(cè)該依賴(lài)關(guān)系。

通過(guò)?set()?注冊(cè)的依賴(lài)關(guān)系,在每次使用時(shí)都會(huì)產(chǎn)生一個(gè)新實(shí)例??梢允褂?yii\di\Container::setSingleton() 注冊(cè)一個(gè)單例的依賴(lài)關(guān)系:

$container->setSingleton('yii\db\Connection', [
    'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
]);

解決依賴(lài)關(guān)系

注冊(cè)依賴(lài)關(guān)系后,就可以使用 DI 容器創(chuàng)建新對(duì)象了。容器會(huì)自動(dòng)解決依賴(lài)關(guān)系,將依賴(lài)實(shí)例化并注入新創(chuàng)建的對(duì)象。依賴(lài)關(guān)系的解決是遞歸的,如果一個(gè)依賴(lài)關(guān)系中還有其他依賴(lài)關(guān)系,則這些依賴(lài)關(guān)系都會(huì)被自動(dòng)解決。

可以使用 yii\di\Container::get() 創(chuàng)建新的對(duì)象。該方法接收一個(gè)依賴(lài)關(guān)系名稱(chēng),它可以是一個(gè)類(lèi)名,一個(gè)接口名或一個(gè)別名。依賴(lài)關(guān)系名或許是通過(guò)?set()?或?setSingleton()?注冊(cè)的。你可以隨意地提供一個(gè)類(lèi)的構(gòu)造器參數(shù)列表和一個(gè)configuration?用于配置新創(chuàng)建的對(duì)象。例如:

// "db" 是前面定義過(guò)的一個(gè)別名$db = $container->get('db');

// 等價(jià)于: $engine = new \app\components\SearchEngine($apiKey, ['type' => 1]);$engine = $container->get('app\components\SearchEngine', [$apiKey], ['type' => 1]);

代碼背后,DI 容器做了比創(chuàng)建對(duì)象多的多的工作。容器首先將檢查類(lèi)的構(gòu)造方法,找出依賴(lài)的類(lèi)或接口名,然后自動(dòng)遞歸解決這些依賴(lài)關(guān)系。

如下代碼展示了一個(gè)更復(fù)雜的示例。UserLister?類(lèi)依賴(lài)一個(gè)實(shí)現(xiàn)了?UserFinderInterface?接口的對(duì)象;UserFinder?類(lèi)實(shí)現(xiàn)了這個(gè)接口,并依賴(lài)于一個(gè)?Connection?對(duì)象。所有這些依賴(lài)關(guān)系都是通過(guò)類(lèi)構(gòu)造器參數(shù)的類(lèi)型提示定義的。通過(guò)屬性依賴(lài)關(guān)系的注冊(cè),DI 容器可以自動(dòng)解決這些依賴(lài)關(guān)系并能通過(guò)一個(gè)簡(jiǎn)單的?get('userLister')?調(diào)用創(chuàng)建一個(gè)新的?UserLister?實(shí)例。

namespace app\models;

use yii\base\Object;
use yii\db\Connection;
use yii\di\Container;

interface UserFinderInterface{
    function findUser();
}

class UserFinder extends Object implements UserFinderInterface{
    public $db;

    public function __construct(Connection $db, $config = [])
    {
        $this->db = $db;
        parent::__construct($config);
    }

    public function findUser()
    {
    }
}

class UserLister extends Object{
    public $finder;

    public function __construct(UserFinderInterface $finder, $config = [])
    {
        $this->finder = $finder;
        parent::__construct($config);
    }
}

$container = new Container;
$container->set('yii\db\Connection', [
    'dsn' => '...',
]);
$container->set('app\models\UserFinderInterface', [
    'class' => 'app\models\UserFinder',
]);
$container->set('userLister', 'app\models\UserLister');

$lister = $container->get('userLister');

// 等價(jià)于:

$db = new \yii\db\Connection(['dsn' => '...']);
$finder = new UserFinder($db);
$lister = new UserLister($finder);

實(shí)踐中的運(yùn)用

當(dāng)在應(yīng)用程序的入口腳本中引入?Yii.php?文件時(shí),Yii 就創(chuàng)建了一個(gè) DI 容器。這個(gè) DI 容器可以通過(guò) Yii::$container 訪(fǎng)問(wèn)。當(dāng)調(diào)用 Yii::createObject() 時(shí),此方法實(shí)際上會(huì)調(diào)用這個(gè)容器的 yii\di\Container::get() 方法創(chuàng)建新對(duì)象。如上所述,DI 容器會(huì)自動(dòng)解決依賴(lài)關(guān)系(如果有)并將其注入新創(chuàng)建的對(duì)象中。因?yàn)?Yii 在其多數(shù)核心代碼中都使用了 Yii::createObject() 創(chuàng)建新對(duì)象,所以你可以通過(guò) Yii::$container 全局性地自定義這些對(duì)象。

例如,你可以全局性自定義 yii\widgets\LinkPager 中分頁(yè)按鈕的默認(rèn)數(shù)量:

\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

這樣如果你通過(guò)如下代碼在一個(gè)視圖里使用這個(gè)掛件,它的?maxButtonCount?屬性就會(huì)被初始化為 5 而不是類(lèi)中定義的默認(rèn)值 10。

echo \yii\widgets\LinkPager::widget();

然而你依然可以覆蓋通過(guò) DI 容器設(shè)置的值:

echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]);

另一個(gè)例子是借用 DI 容器中自動(dòng)構(gòu)造方法注入帶來(lái)的好處。假設(shè)你的控制器類(lèi)依賴(lài)一些其他對(duì)象,例如一個(gè)旅館預(yù)訂服務(wù)。你可以通過(guò)一個(gè)構(gòu)造器參數(shù)聲明依賴(lài)關(guān)系,然后讓 DI 容器幫你自動(dòng)解決這個(gè)依賴(lài)關(guān)系。

namespace app\controllers;

use yii\web\Controller;
use app\components\BookingInterface;

class HotelController extends Controller{
    protected $bookingService;

    public function __construct($id, $module, BookingInterface $bookingService, $config = [])
    {
        $this->bookingService = $bookingService;
        parent::__construct($id, $module, $config);
    }
}

如果你從瀏覽器中訪(fǎng)問(wèn)這個(gè)控制器,你將看到一個(gè)報(bào)錯(cuò)信息,提醒你?BookingInterface?無(wú)法被實(shí)例化。這是因?yàn)槟阈枰嬖V DI 容器怎樣處理這個(gè)依賴(lài)關(guān)系。

\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService');

現(xiàn)在如果你再次訪(fǎng)問(wèn)這個(gè)控制器,一個(gè)?app\components\BookingService?的實(shí)例就會(huì)被創(chuàng)建并被作為第三個(gè)參數(shù)注入到控制器的構(gòu)造器中。

什么時(shí)候注冊(cè)依賴(lài)關(guān)系

由于依賴(lài)關(guān)系在創(chuàng)建新對(duì)象時(shí)需要解決,因此它們的注冊(cè)應(yīng)該盡早完成。如下是推薦的實(shí)踐:

  • 如果你是一個(gè)應(yīng)用程序的開(kāi)發(fā)者,你可以在應(yīng)用程序的入口腳本或者被入口腳本引入的腳本中注冊(cè)依賴(lài)關(guān)系。
  • 如果你是一個(gè)可再分發(fā)擴(kuò)展的開(kāi)發(fā)者,你可以將依賴(lài)關(guān)系注冊(cè)到擴(kuò)展的引導(dǎo)類(lèi)中。

總結(jié)

依賴(lài)注入和服務(wù)定位器都是流行的設(shè)計(jì)模式,它們使你可以用充分解耦且更利于測(cè)試的風(fēng)格構(gòu)建軟件。強(qiáng)烈推薦你閱讀?Martin 的文章?,對(duì)依賴(lài)注入和服務(wù)定位器有個(gè)更深入的理解。

Yii 在依賴(lài)住入(DI)容器之上實(shí)現(xiàn)了它的服務(wù)定位器。當(dāng)一個(gè)服務(wù)定位器嘗試創(chuàng)建一個(gè)新的對(duì)象實(shí)例時(shí),它會(huì)把調(diào)用轉(zhuǎn)發(fā)到 DI 容器。后者將會(huì)像前文所述那樣自動(dòng)解決依賴(lài)關(guān)系。
Article précédent: Article suivant: