laravel 學習筆記 —— 服務容器(IoC)

容器,字面上理解就是裝東西的東西。常見的變量、對象屬性等都可以算是容器。一個容器能夠裝什么,全部取決于你對該容器的定義。當然,有這樣一種容器,它存放的不是文本、數(shù)值,而是對象、對象的描述(類、接口)或者是提供對象的回調(diào),通過這種容器,我們得以實現(xiàn)許多高級的功能,其中最常提到的,就是 “解耦” 、“依賴注入(DI)”。本文就從這里開始。

IoC 容器, laravel 的核心

Laravel 的核心就是一個 IoC 容器,根據(jù)文檔,稱其為“服務容器”,顧名思義,該容器提供了整個框架中需要的一系列服務。作為初學者,很多人會在這一個概念上犯難,因此,我打算從一些基礎的內(nèi)容開始講解,通過理解面向?qū)ο箝_發(fā)中依賴的產(chǎn)生和解決方法,來逐漸揭開“依賴注入”的面紗,逐漸理解這一神奇的設計理念。

本文一大半內(nèi)容都是通過舉例來讓讀者去理解什么是 IoC(控制反轉)DI(依賴注入),通過理解這些概念,來更加深入。更多關于 laravel 服務容器的用法建議閱讀文檔即可。

IoC 容器誕生的故事

講解 IoC 容器有很多的文章,我之前也寫過。但現(xiàn)在我打算利用當下的靈感重新來過,那么開始吧。

超人和超能力,依賴的產(chǎn)生!

面向?qū)ο缶幊蹋幸韵聨讟訓|西無時不刻的接觸:接口、還有對象。這其中,接口是類的原型,一個類必須要遵守其實現(xiàn)的接口;對象則是一個類實例化后的產(chǎn)物,我們稱其為一個實例。當然這樣說肯定不利于理解,我們就實際的寫點中看不中用的代碼輔助學習。

怪物橫行的世界,總歸需要點超級人物來擺平。

我們把一個“超人”作為一個類,


1.  class  Superman  {}

我們可以想象,一個超人誕生的時候肯定擁有至少一個超能力,這個超能力也可以抽象為一個對象,為這個對象定義一個描述他的類吧。一個超能力肯定有多種屬性、(操作)方法,這個盡情的想象,但是目前我們先大致定義一個只有屬性的“超能力”,至于能干啥,我們以后再豐富:


 class  Power  {
 /**
   * 能力值
   */
 protected $ability;

 /**
  * 能力范圍或距離
  */
 protected $range;

 public  function __construct($ability, $range)
 {
   $this->ability = $ability;
   $this->range = $range;
  }
 }

這時候我們回過頭,修改一下之前的“超人”類,讓一個“超人”創(chuàng)建的時候被賦予一個超能力:


class  Superman
{
 protected $power;
 public  function __construct()
  {
    $this->power =  new  Power(999,  100);
  }
}

這樣的話,當我們創(chuàng)建一個“超人”實例的時候,同時也創(chuàng)建了一個“超能力”的實例,但是,我們看到了一點,“超人”和“超能力”之間不可避免的產(chǎn)生了一個依賴。

所謂“依賴”,就是 “我若依賴你,我就不能離開你”。

在一個貫徹面向?qū)ο缶幊痰捻椖恐校@樣的依賴隨處可見。少量的依賴并不會有太過直觀的影響,我們隨著這個例子逐漸鋪開,讓大家慢慢意識到,當依賴達到一個量級時,是怎樣一番噩夢般的體驗。當然,我也會自然而然的講述如何解決問題。

一堆亂麻 —— 可怕的依賴

之前的例子中,超能力類實例化后是一個具體的超能力,但是我們知道,超人的超能力是多元化的,每種超能力的方法、屬性都有不小的差異,沒法通過一種類描述完全。我們現(xiàn)在進行修改,我們假設超人可以有以下多種超能力:

  • 飛行,屬性有:飛行速度、持續(xù)飛行時間
  • 蠻力,屬性有:力量值
  • 能量彈,屬性有:傷害值、射擊距離、同時射擊個數(shù)

我們創(chuàng)建了如下類:


1.  class  Flight
2.  {
3.  protected $speed;
4.  protected $holdtime;
5.  public  function __construct($speed, $holdtime)  {}
6.  }

8.  class  Force
9.  {
10.  protected $force;
11.  public  function __construct($force)  {}
12.  }

14.  class  Shot
15.  {
16.  protected $atk;
17.  protected $range;
18.  protected $limit;
19.  public  function __construct($atk, $range, $limit)  {}
20.  }

*為了省事兒我沒有詳細寫出 __construct() 這個構造函數(shù)的全部,只寫了需要傳遞的參數(shù)。

好了,這下我們的超人有點“忙”了。在超人初始化的時候,我們會根據(jù)需要來實例化其擁有的超能力嗎,大致如下:


1.  class  Superman
2.  {
3.  protected $power;

5.  public  function __construct()
6.  {
7.  $this->power =  new  Fight(9,  100);
8.  // $this->power = new Force(45);
9.  // $this->power = new Shot(99, 50, 2);
10.  /*
11.  $this->power = array(
12.  new Force(45),
13.  new Shot(99, 50, 2)
14.  );
15.  */
16.  }
17.  }

我們需要自己手動的在構造函數(shù)內(nèi)(或者其他方法里)實例化一系列需要的類,這樣并不好??梢韵胂?,假如需求變更(不同的怪物橫行地球),需要更多的有針對性的 新的 超能力,或者需要 變更 超能力的方法,我們必須 重新改造 超人。換句話說就是,改變超能力的同時,我還得重新制造個超人。效率太低了!新超人還沒創(chuàng)造完成世界早已被毀滅。

這時,靈機一動的人想到:為什么不可以這樣呢?超人的能力可以被隨時更換,只需要添加或者更新一個芯片或者其他裝置啥的(想到鋼鐵俠沒)。這樣的話就不要整個重新來過了。

對,就是這樣的。

我們不應該手動在 “超人” 類中固化了他的 “超能力” 初始化的行為,而轉由外部負責,由外部創(chuàng)造超能力模組、裝置或者芯片等(我們后面統(tǒng)一稱為 “模組”),植入超人體內(nèi)的某一個接口,這個接口是一個既定的,只要這個 “模組” 滿足這個接口的裝置都可以被超人所利用,可以提升、增加超人的某一種能力。這種由外部負責其依賴需求的行為,我們可以稱其為 “控制反轉(IoC)”。

工廠模式,依賴轉移!

當然,實現(xiàn)控制反轉的方法有幾種。在這之前,不如我們先了解一些好玩的東西。

我們可以想到,組件、工具(或者超人的模組),是一種可被生產(chǎn)的玩意兒,生產(chǎn)的地方當然是 “工廠(Factory)”,于是有人就提出了這樣一種模式: 工廠模式。

工廠模式,顧名思義,就是一個類所依賴的外部事物的實例,都可以被一個或多個 “工廠” 創(chuàng)建的這樣一種開發(fā)模式,就是 “工廠模式”。

我們?yōu)榱私o超人制造超能力模組,我們創(chuàng)建了一個工廠,它可以制造各種各樣的模組,且僅需要通過一個方法:


1.  class  SuperModuleFactory
2.  {
3.  public  function makeModule($moduleName, $options)
4.  {
5.  switch  ($moduleName)  {
6.  case  'Fight':  return  new  Fight($options[0], $options[1]);
7.  case  'Force':  return  new  Force($options[0]);
8.  case  'Shot':  return  new  Shot($options[0], $options[1], $options[2]);
9.  }
10.  }
11.  }

這時候,超人 創(chuàng)建之初就可以使用這個工廠!

1.  class  Superman
2.  {
3.  protected $power;

5.  public  function __construct()
6.  {
7.  // 初始化工廠
8.  $factory =  new  SuperModuleFactory;

10.  // 通過工廠提供的方法制造需要的模塊
11.  $this->power = $factory->makeModule('Fight',  [9,  100]);
12.  // $this->power = $factory->makeModule('Force', [45]);
13.  // $this->power = $factory->makeModule('Shot', [99, 50, 2]);
14.  /*
15.  $this->power = array(
16.  $factory->makeModule('Force', [45]),
17.  $factory->makeModule('Shot', [99, 50, 2])
18.  );
19.  */
20.  }
21.  }

可以看得出,我們不再需要在超人初始化之初,去初始化許多第三方類,只需初始化一個工廠類,即可滿足需求。但這樣似乎和以前區(qū)別不大,只是沒有那么多 new 關鍵字。其實我們稍微改造一下這個類,你就明白,工廠類的真正意義和價值了。


1.  class  Superman
2.  {
3.  protected $power;

5.  public  function __construct(array $modules)
6.  {
7.  // 初始化工廠
8.  $factory =  new  SuperModuleFactory;

10.  // 通過工廠提供的方法制造需要的模塊
11.  foreach  ($modules as $moduleName => $moduleOptions)  {
12.  $this->power[]  = $factory->makeModule($moduleName, $moduleOptions);
13.  }
14.  }
15.  }

17.  // 創(chuàng)建超人
18.  $superman =  new  Superman([
19.  'Fight'  =>  [9,  100],  
20.  'Shot'  =>  [99,  50,  2]
21.  ]);

現(xiàn)在修改的結果令人滿意?,F(xiàn)在,“超人” 的創(chuàng)建不再依賴任何一個 “超能力” 的類,我們?nèi)缛粜薷牧嘶蛘咴黾恿诵碌某芰?,只需要針對修?SuperModuleFactory 即可。擴充超能力的同時不再需要重新編輯超人的類文件,使得我們變得很輕松。但是,這才剛剛開始。

再進一步!IoC 容器的重要組成 —— 依賴注入!

由 “超人” 對 “超能力” 的依賴變成 “超人” 對 “超能力模組工廠” 的依賴后,對付小怪獸們變得更加得心應手。但這也正如你所看到的,依賴并未解除,只是由原來對多個外部的依賴變成了對一個 “工廠” 的依賴。假如工廠出了點麻煩,問題變得就很棘手。

其實大多數(shù)情況下,工廠模式已經(jīng)足夠了。工廠模式的缺點就是:接口未知(即沒有一個很好的契約模型,關于這個我馬上會有解釋)、產(chǎn)生對象類型單一??傊褪?,還是不夠靈活。雖然如此,工廠模式依舊十分優(yōu)秀,并且適用于絕大多數(shù)情況。不過我們?yōu)榱酥v解后面的 依賴注入 ,這里就先夸大一下工廠模式的缺陷咯。

我們知道,超人依賴的模組,我們要求有統(tǒng)一的接口,這樣才能和超人身上的注入接口對接,最終起到提升超能力的效果。

事實上,我之前說謊了,不僅僅只有一堆小怪獸,還有更多的大怪獸。嘿嘿。額,這時候似乎工廠的生產(chǎn)能力顯得有些不足 —— 由于工廠模式下,所有的模組都已經(jīng)在工廠類中安排好了,如果有新的、高級的模組加入,我們必須修改工廠類(好比增加新的生產(chǎn)線):


1.  class  SuperModuleFactory
2.  {
3.  public  function makeModule($moduleName, $options)
4.  {
5.  switch  ($moduleName)  {
6.  case  'Fight':  return  new  Fight($options[0], $options[1]);
7.  case  'Force':  return  new  Force($options[0]);
8.  case  'Shot':  return  new  Shot($options[0], $options[1], $options[2]);
9.  // case 'more': .......
10.  // case 'and more': .......
11.  // case 'and more': .......
12.  // case 'oh no! its too many!': .......
13.  }
14.  }
15.  }

看到?jīng)]。。。噩夢般的感受!

其實靈感就差一步!你可能會想到更為靈活的辦法!對,下一步就是我們今天的主要配角 —— DI (依賴注入)

由于對超能力模組的需求不斷增大,我們需要集合整個世界的高智商人才,一起解決問題,不應該僅僅只有幾個工廠壟斷負責。不過高智商人才們都非常自負,認為自己的想法是對的,創(chuàng)造出的超能力模組沒有統(tǒng)一的接口,自然而然無法被正常使用。這時我們需要提出一種契約,這樣無論是誰創(chuàng)造出的模組,都符合這樣的接口,自然就可被正常使用。


1.  interface  SuperModuleInterface
2.  {
3.  /**
4.  * 超能力激活方法
5.  *
6.  * 任何一個超能力都得有該方法,并擁有一個參數(shù)
7.  *@param array $target 針對目標,可以是一個或多個,自己或他人
8.  */
9.  public  function activate(array $target);
10.  }

上文中,我們定下了一個接口 (超能力模組的規(guī)范、契約),所有被創(chuàng)造的模組必須遵守該規(guī)范,才能被生產(chǎn)。

其實,這就是 php 中 接口( interface ) 的用處和意義!很多人覺得,為什么 php 需要接口這種東西?難道不是 java 、 C# 之類的語言才有的嗎?這么說,只要是一個正常的面向?qū)ο缶幊陶Z言(雖然 php 可以面向過程),都應該具備這一特性。因為一個 對象(object) 本身是由他的模板或者原型 —— 類 (class) ,經(jīng)過實例化后產(chǎn)生的一個具體事物,而有時候,實現(xiàn)統(tǒng)一種方法且不同功能(或特性)的時候,會存在很多的類(class),這時候就需要有一個契約,讓大家編寫出可以被隨時替換卻不會產(chǎn)生影響的接口。這種由編程語言本身提出的硬性規(guī)范,會增加更多優(yōu)秀的特性。

雖然有些繞,但通過我們接下來的實例,大家會慢慢領會接口帶來的好處。

這時候,那些提出更好的超能力模組的高智商人才,遵循這個接口,創(chuàng)建了下述(模組)類:


1.  /**
2.  * X-超能量
3.  */
4.  class  XPower  implements  SuperModuleInterface
5.  {
6.  public  function activate(array $target)
7.  {
8.  // 這只是個例子。。具體自行腦補
9.  }
10.  }

12.  /**
13.  * 終極炸彈 (就這么俗)
14.  */
15.  class  UltraBomb  implements  SuperModuleInterface
16.  {
17.  public  function activate(array $target)
18.  {
19.  // 這只是個例子。。具體自行腦補
20.  }
21.  }

同時,為了防止有些 “磚家” 自作聰明,或者一些叛徒惡意搗蛋,不遵守契約胡亂制造模組,影響超人,我們對超人初始化的方法進行改造:


1.  class  Superman
2.  {
3.  protected $module;

5.  public  function __construct(SuperModuleInterface $module)
6.  {
7.  $this->module  = $module
8.  }
9.  }

改造完畢!現(xiàn)在,當我們初始化 “超人” 類的時候,提供的模組實例必須是一個 SuperModuleInterface 接口的實現(xiàn)。否則就會提示錯誤。

正是由于超人的創(chuàng)造變得容易,一個超人也就不需要太多的超能力,我們可以創(chuàng)造多個超人,并分別注入需要的超能力模組即可。這樣的話,雖然一個超人只有一個超能力,但超人更容易變多,我們也不怕怪獸啦!

現(xiàn)在有人疑惑了,你要講的 依賴注入 呢?

其實,上面講的內(nèi)容,正是依賴注入。

什么叫做 依賴注入?

本文從開頭到現(xiàn)在提到的一系列依賴,只要不是由內(nèi)部生產(chǎn)(比如初始化、構造函數(shù) __construct 中通過工廠方法、自行手動 new 的),而是由外部以參數(shù)或其他形式注入的,都屬于 依賴注入(DI) 。是不是豁然開朗?事實上,就是這么簡單。下面就是一個典型的依賴注入:

1.  // 超能力模組
2.  $superModule =  new  XPower;

4.  // 初始化一個超人,并注入一個超能力模組依賴
5.  $superMan =  new  Superman($superModule);

關于依賴注入這個本文的主要配角,也就這么多需要講的。理解了依賴注入,我們就可以繼續(xù)深入問題。慢慢走近今天的主角……

更為先進的工廠 —— IoC 容器!

剛剛列了一段代碼:


1.  $superModule =  new  XPower;

3.  $superMan =  new  Superman($superModule);

讀者應該看出來了,手動的創(chuàng)建了一個超能力模組、手動的創(chuàng)建超人并注入了剛剛創(chuàng)建超能力模組。呵呵,手動。

現(xiàn)代社會,應該是高效率的生產(chǎn),干凈的車間,完美的自動化裝配。

一群怪獸來了,如此低效率產(chǎn)出超人是不現(xiàn)實,我們需要自動化 —— 最多一條指令,千軍萬馬來相見。我們需要一種高級的生產(chǎn)車間,我們只需要向生產(chǎn)車間提交一個腳本,工廠便能夠通過指令自動化生產(chǎn)。這種更為高級的工廠,就是工廠模式的升華 —— IoC 容器。


1.  class  Container
2.  {
3.  protected $binds;

5.  protected $instances;

7.  public  function bind($abstract, $concrete)
8.  {
9.  if  ($concrete instanceof  Closure)  {
10.  $this->binds[$abstract]  = $concrete;
11.  }  else  {
12.  $this->instances[$abstract]  = $concrete;
13.  }
14.  }

16.  public  function make($abstract, $parameters =  [])
17.  {
18.  if  (isset($this->instances[$abstract]))  {
19.  return $this->instances[$abstract];
20.  }

22.  array_unshift($parameters, $this);

24.  return call_user_func_array($this->binds[$abstract], $parameters);
25.  }
26.  }

這時候,一個十分粗糙的容器就誕生了?,F(xiàn)在的確很簡陋,但不妨礙我們進一步提升他。先著眼現(xiàn)在,看看這個容器如何使用吧!


1.  // 創(chuàng)建一個容器(后面稱作超級工廠)
2.  $container =  new  Container;

4.  // 向該 超級工廠 添加 超人 的生產(chǎn)腳本
5.  $container->bind('superman',  function($container, $moduleName)  {
6.  return  new  Superman($container->make($moduleName));
7.  });

9.  // 向該 超級工廠 添加 超能力模組 的生產(chǎn)腳本
10.  $container->bind('xpower',  function($container)  {
11.  return  new  XPower;
12.  });

14.  // 同上
15.  $container->bind('ultrabomb',  function($container)  {
16.  return  new  UltraBomb;
17.  });

19.  // ******************  華麗麗的分割線  **********************
20.  // 開始啟動生產(chǎn)
21.  $superman_1 = $container->make('superman',  ['xpower']);
22.  $superman_2 = $container->make('superman',  ['ultrabomb']);
23.  $superman_3 = $container->make('superman',  ['xpower']);
24.  // ...隨意添加

看到?jīng)]?通過最初的 綁定(bind) 操作,我們向 超級工廠 注冊了一些生產(chǎn)腳本,這些生產(chǎn)腳本在生產(chǎn)指令下達之時便會執(zhí)行。發(fā)現(xiàn)沒有?我們徹底的解除了 超人 與 超能力模組 的依賴關系,更重要的是,容器類也絲毫沒有和他們產(chǎn)生任何依賴!我們通過注冊、綁定的方式向容器中添加一段可以被執(zhí)行的回調(diào)(可以是匿名函數(shù)、非匿名函數(shù)、類的方法)作為生產(chǎn)一個類的實例的 腳本 ,只有在真正的 生產(chǎn)(make) 操作被調(diào)用執(zhí)行時,才會觸發(fā)。

這樣一種方式,使得我們更容易在創(chuàng)建一個實例的同時解決其依賴關系,并且更加靈活。當有新的需求,只需另外綁定一個“生產(chǎn)腳本”即可。

實際上,真正的 IoC 容器更為高級。我們現(xiàn)在的例子中,還是需要手動提供超人所需要的模組參數(shù),但真正的 IoC 容器會根據(jù)類的依賴需求,自動在注冊、綁定的一堆實例中搜尋符合的依賴需求,并自動注入到構造函數(shù)參數(shù)中去。Laravel 框架的服務容器正是這么做的。實現(xiàn)這種功能其實理論上并不麻煩,但我并不會在本文中寫出,因為……我懶得寫。

不過我告訴大家,這種自動搜尋依賴需求的功能,是通過 反射(Reflection) 實現(xiàn)的,恰好的,php 完美的支持反射機制!關于反射,php 官方文檔有詳細的資料,并且中文翻譯基本覆蓋,足夠?qū)W習和研究!

http://php.net/manual/zh/book.reflection.php

現(xiàn)在,到目前為止,我們已經(jīng)不再懼怕怪獸們了。高智商人才集思廣益,井井有條,根據(jù)接口契約創(chuàng)造規(guī)范的超能力模組。超人開始批量產(chǎn)出。最終,人人都是超人,你也可以是哦
stuck_out_tongue_closed_eyes

!

回歸正常世界。我們開始重新審視 laravel 的核心。

現(xiàn)在,我們開始慢慢解讀 laravel 的核心。其實,laravel 的核心就是一個 IoC 容器,也恰好是我之前所說的高級的 IoC 容器。

可以說,laravel 的核心本身十分輕量,并沒有什么很神奇很實質(zhì)性的應用功能。很多人用到的各種功能模塊比如 Route(路由)Eloquent ORM(數(shù)據(jù)庫 ORM 組件)、Request and Response(請求和響應)等等等等,實際上都是與核心無關的類模塊提供的,這些類從注冊到實例化,最終被你所使用,其實都是 laravel 的服務容器負責的。

我們以大家最常見的 Route 類作為例子。大家可能經(jīng)常見到路由定義是這樣的:


1.  Route::get('/',  function()  {
2.  // bla bla bla...
3.  });

實際上, Route 類被定義在這個命名空間:Illuminate\Routing\Router,文件 vendor/laravel/framework/src/Illuminate/Routing/Router.php。

我們通過打開發(fā)現(xiàn),這個類的這一系列方法,如 get,post,any 等都不是靜態(tài)(static)方法,這是怎么一回事兒?不要急,我們繼續(xù)。

服務提供者

我們在前文介紹 IoC 容器的部分中,提到了,一個類需要綁定、注冊至容器中,才能被“制造”。

對,一個類要被容器所能夠提取,必須要先注冊至這個容器。既然 laravel 稱這個容器叫做服務容器,那么我們需要某個服務,就得先注冊、綁定這個服務到容器,那么提供服務并綁定服務至容器的東西,就是 服務提供者(ServiceProvider)

雖然,綁定一個類到容器不一定非要通過 服務提供者(ServiceProvider)

但是,我們知道,有時候我們的類、模塊會有需要其他類和組件的情況,為了保證初始化階段不會出現(xiàn)所需要的模塊和組件沒有注冊的情況,laravel 將注冊和初始化行為進行拆分,注冊的時候就只能注冊,初始化的時候就是初始化。拆分后的產(chǎn)物就是現(xiàn)在的 服務提供者。

服務提供者主要分為兩個部分,register(注冊)boot(引導、初始化),具體參考文檔。register 負責進行向容器注冊“腳本”,但要注意注冊部分不要有對未知事物的依賴,如果有,就要移步至 boot 部分。

Facade

我們現(xiàn)在解答之前關于 Route 的方法為何能以靜態(tài)方法訪問的問題。實際上這個問題文檔上有寫,簡單說來就是模擬一個類,提供一個靜態(tài)魔術方法__callStatic,并將該靜態(tài)方法映射到真正的方法上。

我們使用的 Route 類實際上是 Illuminate\Support\Facades\Route 通過 class_alias() 函數(shù)創(chuàng)造的 別名 而已,這個類被定義在文件 vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php

我們打開文件一看……誒?怎么只有這么簡單的一段代碼呢?


1.  <?php namespace  Illuminate\Support\Facades;

3.  /**
4.  * @see \Illuminate\Routing\Router
5.  */
6.  class  Route  extends  Facade  {

8.  /**
9.  * Get the registered name of the component.
10.  *
11.  * @return string
12.  */
13.  protected  static  function getFacadeAccessor()
14.  {
15.  return  'router';
16.  }

18.  }

其實仔細看,會發(fā)現(xiàn)這個類繼承了一個叫做 Facade 的類,到這里謎底差不多要解開了。

上述簡單的定義中,我們看到了 getFacadeAccessor 方法返回了一個 route,這是什么意思呢?事實上,這個值被一個 ServiceProvider 注冊過,大家應該知道注冊了個什么,當然是那個真正的路由類!

有人會問,F(xiàn)acade 是怎么實現(xiàn)的。我并不想說得太細,一個是我懶,另一個原因就是,自己發(fā)現(xiàn)一些東西更容易理解,并不容易忘記。很多細節(jié)我已經(jīng)說了,建議大家自行去研究。

至此,我們已經(jīng)講的差不多了。

和平!我們該總結總結了!

無論如何,世界和平了。

這里要總結的內(nèi)容就是,其實很多事情并不復雜,怕的是復雜的理論內(nèi)容。我覺得很多東西一旦想通也就那么回事兒。很多人覺得 laravel 這不好那不好、這里難哪里難,我只能說,laravel 的確不是一流和優(yōu)秀的框架,說 laravel 是一流、優(yōu)秀的框架的人,不是 laravel 的粉絲那么就是跟風炒作。Laravel 最大的特點和優(yōu)秀之處就是使用了很多 php 比較新(實際上并不新)的概念和技術(也就一堆語法糖)而已。因此 laravel 的確符合一個適宜學習的框架。Laravel 的構思的確和其他框架有很大不同,這也要求學習他的人必須熟練 php,并 基礎扎實!如果你覺得學 laravel 框架十分困難,那么原因只有一個:你 php 基礎不好。

另外,善于利用命名空間和面向?qū)ο蟮闹T多特性,去追尋一些東西,你會發(fā)現(xiàn),原來這一切這么容易。
原文地址:https://www.insp.top/learn-laravel-container

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容