如何提升本身編寫代碼的能力呢?咱們首先想到的是閱讀學習優秀的開源項目,而後寫一個本身的web框架或類庫組件。做爲web開發者,咱們一般都是基於面向對象OOP來開發的,因此面向對象的設計能力或者說設計模式的運用能力尤其重要,固然還有開發語言自己特性和基礎的靈活運用。php
咱們能夠去閱讀一些優秀的開源項目,理解裏面的代碼設計,去學習和造輪子來提升本身。mysql
在優秀成熟的web framework中,路由和http處理是web框架必不可少的,整個框架的服務對象依賴解析也是很重要的,有了依賴注入容器能夠實現類很好的解耦。git
先來講下什麼是依賴注入,依賴注入是一種容許咱們從硬編碼的依賴中解耦出來,從而在運行時或者編譯時可以修改的軟件設計模式(來自維基百科 Wikipedia)。
依賴注入經過構造注入,函數調用或者屬性的設置來提供組件的依賴關係。github
下面的代碼中有一個 Database 的類,它須要一個適配器來與數據庫交互。咱們在構造函數裏實例化了適配器,從而產生了耦合。這會使測試變得很困難,並且 Database 類和適配器耦合的很緊密。web
<?php namespace Database; class Database { protected $adapter; public function __construct() { $this->adapter = new MySqlAdapter; } } class MysqlAdapter {}
這段代碼能夠用依賴注入重構,從而解耦sql
<?php namespace Database; class Database { protected $adapter; public function __construct(MySqlAdapter $adapter) { $this->adapter = $adapter; } } class MysqlAdapter {}
如今咱們經過外界給予 Database 類的依賴,而不是讓它本身產生依賴的對象。咱們甚至能用能夠接受依賴對象參數的成員函數來設置,或者若是 $adapter 屬性自己是 public的,咱們能夠直接給它賦值。數據庫
根據依賴注入的概念,咱們的框架實現了這些特性。設計模式
Dependency injection Container基於PSR-11規範實現,使用了PHP的類反射功能,去實例化類定義的對象依賴。定義類的對象依賴包括3種注入實現方式:構造方法注入(Constructor Injection)、setter方法或屬性注入(Setter Injection)、匿名回調函數注入,代碼示例以下:session
<?php declare(strict_types=1); namespace Examples; use Eagle\DI\Container; class Foo { /** * @var \Examples\Bar */ public $bar; /** * Foo constructor. * @param \Examples\Bar $bar */ public function __construct(Bar $bar) { $this->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); // true
<?php declare(strict_types=1); namespace Examples; require 'vendor/autoload.php'; use Eagle\DI\Container; class Controller { public $model; public function __construct(Model $model) { $this->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); // true
<?php declare(strict_types=1); namespace Examples; require 'vendor/autoload.php'; use Eagle\DI\Container; class Controller { public $model; public function __construct(Model $model) { $this->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
<?php declare(strict_types=1); namespace AutoWiring; require 'vendor/autoload.php'; use Eagle\DI\ContainerBuilder; class Foo { /** * @var \AutoWiring\Bar */ public $bar; /** * @var \AutoWiring\Baz */ public $baz; /** * Construct. * * @param \AutoWiring\Bar $bar * @param \AutoWiring\Baz $baz */ public function __construct(Bar $bar, Baz $baz) { $this->bar = $bar; $this->baz = $baz; } } class Bar { /** * @var \AutoWiring\Bam */ public $bam; /** * Construct. * * @param \AutoWiring\Bam $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可使用symfony的http foundation組件來處理HTTP請求(http messages)。composer
<?php require 'vendor/autoload.php'; use Eagle\Route\Router; use Symfony\Component\HttpFoundation\Request; $router = new Router(); $router->get('/articles', function () { return 'This is articles list'; }); $router->get('/articles/{id:\d+}', function ($id) { return 'Article id: ' . $id; }); /* title爲可選參數 */ $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來由用戶自由擴展。