国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

為什么我們需要 Laravel IoC 容器?

xiaokai / 2611人閱讀

摘要:哲學(xué)的一個(gè)重要組成部分就是容器,也可以稱為服務(wù)容器。那我們要怎么做呢請(qǐng)看下面的例子數(shù)據(jù)庫(kù)連接通過上面的代碼,如果我們想把改成,根本不需要去修改類構(gòu)造函數(shù)里的依賴。現(xiàn)在我要講下容器里到底發(fā)生了什么。

IOC 容器是一個(gè)實(shí)現(xiàn)依賴注入的便利機(jī)制 - Taylor?Otwell

文章轉(zhuǎn)自:https://learnku.com/laravel/t...

Laravel 是當(dāng)今最流行、最常使用的開源現(xiàn)代 web 應(yīng)用框架之一。它提供了一些獨(dú)特的特性,比如 Eloquent ORM, Query 構(gòu)造器,Homestead 等時(shí)髦的特性,這些特性只有 Laravel 中才有。

我喜歡 Laravel 是由于它猶如建筑風(fēng)格一樣的獨(dú)特設(shè)計(jì)。Laravel 的底層使用了多設(shè)計(jì)模式,比如單例、工廠、建造者、門面、策略、提供者、代理等模式。隨著本人知識(shí)的增長(zhǎng),我越來越發(fā)現(xiàn) Laravel 的美。Laravel 為開發(fā)者減少了苦惱,帶來了更多的便利。

學(xué)習(xí) Laravel,不僅僅是學(xué)習(xí)如何使用不同的類,還要學(xué)習(xí) Laravel 的哲學(xué),學(xué)習(xí)它優(yōu)雅的語法。Laravel 哲學(xué)的一個(gè)重要組成部分就是 IoC 容器,也可以稱為服務(wù)容器。它是一個(gè) Laravel 應(yīng)用的核心部分,因此理解并使用 IoC 容器是我們必須掌握的一項(xiàng)重要技能。

IoC 容器是一個(gè)非常強(qiáng)大的類管理工具。它可以自動(dòng)解析類。接下來我會(huì)試著去說清楚它為什么如此重要,以及它的工作原理。

首先,我想先談下依賴反轉(zhuǎn)原則,對(duì)它的了解會(huì)有助于我們更好地理解 IoC 容器的重要性。

該原則規(guī)定:

高層次的模塊不應(yīng)該依賴于低層次的模塊,兩者都應(yīng)該依賴于抽象接口。

抽象接口不應(yīng)該依賴于具體實(shí)現(xiàn)。而具體實(shí)現(xiàn)則應(yīng)該依賴于抽象接口。

一言以蔽之: 依賴于抽象而非具體

class MySQLConnection
{

   /**
   * 數(shù)據(jù)庫(kù)連接
   */
   public function connect()
   {
      var_dump(‘MYSQL Connection’);
   }

}


class PasswordReminder
{    
    /**
     * @var MySQLConnection
     */
     private $dbConnection;

    public function __construct(MySQLConnection $dbConnection) 
    {
      $this->dbConnection = $dbConnection;
    }
}

大家常常會(huì)有一個(gè)誤解,那就是依賴反轉(zhuǎn)就只是依賴注入的另一種說法。但其實(shí)二者是不同的。在上面的代碼示例中,盡管在 PasswordReminder 類中注入了 MySQLConnection 類,但它還是依賴于 MySQLConnection 類。

然而,高層次模塊 PasswordReminder 是不應(yīng)該依賴于低層次模塊 MySQLConnection 的。

如果我們想要把 MySQLConnection 改成 MongoDBConnection,那我們就還得手動(dòng)修改 PasswordReminder 類構(gòu)造函數(shù)里的依賴。

PasswordReminder 類應(yīng)該依賴于抽象接口,而非具體類。那我們要怎么做呢?請(qǐng)看下面的例子:

interface ConnectionInterface
{
   public function connect();
}

class DbConnection implements ConnectionInterface
{
 /**
  * 數(shù)據(jù)庫(kù)連接
  */
 public function connect()
 {
   var_dump(‘MYSQL Connection’);
 }
}

class PasswordReminder
{
    /**
    * @var DBConnection
    */
    private $dbConnection;
    public function __construct(ConnectionInterface $dbConnection)
    {
      $this->dbConnection = $dbConnection;
    }
}

通過上面的代碼,如果我們想把 MySQLConnection 改成 MongoDBConnection,根本不需要去修改 PasswordReminder 類構(gòu)造函數(shù)里的依賴。因?yàn)楝F(xiàn)在 PasswordReminder 類依賴的是接口,而非具體類。

如果你對(duì)接口的概念還不是很了解,可以看下?這篇文章?。它會(huì)幫助你理解依賴反轉(zhuǎn)原則和 IoC 容器等。

現(xiàn)在我要講下 IoC 容器里到底發(fā)生了什么。我們可以把 IoC 容器簡(jiǎn)單地理解為就是一個(gè)容器,里面裝的是類的依賴。

OrderRepositoryInterface 接口:

namespace AppRepositories;

interface OrderRepositoryInterface 
{
   public function getAll();
}

DbOrderRepository 類:

namespace AppRepositories;

class DbOrderRepository implements OrderRepositoryInterface
{

  function getAll()
  {
    return "Getting all from mysql";
  }
}

OrdersController 類:

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppHttpRequests;
use AppRepositoriesOrderRepositoryInterface;

class OrdersController extends Controller
{
    protected $order;

   function __construct(OrderRepositoryInterface $order)
   {
     $this->order = $order;
   }

   public function index()
   {
     dd($this->order->getAll());
     return View::make(orders.index);
   }
}

路由:

Route::resource("orders", "OrdersController");

現(xiàn)在,在瀏覽器中輸入這個(gè)地址 ?

報(bào)錯(cuò)了吧,錯(cuò)誤的原因是服務(wù)容器正在嘗試去實(shí)例化一個(gè)接口,而接口是不能被實(shí)例化的。解決這個(gè)問題,只需把接口綁定到一個(gè)具體的類上:

把下面這行代碼加在路由文件里就搞定了:

App::bind("AppRepositoriesOrderRepositoryInterface", "AppRepositoriesDbOrderRepository");

現(xiàn)在刷新瀏覽器看看:

我們可以這樣定義一個(gè)容器類:

class SimpleContainer
 {
    protected static $container = [];

    public static function bind($name, Callable $resolver)
    {   
        static::$container[$name] = $resolver;
    }

    public static function make($name)
    {
      if(isset(static::$container[$name])){
        $resolver = static::$container[$name] ;
        return $resolver();
    }

    throw new Exception("Binding does not exist in containeer");

   }
}

這里,我想告訴你服務(wù)容器解析依賴是多么簡(jiǎn)單的事。

class LogToDatabase 
{
    public function execute($message)
    {
       var_dump("log the message to a database :".$message);
    }
}

class UsersController {

    protected $logger;

    public function __construct(LogToDatabase $logger)
    {
        $this->logger = $logger;
    }

    public function show()
    {
      $user = "JohnDoe";
      $this->logger->execute($user);
    }
}

綁定依賴:

SimpleContainer::bind("Foo", function()
 {
   return new UsersController(new LogToDatabase);
 });

$foo = SimpleContainer::make("Foo");

print_r($foo->show());

輸出:

string(36) "Log the messages to a file : JohnDoe"

Laravel 的服務(wù)容器源碼:

  public function bind($abstract, $concrete = null, $shared = false)
    {
        $abstract = $this->normalize($abstract);

        $concrete = $this->normalize($concrete);

        if (is_array($abstract)) {
           list($abstract, $alias) = $this->extractAlias($abstract);

           $this->alias($abstract, $alias);
        }

        $this->dropStaleInstances($abstract);

        if (is_null($concrete)) {
            $concrete = $abstract;
        }


        if (! $concrete instanceof Closure) {
            $concrete = $this->getClosure($abstract, $concrete);
        }

        $this->bindings[$abstract] = compact("concrete", "shared");


        if ($this->resolved($abstract)) {
            $this->rebound($abstract);
        }
    }

    public function make($abstract, array $parameters = [])
    {
        $abstract = $this->getAlias($this->normalize($abstract));

        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }

        $concrete = $this->getConcrete($abstract);

        if ($this->isBuildable($concrete, $abstract)) {
            $object = $this->build($concrete, $parameters);
        } else {
            $object = $this->make($concrete, $parameters);
        }


        foreach ($this->getExtenders($abstract) as $extender) {
            $object = $extender($object, $this);
        }

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

       $this->fireResolvingCallbacks($abstract, $object);

       $this->resolved[$abstract] = true;

       return $object;
    }

    public function build($concrete, array $parameters = [])
    {

        if ($concrete instanceof Closure) {
            return $concrete($this, $parameters);
        }

       $reflector = new ReflectionClass($concrete);

        if (! $reflector->isInstantiable()) {
            if (! empty($this->buildStack)) {
                $previous = implode(", ", $this->buildStack);
                $message = "Target [$concrete] is not instantiable while building [$previous].";
            } else {
                $message = "Target [$concrete] is not instantiable.";
            }

          throw new BindingResolutionException($message);
        }

         $this->buildStack[] = $concrete;

         $constructor = $reflector->getConstructor();

        if (is_null($constructor)) {
            array_pop($this->buildStack);

           return new $concrete;
        }

        $dependencies = $constructor->getParameters();
        $parameters = $this->keyParametersByArgument(
            $dependencies, $parameters
        );

         $instances = $this->getDependencies($dependencies,$parameters);

         array_pop($this->buildStack);

         return $reflector->newInstanceArgs($instances);
    }

如果你想了解關(guān)于服務(wù)容器的更多內(nèi)容,可以看下 ?vendor/laravel/framwork/src/Illuminate/Container/Container.php

簡(jiǎn)單的綁定

$this->app->bind("HelpSpotAPI", function ($app) {
    return new HelpSpotAPI($app->make("HttpClient"));
});

單例模式綁定

通過 singleton?方法綁定到服務(wù)容器的類或接口,只會(huì)被解析一次。

$this->app->singleton("HelpSpotAPI", function ($app) {
    return new HelpSpotAPI($app->make("HttpClient"));
});

綁定實(shí)例

也可以通過 instance 方法把具體的實(shí)例綁定到服務(wù)容器中。之后,就會(huì)一直返回這個(gè)綁定的實(shí)例:

$api = new HelpSpotAPI(new HttpClient);

$this->app->instance("HelpSpotAPI", $api);

如果沒有綁定,PHP 會(huì)利用反射機(jī)制來解析實(shí)例和依賴。

如果想了解更多細(xì)節(jié),可以查看?官方文檔

關(guān)于 Laravel 服務(wù)容器的練習(xí)代碼, 可以從我的 ?GitHub?(如果喜歡,煩請(qǐng)不吝 star )倉(cāng)庫(kù)獲取。

感謝閱讀。

文章轉(zhuǎn)自:https://learnku.com/laravel/t... 

更多文章:https://learnku.com/laravel/c...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/31261.html

相關(guān)文章

  • 詳解 Laravel 中的依賴注入和 IoC

    摘要:依賴注入依賴注入一詞是由提出的術(shù)語,它是將組件注入到應(yīng)用程序中的一種行為。就像說的依賴注入是敏捷架構(gòu)中關(guān)鍵元素。類依賴于,所以我們的代碼可能是這樣的創(chuàng)建一個(gè)這是一種經(jīng)典的方法,讓我們從使用構(gòu)造函數(shù)注入開始。 showImg(https://segmentfault.com/img/remote/1460000018806800); 文章轉(zhuǎn)自:https://learnku.com/la...

    haitiancoder 評(píng)論0 收藏0
  • php實(shí)現(xiàn)依賴注入(DI)和控制反轉(zhuǎn)(IOC)

    摘要:工廠模式,依賴轉(zhuǎn)移當(dāng)然,實(shí)現(xiàn)控制反轉(zhuǎn)的方法有幾種。其實(shí)我們稍微改造一下這個(gè)類,你就明白,工廠類的真正意義和價(jià)值了。雖然如此,工廠模式依舊十分優(yōu)秀,并且適用于絕大多數(shù)情況。 此篇文章轉(zhuǎn)載自laravel-china,chongyi的文章https://laravel-china.org/top...原文地址: http://www.insp.top/learn-lar... ,轉(zhuǎn)載務(wù)必保...

    tomato 評(píng)論0 收藏0
  • 深入理解控制反轉(zhuǎn)(IoC)和依賴注入(DI)

    摘要:本文一大半內(nèi)容都是通過舉例來讓讀者去理解什么是控制反轉(zhuǎn)和依賴注入,通過理解這些概念,來更加深入。這種由外部負(fù)責(zé)其依賴需求的行為,我們可以稱其為控制反轉(zhuǎn)。工廠模式,依賴轉(zhuǎn)移當(dāng)然,實(shí)現(xiàn)控制反轉(zhuǎn)的方法有幾種。 容器,字面上理解就是裝東西的東西。常見的變量、對(duì)象屬性等都可以算是容器。一個(gè)容器能夠裝什么,全部取決于你對(duì)該容器的定義。當(dāng)然,有這樣一種容器,它存放的不是文本、數(shù)值,而是對(duì)象、對(duì)象的描...

    HollisChuang 評(píng)論0 收藏0
  • 深入剖析 Laravel 服務(wù)容器

    摘要:劃下重點(diǎn),服務(wù)容器是用于管理類的依賴和執(zhí)行依賴注入的工具。類的實(shí)例化及其依賴的注入,完全由服務(wù)容器自動(dòng)的去完成。 本文首發(fā)于 深入剖析 Laravel 服務(wù)容器,轉(zhuǎn)載請(qǐng)注明出處。喜歡的朋友不要吝嗇你們的贊同,謝謝。 之前在 深度挖掘 Laravel 生命周期 一文中,我們有去探究 Laravel 究竟是如何接收 HTTP 請(qǐng)求,又是如何生成響應(yīng)并最終呈現(xiàn)給用戶的工作原理。 本章將帶領(lǐng)大...

    abson 評(píng)論0 收藏0
  • PHPer面試指南-Laravel

    摘要:簡(jiǎn)述的生命周期采用了單一入口模式,應(yīng)用的所有請(qǐng)求入口都是文件。分發(fā)請(qǐng)求一旦應(yīng)用完成引導(dǎo)和所有服務(wù)提供者都注冊(cè)完成,將會(huì)移交給路由進(jìn)行分發(fā)。此外,由于對(duì)動(dòng)態(tài)方法的獨(dú)特用法,也使測(cè)試起來非常容易。 本書的 GitHub 地址:https://github.com/todayqq/PH... Laravel 作為現(xiàn)在最流行的 PHP 框架,其中的知識(shí)較多,所以單獨(dú)拿出來寫一篇。 簡(jiǎn)述 La...

    alaege 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<