摘要:依賴(lài)注入通過(guò)構(gòu)造注入,函數(shù)調(diào)用或者屬性的設(shè)置來(lái)提供組件的依賴(lài)關(guān)系。這段代碼可以用依賴(lài)注入重構(gòu),從而解耦現(xiàn)在我們通過(guò)外界給予類(lèi)的依賴(lài),而不是讓它自己產(chǎn)生依賴(lài)的對(duì)象。根據(jù)依賴(lài)注入的概念,我們的框架實(shí)現(xiàn)了這些特性。
如何提高自己編寫(xiě)代碼的能力呢?我們首先想到的是閱讀學(xué)習(xí)優(yōu)秀的開(kāi)源項(xiàng)目,然后寫(xiě)一個(gè)自己的web框架或類(lèi)庫(kù)組件。作為web開(kāi)發(fā)者,我們通常都是基于面向?qū)ο驩OP來(lái)開(kāi)發(fā)的,所以面向?qū)ο蟮脑O(shè)計(jì)能力或者說(shuō)設(shè)計(jì)模式的運(yùn)用能力尤為重要,當(dāng)然還有開(kāi)發(fā)語(yǔ)言本身特性和基礎(chǔ)的靈活運(yùn)用。
我們可以去閱讀一些優(yōu)秀的開(kāi)源項(xiàng)目,理解里面的代碼設(shè)計(jì),去學(xué)習(xí)和造輪子來(lái)提高自己。
在優(yōu)秀成熟的web framework中,路由和http處理是web框架必不可少的,整個(gè)框架的服務(wù)對(duì)象依賴(lài)解析也是很重要的,有了依賴(lài)注入容器可以實(shí)現(xiàn)類(lèi)很好的解耦。
依賴(lài)注入容器 Dependency Injection Container先來(lái)說(shuō)下什么是依賴(lài)注入,依賴(lài)注入是一種允許我們從硬編碼的依賴(lài)中解耦出來(lái),從而在運(yùn)行時(shí)或者編譯時(shí)能夠修改的軟件設(shè)計(jì)模式(來(lái)自維基百科 Wikipedia)。
依賴(lài)注入通過(guò)構(gòu)造注入,函數(shù)調(diào)用或者屬性的設(shè)置來(lái)提供組件的依賴(lài)關(guān)系。
下面的代碼中有一個(gè) Database 的類(lèi),它需要一個(gè)適配器來(lái)與數(shù)據(jù)庫(kù)交互。我們?cè)跇?gòu)造函數(shù)里實(shí)例化了適配器,從而產(chǎn)生了耦合。這會(huì)使測(cè)試變得很困難,而且 Database 類(lèi)和適配器耦合的很緊密。
adapter = new MySqlAdapter; } } class MysqlAdapter {}
這段代碼可以用依賴(lài)注入重構(gòu),從而解耦
adapter = $adapter; } } class MysqlAdapter {}
現(xiàn)在我們通過(guò)外界給予 Database 類(lèi)的依賴(lài),而不是讓它自己產(chǎn)生依賴(lài)的對(duì)象。我們甚至能用可以接受依賴(lài)對(duì)象參數(shù)的成員函數(shù)來(lái)設(shè)置,或者如果 $adapter 屬性本身是 public的,我們可以直接給它賦值。
根據(jù)依賴(lài)注入的概念,我們的框架實(shí)現(xiàn)了這些特性。
Dependency injection Container基于PSR-11規(guī)范實(shí)現(xiàn),使用了PHP的類(lèi)反射功能,去實(shí)例化類(lèi)定義的對(duì)象依賴(lài)。定義類(lèi)的對(duì)象依賴(lài)包括3種注入實(shí)現(xiàn)方式:構(gòu)造方法注入(Constructor Injection)、setter方法或?qū)傩宰⑷耄⊿etter Injection)、匿名回調(diào)函數(shù)注入,代碼示例如下:
1.構(gòu)造方法注入(Constructor Injection)bar = $bar; } } /*class Bar { }*/ class Bar { public $baz; public function __construct(Baz $baz) { $this->baz = $baz; } } class Baz { } $container = new Container; $container->set(Foo::class)->addArguments(Bar::class); $container->set(Bar::class)->addArguments(Baz::class); $foo = $container->get(Foo::class); var_dump($foo, $foo->bar); var_dump($foo instanceof Foo); // true var_dump($foo->bar instanceof Bar); // true var_dump($foo->bar->baz instanceof Baz); // true2.方法注入(Setter Injection)
model = $model; } } class Model { public $pdo; public function setPdo(PDO $pdo) { $this->pdo = $pdo; } } $container = new Container; $container->set(Controller::class)->addArguments(Model::class); $container->set(Model::class)->addInvokeMethod("setPdo", [PDO::class]); $container->set(PDO::class) ->addArguments(["mysql:dbname=test;host=localhost", "root", "111111"]); $controller = $container->get(Controller::class); var_dump($controller instanceof Controller); // true var_dump($controller->model instanceof Model); // true var_dump($controller->model->pdo instanceof PDO); // true3.匿名回調(diào)函數(shù)注入(Closure callable Injection)
model = $model; } } class Model { public $pdo; public function setPdo(PDO $pdo) { $this->pdo = $pdo; } } $container = new Container; $container->set(Controller::class, function () { $pdo = new PDO("mysql:dbname=test;host=localhost", "root", "111111"); $model = new Model; $model->setPdo($pdo); return new Controller($model); }); $controller = $container->get(Controller::class); var_dump($controller instanceof Controller); // true var_dump($controller->model instanceof Model); // true var_dump($controller->model->pdo instanceof PDO); // true自動(dòng)裝配(auto wiring)
bar = $bar; $this->baz = $baz; } } class Bar { /** * @var AutoWiringBam */ public $bam; /** * Construct. * * @param AutoWiringBam $bam */ public function __construct(Bam $bam) { $this->bam = $bam; } } class Baz { // .. } class Bam { // .. } $container = new ContainerBuilder; $container = $container->build(); $foo = $container->get(Foo::class); var_dump($foo instanceof Foo); // true var_dump($foo->bar instanceof Bar); // true var_dump($foo->baz instanceof Baz); // true var_dump($foo->bar->bam instanceof Bam); // true路由 Route
再介紹下路由的使用,route可以使用symfony的http foundation組件來(lái)處理HTTP請(qǐng)求(http messages)。
get("/articles", function () { return "This is articles list"; }); $router->get("/articles/{id:d+}", function ($id) { return "Article id: " . $id; }); /* title為可選參數(shù) */ $router->get("/articles/{id:d+}[/{title}]", function ($id, $title) { return "Article id: " . $id . ", title: " . $title; }); /*匹配處理路由組*/ $router->group("/articles", function () use ($router) { $router->get("/list", function() { return "This is articles list"; }); $router->get("/detail", function ($id, $title) { return "Article detail id: " . $id . ", title: " . $title; }); }); $request = new Request(); $routeHandler = $router->getRouteHandler(); $response = $routeHandler->handle($request); echo $response;
其它的ORM、cache、filesystem、session、validation等組件可以使用composer來(lái)由用戶(hù)自由擴(kuò)展。
項(xiàng)目地址 https://github.com/parvinShi/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/30992.html
摘要:什么是單頁(yè)面應(yīng)用單頁(yè)面應(yīng)用是指用戶(hù)在瀏覽器加載單一的頁(yè)面,后續(xù)請(qǐng)求都無(wú)需再離開(kāi)此頁(yè)目標(biāo)旨在用為用戶(hù)提供了更接近本地移動(dòng)或桌面應(yīng)用程序的體驗(yàn)。流程第一次請(qǐng)求時(shí),將導(dǎo)航頁(yè)傳輸?shù)娇蛻?hù)端,其余請(qǐng)求通過(guò)獲取數(shù)據(jù)實(shí)現(xiàn)數(shù)據(jù)的傳輸通過(guò)或遠(yuǎn)程過(guò)程調(diào)用。 什么是單頁(yè)面應(yīng)用(SPA)? 單頁(yè)面應(yīng)用(SPA)是指用戶(hù)在瀏覽器加載單一的HTML頁(yè)面,后續(xù)請(qǐng)求都無(wú)需再離開(kāi)此頁(yè) 目標(biāo):旨在用為用戶(hù)提供了更接近本地...
摘要:什么是單頁(yè)面應(yīng)用單頁(yè)面應(yīng)用是指用戶(hù)在瀏覽器加載單一的頁(yè)面,后續(xù)請(qǐng)求都無(wú)需再離開(kāi)此頁(yè)目標(biāo)旨在用為用戶(hù)提供了更接近本地移動(dòng)或桌面應(yīng)用程序的體驗(yàn)。流程第一次請(qǐng)求時(shí),將導(dǎo)航頁(yè)傳輸?shù)娇蛻?hù)端,其余請(qǐng)求通過(guò)獲取數(shù)據(jù)實(shí)現(xiàn)數(shù)據(jù)的傳輸通過(guò)或遠(yuǎn)程過(guò)程調(diào)用。 什么是單頁(yè)面應(yīng)用(SPA)? 單頁(yè)面應(yīng)用(SPA)是指用戶(hù)在瀏覽器加載單一的HTML頁(yè)面,后續(xù)請(qǐng)求都無(wú)需再離開(kāi)此頁(yè) 目標(biāo):旨在用為用戶(hù)提供了更接近本地...
摘要:如何構(gòu)建一個(gè)自己的框架為什么我們要去構(gòu)建一個(gè)自己的框架可能絕大多數(shù)的人都會(huì)說(shuō)市面上已經(jīng)那么多的框架了,還造什么輪子。 showImg(https://segmentfault.com/img/bVNg9F?w=500&h=500); 如何構(gòu)建一個(gè)自己的PHP框架 為什么我們要去構(gòu)建一個(gè)自己的PHP框架?可能絕大多數(shù)的人都會(huì)說(shuō)市面上已經(jīng)那么多的框架了,還造什么輪子?。我的觀點(diǎn)造輪子不是目...
摘要:可以為服務(wù)提供者的方法設(shè)置類(lèi)型提示。方法將在所有其他服務(wù)提供者均已注冊(cè)之后調(diào)用。所有服務(wù)提供者都在配置文件中注冊(cè)。可以選擇推遲服務(wù)提供者的注冊(cè),直到真正需要注冊(cè)綁定時(shí),這樣可以提供應(yīng)用程序的性能。 本文最早發(fā)布于 Rootrl的Blog 導(dǎo)言 Laravel是一款先進(jìn)的現(xiàn)代化框架,里面有一些概念非常重要。在上手Laravel之前,我認(rèn)為先弄懂這些概念是很有必要的。你甚至需要重溫下PHP...
閱讀 1714·2021-11-22 15:33
閱讀 2085·2021-10-08 10:04
閱讀 3543·2021-08-27 13:12
閱讀 3419·2019-08-30 13:06
閱讀 1467·2019-08-29 16:43
閱讀 1392·2019-08-29 16:40
閱讀 786·2019-08-29 16:15
閱讀 2746·2019-08-29 14:13