參考資料:
laravel底層核心程式碼分析之核心概念講解
PHP控制反轉(IOC)和依賴注入(DI)
閉包匿名函式,還在傻傻搞不清楚嗎?
Laravel框架核心
優點
- 整合了composer
- 實現了依賴注入,更好的管理類的依賴關係,方便擴充套件(相對於MVC模式)
- 高階特性:控制檯console,事件event,佇列queue,中介軟體middleware,門面模式facades
- 核心概念:服務容器 serviceProvider
缺點及優化
缺點
- 載入檔案太多,訪問速度慢
優化
- 快取配置檔案
- 去掉不必要的載入檔案(主要是serviceProvider)
- 開啟Opcache
框架啟動流程(生命週期)
- 引用自動載入檔案
- 生成服務容器
1) 註冊基礎的bingings
2) 通過bind註冊服務容器,事件,路由,日誌服務
3) 通過bind繫結介面 - 獲取Request物件
- 邏輯處理
1) 解析啟動項(基礎服務)如路由,異常處理,門面,服務容器
2) 通過管道模式,用中介軟體過濾使用者請求,處理業務邏輯 - 返回Response物件
知識點
單例模式,觀察者模式,管道模式
依賴注入,匿名函式,反射
預定義介面ArrayAccess
控制反轉和依賴注入
控制反轉 IOC(inversion of control)
將元件間的依賴關係從程式內部提到外部來管理
解釋:不在A類中直接新建B類例項,而是通過IOC容器將B類的例項傳給A
依賴注入 DI(dependency injection)
將元件的依賴通過外部以引數或其他形式注入
示例:
class DbMysql
{
public function query(){}
}
class IOC
{
public $db;
public function __construct($dbMysql)
{
$this->db = $dbMysql;
}
public function action()
{
$this->db->query();
}
}
$db = new DbMysql();
$c = new IOC($db);
$c->action();
IOC類中不需要例項化DbMysql,而是將DbMysql的例項作為引數傳入,僅呼叫DbMysql的方法。這種模式就是依賴注入。
將B類的例項化動作提出到IOC類的外面,就叫做控制反轉。
PHP的反射機制
在PHP執行時,擴充套件分析程式,匯出或提出關於類,方法,屬性,引數的詳細資訊,這種動態獲取和呼叫資訊的功能稱為反射API。
class A
{
public function __construct(B $b)
{
}
}
class B
{
}
//獲取類的反射資訊(所有資訊)
$reflector = new ReflectionClass('A');
//獲取建構函式
$constructor = $reflector->getConstructor();
//獲取建構函式引數
$dependencies = $constructor->getParameters();
//獲取依賴的類名
foreach ($dependencies as $dependency){
if(!is_null($dependency->getClass())){
$classname = $dependency->getClass()->name;
$p[] = new $classname();
}
}
//從給出的引數建立一個新的類例項
$a = $reflector->newInstanceArgs($p);
如果B類也有依賴的類,則需要通過遞迴建立
<?php
class A
{
public function __construct(B $b)
{
$this->b = $b;
}
public function getB()
{
$this->b->bMethod();
}
}
class B
{
public function __construct(C $c,D $d)
{
$this->c = $c;
$this->d = $d;
}
public function bMethod()
{
echo "我是B中的方法bMethod()";
}
}
class C{
public function __construct()
{
}
public function cMethod(){
echo "我是C中的方法cMethod()";
}
}
class D{
public function __construct()
{
}
public function dMethod(){
echo "我是D中的方法dMethod()";
}
}
class Ioc
{
protected $instances = [];
public function __construct()
{
}
public function getInstance($classname){
$reflector = new ReflectionClass($classname);
$constructor = $reflector->getConstructor();
$dependencies = $constructor->getParameters();
if(!$dependencies){
return new $classname();
}
foreach ($dependencies as $dependency){
if(!is_null($dependency->getClass())){
$instances[] = $this->make($dependency->getClass()->name);
}
}
return $reflector->newInstanceArgs($instances);
}
public function make($classname){
return $this->getInstance($classname);
}
}
$ioc = new Ioc();
$a = $ioc->make('A');
$a->getB();
總結
PHP程式執行的本質:包含檔案,獲取例項化物件。
傳統框架:通過include/require來管理類的依賴關係。
Laravel:通過namespace和use,實現了自動載入機制,找到類所在檔案,然後通過反射獲取類的例項化物件。
學習資料:
laravel底層核心程式碼分析之匿名函式
閉包匿名函式,還在傻傻搞不清楚嗎?
匿名函式
回撥函式
呼叫函式的時候將另一個函式作為引數傳遞到呼叫的函式中,而不是傳遞一個普通的變數作為引數
使用回撥函式是為了可以將一段自己定義的功能傳到函式內部使用
function test($v){
return $v * $v;
}
$a = array(1, 2, 3);
print_r(array_map("test", $a)); //[1, 4, 9]
匿名函式
沒有名字的函式就是匿名函式
1.普通使用
$func = function($str){
echo $str;
};
$func('Hello');
2.使用use傳遞外部變數
$b = "World";
$func = function($str) use($b){
echo $str. " ". $b;
};
$func("Hello");
閉包(closures)
php的閉包(Closure)也就是匿名函式。是PHP5.3引入的。
閉包函式就是能夠讀取其他函式內部變數的函式
閉包 = 匿名函式 + use
function getMoney($a, $b){
return function($p) use ($a, $b){
echo $p. '-'. $a. '-'. $b;
};
}
$closure = getMoney('1', '2');
var_dump($closure instanceof Closure);//true
$closure('test');//test-1-2
實際應用
1. 當做回撥函式
src/Illuminate/Routing/Router.php
public function gatherRouteMiddleware(Route $route)
{
$middleware = collect($route->gatherMiddleware())->map(function ($name) {
return (array) MiddlewareNameResolver::resolve($name, $this->middleware, $this->middlewareGroups);
})->flatten();
return $this->sortMiddleware($middleware);
}
2. 當做閉包
src/Illuminate/Container/Container.php
//建立
protected function getClosure($abstract, $concrete)
{
return function ($container, $parameters = []) use ($abstract, $concrete) {
if ($abstract == $concrete) {
return $container->build($concrete);
}
return $container->make($concrete, $parameters);
};
}
//繫結
function bind($abstract, $concrete = null, $shared = false)
{
...
if (! $concrete instanceof Closure) {
$concrete = $this->getClosure($abstract, $concrete);
}
...
}
//呼叫
public function build($concrete)
{
if ($concrete instanceof Closure) {
return $concrete($this, $this->getLastParameterOverride());
}
...
}