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

資訊專欄INFORMATION COLUMN

Yii2中的依賴注入

harriszh / 2761人閱讀

摘要:構造器注入實現特定參數的構造函數,在新建對象時傳入所依賴類型的對象。

基本概念

1.依賴倒置(反轉)原則(DIP):一種軟件架構設計的原則(抽象概念,是一種思想)
在面向對象編程領域中,依賴反轉原則(Dependency inversion principle,DIP)是指一種特定的解耦(傳統的依賴關系創建在高層次上,而具體的策略設置則應用在低層次的模塊上)形式,使得高層次的模塊不依賴于低層次的模塊的實現細節,依賴關系被顛倒(反轉),從而使得低層次模塊依賴于高層次模塊的需求抽象。

該原則規定:

1.高層次的模塊不應該依賴于低層次的模塊,兩者都應該依賴于抽象接口。

2.抽象接口不應該依賴于具體實現。而具體實現則應該依賴于抽象接口。

在上圖中,高層對象A依賴于底層對象B的實現;圖2中,把高層對象A對底層對象的需求抽象為一個接口A,底層對象B實現了接口A,這就是依賴反轉。

該原則顛倒了一部分人對于面向對象設計的認識方式。如高層次和低層次對象都應該依賴于相同的抽象接口。它轉換了依賴,高層模塊不依賴于低層模塊的實現,而低層模塊依賴于高層模塊定義的接口。通俗的講,就是高層模塊定義接口,低層模塊負責實現。

2.控制反轉(IoC):一種反轉流、依賴和接口的方式(DIP的具體實現方式,一種設計原則)
控制反轉(Inversion of Control,縮寫為IoC),是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)。通過控制反轉,對象在被創建的時候,由一個調控系統內所有對象的外界實體,將其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。

它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。

實現控制反轉主要有兩種方式:
1.依賴注入:
2.依賴查找

兩者的區別在于,前者是被動的接收對象,在類A的實例創建過程中即創建了依賴的B對象,通過類型或名稱來判斷將不同的對象注入到不同的屬性中,而后者是主動索取相應類型的對象,獲得依賴對象的時間也可以在代碼中自由控制。

3.依賴注入(DI):IoC的一種實現方式,用來反轉依賴(IoC的具體實現方式)
依賴注入有如下實現方式:

接口注入(Interface Injection):實現特定接口以供外部容器注入所依賴類型的對象。

設值注入(Setter Injection): 實現特定屬性的public set方法,來讓外部容器調用傳入所依賴類型的對象。

構造器注入(Constructor Injection): 實現特定參數的構造函數,在新建對象時傳入所依賴類型的對象。

基于注解 : 基于Java的注解功能,在私有變量前加“@Autowired”等注解,不需要顯式的定義以上三種代碼,便可以讓外部容器傳入對應的對象。該方案相當于定義了public的set方法,但是因為沒有真正的set方法,從而不會為了實現依賴注入導致暴露了不該暴露的接口(因為set方法只想讓容器訪問來注入而并不希望其他依賴此類的對象訪問)。

3.依賴查找(DL):IoC的一種實現方式,用來反轉依賴(IoC的具體實現方式)
依賴查找更加主動,在需要的時候通過調用框架提供的方法來獲取對象,獲取時需要提供相關的配置文件路徑、key等信息來確定獲取對象的狀態

小結
依賴倒置原則(DIP):一種軟件架構設計的原則(抽象概念,一種思想)。
控制反轉(IoC):一種反轉流、依賴和接口的方式(DIP的具體實現方式)。
依賴注入(DI):IoC的一種實現方式,用來反轉依賴(IoC的具體實現方式)。
IoC容器(也稱DI Container):提供了動態地(自動化)創建、注入依賴單元,映射依賴關系等功能,減少了許多代碼量(DI框架)。

需要注意的一些地方
1.控制反轉的層面
在傳統的應用中,程序流程的順序是由開發者主導的,由于IoC,主導權轉移到了框架的手里(因為IoC容器)

2.控制反轉需要解決的問題
查找,生成所需的實例,返回給需要者(因此又叫依賴注入)

3.實現依賴注入的目的
盡管一個類A對它所依賴的類B是如何實現的一無所知,類A依然能夠與類B通信(通過定義一些通用接口)。類B在開發中可能會有多種實現,依賴注入(同時也是IoC)解決的問題就是自動地將這些類B的實現在需要的時候傳遞給類A。

4.如何實現依賴注入
最基本的思路是構造一個獨立的類,它的功能就是統一為其他所有類的依賴生成所需的實例(assembler,類似容器),然后構造并返回這個類

依賴注入的具體實現方式(主要介紹設值注入和構造器注入)

備注:對類A,類B,類C的定義如下
類A (需要通過容器獲取的)
類B (類A的依賴,廣義上的接口)
類C (類B的具體實現)

1.構造器注入

a)在類A的構造器參數列表中定義了該類所有需要被依賴注入的東西(類B)

b)在容器中需要先定義好某個接口(廣義上的interface,即類B)關聯的某個具體實現類(有時還需要配置一些具體參數,即類C),這些容器配置在不同的開發中很可能是不一樣的。通常這些配置會是一個獨立的文件

c)在需要某個類A的時候通過容器來生成而不是直接new

class MovieLister...     (MovieLister相當于類A,MovieFinder相當于類B)
public MovieLister(MovieFinder finder) {
    this.finder = finder;       
}

class ColonMovieFinder...   (這個相當于類c)
public ColonMovieFinder(String filename) {
    this.filename = filename;
}

(這里返回的pico就是IoC容器)
private MutablePicoContainer configureContainer() {
    MutablePicoContainer pico = new DefaultPicoContainer();
    Parameter[] finderParams =  {new ConstantParameter("movies1.txt")};
    //在使用容器前需要先配置,下面的代碼就是對容器的配置
    pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);
    pico.registerComponentImplementation(MovieLister.class);
    return pico;
}

下面是通過容器來獲得類A的過程
public void testWithPico() {
    MutablePicoContainer pico = configureContainer();//獲得一個配置好的容器
    MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);//通過容器來獲得類A
    Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
    assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}

2.setter注入

a)在類A中為所有需要注入的依賴類(類B)創建setter方法

b)在獨立的文件配置類A中的依賴的具體實現(即配置類B的具體實現類C)

c)通過容器生成生成類A

class MovieLister...  (同樣的MovieLister為類A,MovieFinder為類B) 
private MovieFinder finder;
public void setFinder(MovieFinder finder) {
  this.finder = finder;
}

class ColonMovieFinder...  (這個同樣的相當于類C)
public void setFilename(String filename) {
   this.filename = filename;
}


//下面是容器的配置

    
        
            
        
    
    
        
            movies1.txt
        
    



public void testWithSpring() throws Exception {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");//獲得配置好的容器
    MovieLister lister = (MovieLister) ctx.getBean("MovieLister");  //通過容器獲取類A
    Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
    assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
Service Locator

與DI類似,Service Locator也是用來打破依賴的

基本思想
提供一個獨立的類(即Service Locator),它能夠為整個應用提供所需的所有service(也可以理解為component)。

具體實現
1.在類A中,依賴的所有類都是通過Service Locator獲取的

    MovieFinder finder = ServiceLocator.movieFinder();

2.通過配置可以定制在Service Locator中實現如何返回一個特定實例,這個與DI類似

小結
1.實際上可以將Service Locator和DI結合使用,在類A中通過Service Locator獲取依賴,而在Service Locator中則可以通過DI來實現獲取具體的實例(或者將Service Locator與DI互換也可以?)

2.動態的Service Locator:使用一張映射表,通過查表實現(或直接獲?。┚唧w的實例

3.Service Locator與DI 的區別:使用Service Locator時是顯式地調用Locator,而Di并沒有顯式地調用

Yii2中的依賴注入

相關的類:

yiidiContainer 容器

yiidiinstance 容器或Service Locator中的東西: 本質上是對于某一個類實例的引用

yiidiServiceLocator

1.yiidiinstance
主要用在兩個地方:

1.在配置DI容器的時候,使用Instance來引用一個類名,接口名或者是別名(即Instance的id屬性)。因此后續DI容器可以將這個引用解析成相應的對象

2.用在那些使用service locator獲取依賴對象的類中

對于 yiidiInstance:
1.表示的是容器中的內容,代表的是對于實際對象的引用。
2.DI容器可以通過他獲取所引用的實際對象。
3.Instance類僅有的一個屬性id一般表示的是實例的類型(即component ID, class name, interface name or alias name)。

2.yiidiContainer
注意:下面所說的“對象類型”的具體定義為“類名,接口名,別名”
對于yiidiContainer

a) 5個私有屬性(都是數組):$_singletons,$_definitions,$_params,$_reflections,$_dependencies

b) $_singletons // 用于保存單例Singleton對象,以對象類型為鍵

c) $_definitions // 用于保存依賴的定義,以對象類型為鍵

d) $_params // 用于保存構造函數的參數,以對象類型為鍵

e) $_reflections // 用于緩存ReflectionClass對象,以對象類型為鍵

f) $_dependencies // 用于緩存依賴信息,以對象類型為鍵

注意
1.在DI容器中,依賴關系的定義是唯一的。 后定義的同名依賴,會覆蓋前面定義好的依賴。
2.上面的鍵具體就是:帶命名空間的類名,接口名,或者是一個別名
3.對于 $_definitions 數組中的元素,它要么是一個包含了”class” 元素的數組,要么是一個PHP callable, 再要么就是一個具體對象。這就是規范化后的最終結果
4.對于$_singletons數組中的元素,要不就是null(表示還未實例化),要不就是一個具體的實例
5.對于$_params數組中的元素,就是一個數組,包含構造函數的所有參數
6.對于$_reflections數組中的元素,就是一個ReflectionClass對象
7.setter注入可以在實例化后

yiidiContainer使用的具體過程
一個簡單的例子

namespace appmodels;

use yiiaseObject;
use yiidbConnection;
use yiidiContainer;

interface UserFinderInterface
{
    function findUser();
}

class UserFinder extends Object implements UserFinderInterface
{
    public $db;

    public function __construct(Connection $db, $config = [])
    {
        $this->db = $db;
        parent::__construct($config);
    }

    public function findUser()
    {
    }
}

class UserLister extends Object
{
    public $finder;

    public function __construct(UserFinderInterface $finder, $config = [])
    {
        $this->finder = $finder;
        parent::__construct($config);
    }
}

$container = new Container;
$container->set("yiidbConnection", [
    "dsn" => "...",
]);
$container->set("appmodelsUserFinderInterface", [
    "class" => "appmodelsUserFinder",
]);
$container->set("userLister", "appmodelsUserLister");

$lister = $container->get("userLister");

// which is equivalent to:

$db = new yiidbConnection(["dsn" => "..."]);
$finder = new UserFinder($db);
$lister = new UserLister($finder);

1.在類A的構造器參數列表中定義了該類所有需要被依賴注入的東西(類B)

2.注冊依賴:
a)yiidiContainer::set()
b)yiidiContainer::setSinglton()
使用到了$_definitions ,$_params, $_singletons

3.對象的實例化
a)解析依賴信息
yiidiContainer::getDependencies() (會被后續的build()調用)
getDependencies():操作$_reflections與$_dependencies
1.會向$_reflections 和 $_dependencies寫入信息
2.使用PHP的反射機制來獲取類的有關信息,主要就是為了從構造器中獲取依賴信息,會將反射得到的信息寫入$_reflections
3.將從構造器中獲取的依賴信息(即構造函數的參數列表)寫入$_dependencies
4.返回值: 數組[$reflection, $dependencies]

yiidiContainer::resolveDependencies() (同樣的會被后續的build()調用)
resolveDependencies()利用getDependencies()獲得的信息進一步具體處理(遞歸調用)。處理依賴信息, 將依賴信息中保存的Instance實例所引用的類或接口進行實例化。

b)創建實例
yiidiContainer::build()
由getDependencies()獲得第一層依賴
由resolveDependencies()遞歸分析依賴,最終生成所有依賴的實例
$reflection->newInstanceArgs($dependencies);//生成所有依賴后生成這個實例

注意:DI容器只支持 yiibaseObject 類,也就是說如果你想你的類可以放在DI容器里,那么必須繼承自 yiibaseObject 類。

4.獲取依賴實例化對象

yiidiContainer::get()
a)如果是已經實例化的單例,直接返回($_singletons)

b)如果是尚未定義(不存在于$_definition),則說明其實例化沒有依賴,調用build()

c)存在$_definition
    i.$definition為callable,直接調用
    ii.$definition為數組,根據$definition數組中的‘class’,遞歸調用get(),遞歸終止的條件是(當具體實現類就是當前的依賴類時),遞歸結束時調用build()進行實例化
    iii.$definition為對象,直接返回該對象,并將該對象設置為單例
    

setSinglton()類似
public function set($class, $definition = [], array $params = [])
{
    //normalizeDefinition()處理后,返回值要么是一個包含了”class” 元素的數組,要么是一個PHP callable, 再要么就是一個具體對象
    $this->_definitions[$class] = $this->normalizeDefinition($class, $definition);
    $this->_params[$class] = $params;
    unset($this->_singletons[$class]);
    return $this;
}

public function get($class, $params = [], $config = [])
{
    if (isset($this->_singletons[$class])) {//是單例,且已經實例化(不為null)
        // singleton
        return $this->_singletons[$class];
    } elseif (!isset($this->_definitions[$class])) {//還沒有定義過,需要build
        return $this->build($class, $params, $config);
    }

    $definition = $this->_definitions[$class];

    if (is_callable($definition, true)) {
        $params = $this->resolveDependencies($this->mergeParams($class, $params));
        $object = call_user_func($definition, $this, $params, $config);
    } elseif (is_array($definition)) {
        $concrete = $definition["class"];
        unset($definition["class"]);

        $config = array_merge($definition, $config);
        $params = $this->mergeParams($class, $params);

        if ($concrete === $class) {//$concrete相當于之前提到的具體實現類C,而$class則相當于接口類B
            $object = $this->build($class, $params, $config);
        } else {
            $object = $this->get($concrete, $params, $config);//遞歸,直到找到具體的實現類C
        }
    } elseif (is_object($definition)) {
        return $this->_singletons[$class] = $definition;
    } else {
        throw new InvalidConfigException("Unexpected object definition type: " . gettype($definition));
    }

    if (array_key_exists($class, $this->_singletons)) {
        // singleton
        $this->_singletons[$class] = $object;
    }

    return $object;
}


protected function build($class, $params, $config)
{
    /* @var $reflection ReflectionClass */
    list ($reflection, $dependencies) = $this->getDependencies($class); //獲取第一層依賴關系

    foreach ($params as $index => $param) {
        $dependencies[$index] = $param; //額外提供的構造函數參數,添加到依賴中
    }

    $dependencies = $this->resolveDependencies($dependencies, $reflection);//遞歸解析依賴,并會在此返回依賴的實例
    if (!$reflection->isInstantiable()) {
        throw new NotInstantiableException($reflection->name);
    }
    if (empty($config)) {
        return $reflection->newInstanceArgs($dependencies);//通過反射實例生成對象
    }
    
    //config中的對象作為該類的property使用
    if (!empty($dependencies) && $reflection->implementsInterface("yiiaseConfigurable")) {
        // set $config as the last parameter (existing one will be overwritten)
        $dependencies[count($dependencies) - 1] = $config;
        return $reflection->newInstanceArgs($dependencies);
    } else {
        $object = $reflection->newInstanceArgs($dependencies);
        foreach ($config as $name => $value) {
            $object->$name = $value;
        }
        return $object;
    }
}


protected function getDependencies($class)
{
    if (isset($this->_reflections[$class])) {//如果已經反射解析過則直接返回
        return [$this->_reflections[$class], $this->_dependencies[$class]];
    }

    $dependencies = [];
    $reflection = new ReflectionClass($class);
    
    //構造函數的參數即這個類的依賴
    $constructor = $reflection->getConstructor();
    if ($constructor !== null) {    
        foreach ($constructor->getParameters() as $param) {
            if ($param->isDefaultValueAvailable()) {
                $dependencies[] = $param->getDefaultValue();
            } else {
                $c = $param->getClass();//這里要能獲取到類名需要在構造函數中用類型限制參數,否則獲取到null,而且注意對于php的基本類型,獲取到的也是null
                $dependencies[] = Instance::of($c === null ? null : $c->getName());
            }
        }
    }

    $this->_reflections[$class] = $reflection;
    $this->_dependencies[$class] = $dependencies;

    return [$reflection, $dependencies];
}



protected function resolveDependencies($dependencies, $reflection = null)
{
    foreach ($dependencies as $index => $dependency) {
        if ($dependency instanceof Instance) {
            if ($dependency->id !== null) { //這里的dependency是Instance的實例
                $dependencies[$index] = $this->get($dependency->id);
            } elseif ($reflection !== null) {
                $name = $reflection->getConstructor()->getParameters()[$index]->getName();
                $class = $reflection->getName();
                throw new InvalidConfigException("Missing required parameter "$name" when instantiating "$class".");
            }
        }
    }
    return $dependencies;
}

遞歸調用的示意圖

在Yii2中調用組件

先看一下各個類的繼承關系

下面以Yii::$app->db為例
1.配置組件
配置的內容:

"components" => [
    "db" => [
        "class" => "yiidbConnection",
        "dsn" => "mysql:host=localhost;dbname=wechat",
        "username" => "root",
        "password" => "michael",
        "charset" => "utf8",
    ],

2.在框架的啟動過程中加載組件的定義
Yii2的啟動
入口腳本:

(new yiiwebApplication($config))->run();
1.new yiiwebApplication($config)
2.run()

yiiwebApplication的構造函數

public function __construct($config = [])
{
    Yii::$app = $this;
    static::setInstance($this);   //將當前module存到Yii::$app->loadedModules[]
    $this->state = self::STATE_BEGIN;

    //1.通過$config配置別名,基本參數
    //2.配置核心組件(僅僅是配置,將Yii框架寫好的配置與自己的配置合并)
    $this->preInit($config); 

    $this->registerErrorHandler($config);

    //下面這一行是重點,Component是當前類的祖先
    //在下面的構造函數中執行了Yii::configure($this, $config),將$config中的配置作為屬性添加到$app中
    Component::__construct($config);
}

Component::__construct($config)

//實際上下面這個構造函數的定義在yiiaseObject中
public function __construct($config = [])
    {
        if (!empty($config)) {
            Yii::configure($this, $config);
        }
        $this->init();
    }

Yii::configure($this, $config)

public static function configure($object, $properties)
    {
        foreach ($properties as $name => $value) {
            //下面這行代碼會觸發魔術方法 ($object->components = $value)
            //實際執行的代碼是ServiceLocator::setComponents($components)
            $object->$name = $value;
        }

        return $object;
    }

ServiceLocator::setComponents($components)

public function setComponents($components)
{
    foreach ($components as $id => $component) {
        $this->set($id, $component);
    }
}

最終加載組件配置的代碼

//從下面的代碼中可以看到,最終組件的配置被存儲在$app->_definitions數組中
public function set($id, $definition)
{
    if ($definition === null) {
        unset($this->_components[$id], $this->_definitions[$id]);
        return;
    }

    unset($this->_components[$id]);

    if (is_object($definition) || is_callable($definition, true)) {
        // an object, a class name, or a PHP callable
        $this->_definitions[$id] = $definition;
    } elseif (is_array($definition)) {
        // a configuration array
        if (isset($definition["class"])) {
            $this->_definitions[$id] = $definition;
        } else {
            throw new InvalidConfigException("The configuration for the "$id" component must contain a "class" element.");
        }
    } else {
        throw new InvalidConfigException("Unexpected configuration type for the "$id" component: " . gettype($definition));
    }
}

3.獲取組件
Yii::$app->db會觸發魔術方法,調用ServiceLocator::__get()

public function __get($name)
{
    if ($this->has($name)) {
        //已經定義過組件
        return $this->get($name);
    } else {
        //沒有定義過組件
        return parent::__get($name);
    }
}

public function has($id, $checkInstance = false)
{
    //這里因為在框架啟動過程中將組件的配置加載到$_definitions中了,所以會返回true
    return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
}


//通過下面的代碼可以看到,如果組件已經實例化過存儲在$_components中了,就直接返回
//否則通過Yii::createObject($definition)來生成組件實例,并存儲到$_components中
public function get($id, $throwException = true)
{
    if (isset($this->_components[$id])) {
        return $this->_components[$id];
    }

    if (isset($this->_definitions[$id])) {
        $definition = $this->_definitions[$id];
        if (is_object($definition) && !$definition instanceof Closure) {
            return $this->_components[$id] = $definition;
        } else {
            return $this->_components[$id] = Yii::createObject($definition);
        }
    } elseif ($throwException) {
        throw new InvalidConfigException("Unknown component ID: $id");
    } else {
        return null;
    }
}

Yii::createObject($definition)

//在Yii2框架中要使用DI來生成對象的話,可以通過調用Yii::createObject($definition)實現
public static function createObject($type, array $params = [])
{
    if (is_string($type)) {
        //使用容器
        return static::$container->get($type, $params);
    } elseif (is_array($type) && isset($type["class"])) {
        $class = $type["class"];
        unset($type["class"]);
        return static::$container->get($class, $params, $type);
    } elseif (is_callable($type, true)) {
        return static::$container->invoke($type, $params);
    } elseif (is_array($type)) {
        throw new InvalidConfigException("Object configuration must be an array containing a "class" element.");
    }

    throw new InvalidConfigException("Unsupported configuration type: " . gettype($type));
}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25699.html

相關文章

  • 使用Yii2依賴注入簡化開發

    摘要:本文代碼什么是依賴注入對象由框架來創建而不是程序員通過創建。解除了調用者與被調用者之間的依賴。的依賴注入通過提供容器特性。靈活使用可以使我們從依賴關系中解脫出來,專注于業務邏輯。 本文代碼 https://github.com/xialeistudio/yii2-di-demo 什么是依賴注入(DI)? 對象由框架來創建而不是程序員通過 new 創建。跟IoC差不多一個意思。 為什么要...

    Luosunce 評論0 收藏0
  • 圖解Yii2框架依賴注入容器、服務定位器

    摘要:調用方法創建類得實例化對象,實際上又調用了依賴注入容器獲取每一個類的實例化對象。依賴注入容器自動解決待實例化類的依賴關系,并返回待實例化類的實例對象。 以下是Yii2源碼中,ServiceLocator(服務定位器)與Container(依賴注入容器)的關系解析圖。 一句話總結 Application繼承了ServiceLocator,是一個服務器定位器,ServiceLocator用...

    AlphaGooo 評論0 收藏0
  • yii2框架中的di容器源碼中了解反射的作用

    摘要:反射簡介參考官方簡介的話,具有完整的反射,添加了對類接口函數方法和擴展進行反向工程的能力。此外,反射提供了方法來取出函數類和方法中的文檔注釋。 反射簡介 參考官方簡介的話,PHP 5 具有完整的反射 API,添加了對類、接口、函數、方法和擴展進行反向工程的能力。 此外,反射 API 提供了方法來取出函數、類和方法中的文檔注釋。 YII2框架中示例 對于yii2框架,應該都知道di容器,...

    dantezhao 評論0 收藏0
  • yii過濾xss代碼,防止sql注入教程

    摘要:好啦,我們看看在框架的不同版本中是怎么處理攻擊,注入等問題的。那要是,又是怎樣處理的喃考慮目前國內網站大部分采集文章十分頻繁,更有甚者不注明原文出處,原作者更希望看客們查看原文,以防有任何問題不能更新所有文章,避免誤導繼續閱讀 作者:白狼 出處:http://www.manks.top/yii2_filter_xss_code_or_safe_to_database.html 本文版權...

    Shonim 評論0 收藏0
  • Yii2 完整框架分析(詳細)

    摘要:行為是如何注冊到組件的呢通過注冊行為之后,實際上是添加到了的屬性中那么行為中的屬性,就添加到了,中進行直接調用行為里面的方法的時候,實際上觸發了里面的魔術方法繼承鏈圖解 Yii2 框架Trace 準備 了解composer的autoload psr0 psr4 加載機制 了解spl_autoload_register 了解依賴注入的實現原理反射 了解常用魔術方法__set,__get...

    spademan 評論0 收藏0

發表評論

0條評論

harriszh

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<