<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #依賴注入 依賴注入(DI)的目的是使類免除獲取其操作所需的對象的責任(這些對象被稱為服務)。 要在他們的實例化上傳遞這些服務。 我們在這章學到以下幾點: * 依賴注入的原理是什么。 * 如何創建動態和靜態DI容器。 * 如何延遲加載服務。 什么是依賴注入? 依賴注入(DI)是沒有什么神秘或令人費解的。 它可以被理解為一個自私的句子:“不要尋求任何東西,讓別人做它”。現在讓我們把它翻譯成程序員的演講。 我們有一個博客里面有一個Article類: ~~~ class Article { public $id; public $title; public $content; function save() { // 我們將數據保存到數據庫中 } } ~~~ 我們可以這樣使用這個類 ~~~ $article = new Article; $article->title = '10 Things You Need to Know About Losing Weight'; $article->content = 'Every year millions of people in ...'; $article->save(); ~~~ save()方法是將要把文章保存到articles數據表中,它使用Nette\Database很容易實現。但是怎樣Article得到數據庫連接。 即使用Connection類。 嗯,我們可以將它放入一些全局變量中,如$ GLOBALS ['connection']或類的一些靜態成員。 但是你沒有聽說過使用全局變量是錯誤的嗎? 這是真的,全局變量是邪惡的,靜態成員也是一樣的。 那么在我們怎樣得到數據庫連接? DI有答案:“不要尋找任何東西,讓別人做它。”換句話說,如果我需要一個數據庫,有人給我,這不是我的工作。 哈,它狡猾,親愛的DI! 我們開始做吧: ~~~ class Article { public $id; public $title; public $content; private $connection; function __construct(Nette\Database\Connection $connection) { $this->connection = $connection; } function save() { $this->connection->query('INSERT INTO articles', [ 'title' => $this->title, 'content' => $this->content, ]); } } ~~~ 使用Article類將稍有改變: ~~~ $article = new Article($connection); $article->title = ... $article->content = ... $article->save(); ~~~ 你在問,這個代碼需要$connection? DI給出一個直接的答案:“讓別人做它。”數據庫連接將由調用代碼的人提供。 等等,等等。 當然你說,不可能使責任的外交。 必須有一個零點。 你是對的。 開始有一個創造者,他沒有委托任何東西,他創造了對象。 我們稱之為系統容器。 他有一個單獨的章節。 以前學過對象編程的人不難看懂,但是沒有學過的話有點難了。實際上上面意思是做一個 Article對象,他有一個保存數據方法,但是在保存數據之前要連接數據,但是要怎樣連接數據呢,所以我們做一個$connection默認對象,如果有人要使用Article類,那他就要實例化它,程序就會自動注入$connection默認對象。有些象做一個電腦配置單,然后按配置單采購配件,再組裝起來,系統就是依賴注入,這樣才能成為一臺完整電腦出來,但可以按配置單組很多臺電腦,每臺電腦都有系統。 # 為什么全局變量是錯誤的呢? 好問題。 Article類無論如何都需要數據庫連接。 但從第一個例子,沒有顯示出來,從哪里和如何得到它。 這樣的代碼的用戶可能會感到驚訝,文章真的節省了,他問:“它在哪里保存?”第二個例子使用DI,代碼是自我解釋。 想象一下,你正在探索一些支付網關,你寫一個例子: ~~~ $cc = new CreditCard('4461510140804839', 12, 2013); $cc->pay(1000, CreditCard::DOLLARS); ~~~ 您運行的代碼,與您的卡號,后來你會發現,它真的從您的帳戶扣了錢! 震驚你盯著列表和哀嘆:“我的錢在哪里,怎么會發生,我沒有配對它任何支付網關!”類CreditCard自己做了,發現一個在一些全局變量中詞,神秘,如Article得到了數據庫連接。 這樣的事情你不是從代碼中推導出來的,你甚至不知道如何將網關改為另一個,比如測試。 # DI意味著更多的寫作 你可以實例化對象,使用DI意味著更多的寫作,那就是創建一個Article的實例,你必須處理數據庫連接等等。 這是真的,但不要忘記最后一次,當“少寫作”花費你$ 1000! 不,我們不想放松。 異常是正確的,我們將添加一個更大:當我們發現需要緩存一些數據,與DI協調,它將需要一個參數與緩存存儲庫。 這意味著在許多地方調整應用程序:至少在任何地方,其中Article要被實例化。 現在怎么辦? 事情有一個解決方案:而不是手動創建Article對象,我們做一個工廠,即。 函數創建這些文章對象。 當Article更改構造函數時,只有工廠必須更新,沒有更多。 和在哪里得到工廠在我們的代碼? 你知道...讓別人做。 :-) # DI容器和服務 術語“DI容器”是指工廠。 更確切地說,它是一個對象,包含任何數量的工廠,每個服務一個。 什么是服務? 普通對象,比如說Connection實例。 只是用DI容器我們稱之為服務。 也許一些顧問發明它使DI看起來很復雜,所以他們可以咨詢。 示例可以是創建Article對象的容器,也可以是所需的數據庫連接:: ~~~ class Container { function createConnection() { return new Nette\Database\Connection('mysql:', 'root', '***'); } function createArticle() { return new Article($this->createConnection()); } } ~~~ 用法如下: ~~~ $container = new Container; $article = $container->createArticle(); ~~~ 優點是顯而易見的,我們不需要關心這篇文章究竟是如何實例化的,這是工廠的工作。 無論如何,解決方案仍有兩個缺點。 首先,有條目數據連接到代碼,所以我們將它們分離成一個變量: ~~~ class Container { private $parameters; function __construct(array $parameters) { $this->parameters = $parameters; } function createConnection() { return new Nette\Database\Connection( $this->parameters['dsn'], $this->parameters['user'], $this->parameters['password'] ); } function createArticle() { return new Article($this->createConnection()); } } $container = new Container([ 'dsn' => 'mysql:', 'user' => 'root', 'password' => '***', ]); $article = $container->createArticle(); ~~~ 更重要的缺點是,總是,當我們要求一個Article創建時,將要開始新的數據庫連接。 這需要避免。 我們將添加方法getConnection,它將保留一次創建的服務以供下次使用: ~~~ class Container { private $parameters; private $services = []; function __construct(array $parameters) { $this->parameters = $parameters; } function createConnection() { return new Nette\Database\Connection( $this->parameters['dsn'], $this->parameters['user'], $this->parameters['password'] ); } function getConnection() { if (!isset($this->services['connection'])) { $this->services['connection'] = $this->createConnection(); } return $this->services['connection']; } function createArticle() { return new Article($this->getConnection()); } } ~~~ 現在我們有全功能DI容器。 如你所見,編寫它并不復雜。 值得注意的是,服務單獨不知道,這是由一些容器創建的,因此可以創建任何PHP對象的方式。 不用觸摸自己的源代碼。 # Nette\DI\Container Nette \ DI \ Container類是通用DI容器的靈活實現。 它自動確保該服務實例只創建一次。 我們可以使我們自己的容器靜態,即。 繼承這個類,或者當我們添加工廠作為閉包或回調時,它是動態的。 ## 靜態容器 工廠方法的名稱遵循統一的約定,它們包括前綴createService +從首字母大寫開始的服務的名稱。 如果他們不應該從外部訪問,可以降低其受保護的可見性。 請注意,容器已經為用戶參數定義了$parameters字段。 ~~~ class MyContainer extends Nette\DI\Container { protected function createServiceConnection() { return new Nette\Database\Connection( $this->parameters['dsn'], $this->parameters['user'], $this->parameters['password'] ); } protected function createServiceArticle() { return new Article($this->getService('connection')); } } ~~~ 現在我們創建一個容器的實例并傳遞參數: ~~~ $container = new MyContainer([ 'dsn' => 'mysql:', 'user' => 'root', 'password' => '***', ]); ~~~ 我們通過調用getService方法獲取服務: ~~~ $article = $container->getService('article'); ~~~ 如前所述,所有服務都只在一個容器中創建一次,但是如果容器總是創建一個Article的新實例,這將更有用。 它可以很容易地實現:而不是服務文章的工廠,我們將創建一個普通的方法createArticle: ~~~ class MyContainer extends Nette\DI\Container { function createServiceConnection() { return new Nette\Database\Connection( $this->parameters['dsn'], $this->parameters['user'], $this->parameters['password'] ); } function createArticle() { return new Article($this->getService('connection')); } } $container = new MyContainer(...); $article = $container->createArticle(); ~~~ 從$ container-> createArticle()的調用很明顯,一個新的對象總是被創建。 這是一個程序員的約定。 ## 動態容器 我們可以使用addService方法將服務添加到Nette \ DI \ Container甚至運行時。 工廠可以寫成PHP回調或閉包。 請注意,容器本身作為參數傳遞給它們,以便容易地訪問參數和其他服務。 ~~~ $container = new Nette\DI\Container; $container->addService('connection', function($container) { return new Nette\Database\Connection( $container->parameters['dsn'], $container->parameters['user'], $container->parameters['password'] ); }); ~~~ 當服務創建只包括簡單的實例化時,可以直接傳遞類名作為addService方法的第二個參數。 當我們已經創建了對象時,我們甚至可以傳遞它。 除了addService,我們還有hasService用于服務存在檢查,removeService用于刪除它
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看