成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Laravel學(xué)習(xí)筆記之PHP重載(overloading)

khs1994 / 3579人閱讀

摘要:重載在中就大量應(yīng)用了重載相關(guān)知識(shí),如在中就用到了方法重載知識(shí)使用魔術(shù)方法來(lái)動(dòng)態(tài)創(chuàng)建類中未定義或不可見(jiàn)的靜態(tài)方法。中通過(guò)引入魔術(shù)方法來(lái)實(shí)現(xiàn)動(dòng)態(tài)的創(chuàng)建類屬性和方法,包括屬性重載的魔術(shù)方法和方法重載的魔術(shù)方法。

說(shuō)明:本文主要講述PHP中重載概念,由于Laravel框架中經(jīng)常使用這塊知識(shí)點(diǎn),并且PHP的重載概念又與其他OOP語(yǔ)言如JAVA中重載概念不一樣,故復(fù)習(xí)并記錄相關(guān)知識(shí)點(diǎn)。同時(shí),作者會(huì)將開(kāi)發(fā)過(guò)程中的一些截圖和代碼黏上去,提高閱讀效率。

重載(overloading)

在Laravel中就大量應(yīng)用了重載相關(guān)知識(shí),如在IlluminateSupportFacadesFacade中就用到了方法重載知識(shí):使用魔術(shù)方法__callStatic()來(lái)動(dòng)態(tài)創(chuàng)建類中未定義或不可見(jiàn)的靜態(tài)方法。PHP中重載概念與其他的OOP語(yǔ)言如JAVA語(yǔ)言中重載概念還不一樣,PHP中重載概念主要是:動(dòng)態(tài)的創(chuàng)建類屬性和方法,而不是一般的類中方法名一樣而參數(shù)不一樣。PHP中通過(guò)引入魔術(shù)方法來(lái)實(shí)現(xiàn)動(dòng)態(tài)的創(chuàng)建類屬性和方法,包括屬性重載的魔術(shù)方法和方法重載的魔術(shù)方法。當(dāng)然,重載是在類的外部發(fā)生的,所以所有魔術(shù)方法必須聲明public,而且參數(shù)不能引用傳遞。

PHP中是可以動(dòng)態(tài)創(chuàng)建一個(gè)類中未定義屬性或方法的,這也是PHP這個(gè)語(yǔ)言的一個(gè)比較靈活的特性,如:

class Person {

}

$person = new Person();
$person->name = "PHP";
echo $person->name.PHP_EOL;
$person->age("18");

Person類中沒(méi)有屬性$name和方法age(),但PHP可以動(dòng)態(tài)創(chuàng)建,echo出的$name值是"PHP",訪問(wèn)未定義的age()方法并不報(bào)錯(cuò)。

屬性重載

PHP中引入了4個(gè)魔術(shù)方法來(lái)實(shí)現(xiàn)屬性重載:

__set(string $name, array $value)

__get(string $name)

__isset(string $name)

__unset(string $name)

1、當(dāng)在類中定義魔術(shù)方法__set()時(shí),給未定義或不可見(jiàn)屬性賦值時(shí)會(huì)先觸發(fā)__set(),可以使用__set()魔術(shù)方法來(lái)禁止動(dòng)態(tài)創(chuàng)建屬性:

class Person {
    public function __set($name, $value)
    {
        if (isset($this->$name)) {
            return $this->$name = $value;
        } else {
            return null;
        }
    }
}

$person = new Person();
$person->name = "PHP";
echo $person->name.PHP_EOL;

這時(shí)想要?jiǎng)討B(tài)創(chuàng)建$name屬性就不可以了,返回null。

2、當(dāng)在類中定義魔術(shù)方法__get()時(shí),當(dāng)讀取未定義或不可見(jiàn)屬性時(shí)就觸發(fā)__get()方法:

class Person {
    private $sex;
    public function __set($name, $value)
    {
        if (isset($this->$name)) {
            return $this->$name = $value;
        } else {
            return null;
        }
    }

    public function __get($name)
    {
        return $name;
    }
}

$person = new Person();
$person->name = "PHP";
echo $person->name.PHP_EOL;
echo $person->sex.PHP_EOL;

如果不寫(xiě)魔術(shù)方法__get(),當(dāng)讀取不可見(jiàn)屬性$sex就報(bào)錯(cuò),而這里返回的是namesex字符串。

3、當(dāng)在類中定義魔術(shù)方法__isset()時(shí),當(dāng)對(duì)未定義或不可見(jiàn)屬性調(diào)用isset()或empty()方法時(shí),就會(huì)先觸發(fā)__isset()魔術(shù)方法:

class Person {
    private $sex;
    public function __set($name, $value)
    {
        if (isset($this->$name)) {
            return $this->$name = $value;
        } else {
            return null;
        }
    }

    public function __get($name)
    {
        return $name;
    }

    public function __isset($name)
    {
        echo $name;
    }
}

$person = new Person();
$person->name = "PHP";
echo $person->name.PHP_EOL;
echo $person->sex.PHP_EOL;
echo isset($person->address).PHP_EOL;

如果沒(méi)有魔術(shù)方法__isset()最后一行返回空,否則就觸發(fā)該魔術(shù)方法。

4、同樣的,魔術(shù)方法__unset()當(dāng)使用unset()方法時(shí)觸發(fā):

class Person {
    private $sex;
    public function __set($name, $value)
    {
        if (isset($this->$name)) {
            return $this->$name = $value;
        } else {
            return null;
        }
    }

    public function __get($name)
    {
        return $name;
    }

    public function __isset($name)
    {
        echo $name;
    }

    public function __unset($name)
    {
        echo $name.PHP_EOL;
    }
}

$person = new Person();
$person->name = "PHP";
echo $person->name.PHP_EOL;
echo $person->sex.PHP_EOL;
echo isset($person->address).PHP_EOL;
unset($person->name);
方法重載

上面是類屬性重載,當(dāng)類方法重載時(shí),PHP提供了兩個(gè)魔術(shù)方法:__call()和__callStatic(),__call()是動(dòng)態(tài)創(chuàng)建對(duì)象方法觸發(fā),__callStatic()是動(dòng)態(tài)創(chuàng)建類方法觸發(fā):

class Person {
    private $sex;
    public function __set($name, $value)
    {
        if (isset($this->$name)) {
            return $this->$name = $value;
        } else {
            return null;
        }
    }

    public function __get($name)
    {
        return $name;
    }

    public function __isset($name)
    {
        echo $name;
    }

    public function __unset($name)
    {
        echo $name.PHP_EOL;
    }

    public function __call(string $method, array $args)
    {
        echo $method."/".implode(",", $args).PHP_EOL;
    }

    public function __callStatic(string $method, array $args)
    {
        echo $method."/".implode(",", $args).PHP_EOL;
    }
}

$person = new Person();

$person->name = "PHP";
echo $person->name.PHP_EOL;
echo $person->sex.PHP_EOL;
echo isset($person->address).PHP_EOL;
unset($person->name);

$person->age("18");
Person::education("Master");

當(dāng)調(diào)用對(duì)象方法age()時(shí)觸發(fā)__call()魔術(shù)方法,且$args是一個(gè)數(shù)組,是要傳遞給$method方法的參數(shù)。方法返回字符串:age/18education/Master。

Laravel中方法重載使用

在使用Laravel的Facade這種模式時(shí),是通過(guò)Facade幫我們代理從容器Container中取出所需要的服務(wù)Service,就不需要通過(guò)$app["config"]這種方式取服務(wù)了,如:

        $callback = Config::get("github.callback");

但是查看源碼 IlluminateSupportFacadesConfig,發(fā)現(xiàn)并沒(méi)有get()這個(gè)靜態(tài)方法:


利用上面知識(shí),當(dāng)調(diào)用一個(gè)類中未定義或不可見(jiàn)的靜態(tài)方法時(shí),必然是調(diào)用了__callStatic()方法,發(fā)現(xiàn)IlluminateSupportFacadesFacade這個(gè)抽象類中定義了魔術(shù)方法__callStatic():

public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException("A facade root has not been set.");
        }

        switch (count($args)) {
            case 0:
                return $instance->$method();
            case 1:
                return $instance->$method($args[0]);
            case 2:
                return $instance->$method($args[0], $args[1]);
            case 3:
                return $instance->$method($args[0], $args[1], $args[2]);
            case 4:
                return $instance->$method($args[0], $args[1], $args[2], $args[3]);
            default:
                return call_user_func_array([$instance, $method], $args);
        }
    }

其中,

    /**
     * Get the root object behind the facade.
     *
     * @return mixed
     */
    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());//這里調(diào)用Config::getFacadeAccessor(),返回"config",static是靜態(tài)延遲綁定
    }
    
    /**
     * Resolve the facade root instance from the container.
     *
     * @param  string|object  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }
        //這里是使用$app["config"]從容器中解析,也就是實(shí)際上Facade貌似是幫我們從容器中解析Service,其實(shí)也是通過(guò)$app["config"]這種方式去解析。
        //當(dāng)然,有了Facade后,從容器中解析服務(wù)就不用受限于$app這個(gè)容器變量了。
        return static::$resolvedInstance[$name] = static::$app[$name];
    }

看到這里,我們知道當(dāng)使用Config::get()方法時(shí),會(huì)從容器中解析出名稱為"config"這個(gè)Service,也就是這個(gè)Service中有我們需要的get()方法,那哪一個(gè)Service名字叫做"config"。實(shí)際上,觀察Laravel源碼包的目錄結(jié)構(gòu)也知道在哪了:IlluminateConfigRepository,這個(gè)服務(wù)就是我們需要的,里面get()方法源碼:

    /**
     * Get the specified configuration value.
     *
     * @param  string  $key
     * @param  mixed   $default
     * @return mixed
     */
    public function get($key, $default = null)
    {
        return Arr::get($this->items, $key, $default);
    }

既然這個(gè)服務(wù)Service叫做config,那么容器類Application剛啟動(dòng)時(shí)就已經(jīng)把所有需要的服務(wù)注冊(cè)進(jìn)來(lái)了,并且取了名字。實(shí)際上,"config"服務(wù)是在IlluminateFoundationBootstrapLoadConfiguration注冊(cè)的,看bootstrap()方法源碼:

    /**
     * Bootstrap the given application.
     *
     * @param  IlluminateContractsFoundationApplication  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $items = [];

        // First we will see if we have a cache configuration file. If we do, we"ll load
        // the configuration items from that file so that it is very quick. Otherwise
        // we will need to spin through every configuration file and load them all.
        if (file_exists($cached = $app->getCachedConfigPath())) {
            $items = require $cached;

            $loadedFromCache = true;
        }

        $app->instance("config", $config = new Repository($items)); //在這里注冊(cè)名叫config的服務(wù),服務(wù)實(shí)體是Repository類

        // Next we will spin through all of the configuration files in the configuration
        // directory and load each one into the repository. This will make all of the
        // options available to the developer for use in various parts of this app.
        if (! isset($loadedFromCache)) {
            $this->loadConfigurationFiles($app, $config);
        }

        $app->detectEnvironment(function () use ($config) {
            return $config->get("app.env", "production");
        });

        date_default_timezone_set($config["app.timezone"]);

        mb_internal_encoding("UTF-8");
    }

這個(gè)啟動(dòng)方法做了一些環(huán)境監(jiān)測(cè)、時(shí)間設(shè)置和編碼設(shè)置。使用其他的Facade獲取其他Service也是這樣的過(guò)程。

總結(jié):基本學(xué)習(xí)了PHP的重載知識(shí)后,對(duì)使用Laravel的Facade這個(gè)方式來(lái)獲取服務(wù)時(shí)有了更深入的了解??傊?,多多使用Laravel來(lái)做一些東西和多多學(xué)習(xí)Laravel源碼并模仿之,也是一件有趣的事情。

歡迎關(guān)注Laravel-China。

RightCapital招聘Laravel DevOps

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/21798.html

相關(guān)文章

  • Laravel學(xué)習(xí)筆記Filesystem源碼解析(上)

    摘要:說(shuō)明本文主要學(xué)習(xí)的模塊的源碼邏輯,把自己的一點(diǎn)點(diǎn)研究心得分享出來(lái),希望對(duì)別人有所幫助。實(shí)際上,使用了的重載學(xué)習(xí)筆記之重載,通過(guò)魔術(shù)方法調(diào)用里的,而這個(gè)實(shí)際上就是,該中有方法,可以調(diào)用。 說(shuō)明:本文主要學(xué)習(xí)Laravel的Filesystem模塊的源碼邏輯,把自己的一點(diǎn)點(diǎn)研究心得分享出來(lái),希望對(duì)別人有所幫助??偟膩?lái)說(shuō),F(xiàn)ilesystem模塊的源碼也比較簡(jiǎn)單,Laravel的Illumi...

    AlphaGooo 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記bootstrap源碼解析

    摘要:總結(jié)本文主要學(xué)習(xí)了啟動(dòng)時(shí)做的七步準(zhǔn)備工作環(huán)境檢測(cè)配置加載日志配置異常處理注冊(cè)注冊(cè)啟動(dòng)。 說(shuō)明:Laravel在把Request通過(guò)管道Pipeline送入中間件Middleware和路由Router之前,還做了程序的啟動(dòng)Bootstrap工作,本文主要學(xué)習(xí)相關(guān)源碼,看看Laravel啟動(dòng)程序做了哪些具體工作,并將個(gè)人的研究心得分享出來(lái),希望對(duì)別人有所幫助。Laravel在入口index...

    xiaoxiaozi 評(píng)論0 收藏0
  • php易錯(cuò)筆記-類與對(duì)象,命名空間

    摘要:類與對(duì)象基本概念如果在之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。如果一個(gè)類被聲明為,則不能被繼承。命名空間通過(guò)關(guān)鍵字來(lái)聲明。 類與對(duì)象 基本概念 new:如果在 new 之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。 Example #3 創(chuàng)建一個(gè)實(shí)例 ...

    MartinHan 評(píng)論0 收藏0
  • 搞定PHP面試 - PHP魔術(shù)方法知識(shí)點(diǎn)整理

    摘要:魔術(shù)方法知識(shí)點(diǎn)整理代碼使用語(yǔ)法編寫(xiě)一構(gòu)造函數(shù)和析構(gòu)函數(shù)構(gòu)造函數(shù)具有構(gòu)造函數(shù)的類會(huì)在每次創(chuàng)建新對(duì)象時(shí)先調(diào)用此方法,所以非常適合在使用對(duì)象之前做一些初始化工作。在析構(gòu)函數(shù)中調(diào)用將會(huì)中止其余關(guān)閉操作的運(yùn)行。析構(gòu)函數(shù)中拋異常會(huì)導(dǎo)致致命錯(cuò)誤。 PHP魔術(shù)方法知識(shí)點(diǎn)整理 代碼使用PHP7.2語(yǔ)法編寫(xiě) 一、構(gòu)造函數(shù)和析構(gòu)函數(shù) __construct() 構(gòu)造函數(shù) __construct ([ mi...

    付永剛 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Core Concepts in Guzzle Package——Strea

    摘要:使用了來(lái)表示該,該接口也是對(duì)的抽象,暴露了一些常用方法判斷是否滿足要求的方法的讀寫(xiě)相關(guān)操作獲取元數(shù)據(jù)方法操作指針相關(guān)方法等等。本篇主要學(xué)習(xí)下相關(guān)使用。后續(xù)還會(huì)分享相關(guān)使用,到時(shí)見(jiàn)。 說(shuō)明:本文主要學(xué)習(xí)guzzlehttp/guzzle package的使用,該package提供了一套發(fā)送HTTP請(qǐng)求API,就像phpunit package, mockery package, symf...

    singerye 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<