成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

AlphaGooo / 2875人閱讀

摘要:說(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的IlluminateFilesystem模塊主要依賴于LeagueFlysystem這個(gè)Filesystem Abstractor Layer,類似于是LeagueFlysystem的Laravel Bridge。而不同的Filesystem SDK有著各自的具體增刪改查邏輯,如AWS S3 SDK,Dropbox SDK,這些SDK都是通過(guò)Adapter Pattern裝載入這個(gè)Filesystem Abstractor Layer。Filesystem模塊的整體架構(gòu)如下兩張圖:

開發(fā)環(huán)境:Laravel5.2+MAMP+PHP7+MySQL5.6

1. IlluminateFilesystemFilesystemServiceProvider

Laravel中每一個(gè)Service模塊都有對(duì)應(yīng)的ServiceProvider,主要幫助把該Service注冊(cè)到Container中,方便在應(yīng)用程序中利用Facade調(diào)用該Service。同樣,F(xiàn)ilesystem Service有對(duì)應(yīng)的FilesystemServiceProvider,幫助注冊(cè)filesfilesystem等Service:

        // IlluminateFilesystem
        $this->app->singleton("files", function () {
            return new Filesystem;
        });
        
        $this->app->singleton("filesystem", function () {
            return new FilesystemManager($this->app);
        });

使用Container的singleton單例注冊(cè),同時(shí)還注冊(cè)了filesystem.disk(config/filesystems.php的default配置選項(xiàng))和filesystem.cloud(config/filesystems.php的cloud配置選項(xiàng))。其中,files的Facade為IlluminateSupportFacadesFile,filesystem的Facade為IlluminateSupportFacadesFilesystem

2. IlluminateFilesystemFilesystemManager

Laravel官網(wǎng)上有類似這樣代碼:

// Recursively List下AWS S3上路徑為dir/to的所有文件,迭代所有的文件和文件夾下的文件
$s3AllFiles = Storage::disk("s3")->allFiles("dir/to");
// Check S3 上dir/to/filesystem.png該文件是否存在
$s3AllFiles = Storage::disk("s3")->exists("dir/to/filesystem.png");

那這樣的代碼內(nèi)部實(shí)現(xiàn)邏輯是怎樣的呢?

翻一下IlluminateFilesystemFilesystemManager代碼就很容易知道了。首先Storage::disk()是利用了Facade模式,Storage是名為filesystem的Facade,而filesystem從上文知道實(shí)際是FilesystemManager的對(duì)象,所以可以看做(new FilesystemManager)->disk(),看disk()方法源碼:

    // IlluminateFilesystemFilesystemManager
    /**
     * Get a filesystem instance.
     *
     * @param  string  $name
     * @return IlluminateContractsFilesystemFilesystem
     */
    public function disk($name = null)
    {
        // 如果不傳參,就默認(rèn)filesystems.default的配置
        $name = $name ?: $this->getDefaultDriver();
        // 這里傳s3,$this->get("s3")取S3 driver
        return $this->disks[$name] = $this->get($name);
    }
    
    /**
     * Get the default driver name.
     *
     * @return string
     */
    public function getDefaultDriver()
    {
        return $this->app["config"]["filesystems.default"];
    }
    
    /**
     * Attempt to get the disk from the local cache.
     *
     * @param  string  $name
     * @return IlluminateContractsFilesystemFilesystem
     */
    protected function get($name)
    {
        // PHP7里可以這樣簡(jiǎn)潔的寫 $this->disks[$name] ?? $this->resolve($name);
        return isset($this->disks[$name]) ? $this->disks[$name] : $this->resolve($name);
    }
    
    /**
     * Resolve the given disk.
     *
     * @param  string  $name
     * @return IlluminateContractsFilesystemFilesystem
     *
     * @throws InvalidArgumentException
     */
    protected function resolve($name)
    {
        // 取出S3的配置
        $config = $this->getConfig($name);
        // 檢查自定義驅(qū)動(dòng)中是否已經(jīng)提前定義了,自定義是通過(guò)extend($driver, Closure $callback)定制化driver,
        // 如果已經(jīng)定義則取出定制化driver,下文介紹
        if (isset($this->customCreators[$config["driver"]])) {
            return $this->callCustomCreator($config);
        }
        // 這里有個(gè)巧妙的技巧,檢查IlluminateFilesystemFilesystemManager中是否有createS3Driver這個(gè)方法,
        // 有的話代入$config參數(shù)執(zhí)行該方法,看createS3Driver()方法
        $driverMethod = "create".ucfirst($config["driver"])."Driver";

        if (method_exists($this, $driverMethod)) {
            return $this->{$driverMethod}($config);
        } else {
            throw new InvalidArgumentException("Driver [{$config["driver"]}] is not supported.");
        }
    }
    
    /**
     * Get the filesystem connection configuration.
     *
     * @param  string  $name
     * @return array
     */
    protected function getConfig($name)
    {
        return $this->app["config"]["filesystems.disks.{$name}"];
    }
    
    /**
     * Create an instance of the Amazon S3 driver.
     *
     * @param  array  $config
     * @return IlluminateContractsFilesystemCloud
     */
    public function createS3Driver(array $config)
    {
        $s3Config = $this->formatS3Config($config);

        $root = isset($s3Config["root"]) ? $s3Config["root"] : null;

        $options = isset($config["options"]) ? $config["options"] : [];

        // use LeagueFlysystemAwsS3v3AwsS3Adapter as S3Adapter,這里用了LeagueFlysystemFilesystem,
        // 上文說(shuō)過(guò)Laravel的Filesystem只是個(gè)Filesystem Bridge,實(shí)際上用的是LeagueFlysystem這個(gè)依賴。
        // LeagueFlysystem源碼解析會(huì)在下篇中講述,
        // 主要使用了Adapter Pattern把各個(gè)Filesystem SDK 整合到一個(gè)LeagueFlysystemFilesystemInterface實(shí)例中,
        // 有幾個(gè)核心概念:Adapters, Relative Path, Files First, Plugin, MountManager(File Shortcut), Cache。
        // 下面代碼類似于
        //  (new IlluminateFilesystemFilesystemAdapter(
        //    new LeagueFlysystemFilesystem(
        //        new S3Adapter(new S3Client(), $options), $config)
        //    )
        //  ))
        return $this->adapt($this->createFlysystem(
            new S3Adapter(new S3Client($s3Config), $s3Config["bucket"], $root, $options), $config
        ));
    }
    
    /**
     * Create a Flysystem instance with the given adapter.
     *
     * @param  LeagueFlysystemAdapterInterface  $adapter
     * @param  array  $config
     * @return LeagueFlysystemFlysystemInterface
     */
    protected function createFlysystem(AdapterInterface $adapter, array $config)
    {
        $config = Arr::only($config, ["visibility", "disable_asserts"]);

        // use LeagueFlysystemFilesystem as Flysystem
        return new Flysystem($adapter, count($config) > 0 ? $config : null);
    }
    
    /**
     * Adapt the filesystem implementation.
     *
     * @param  LeagueFlysystemFilesystemInterface  $filesystem
     * @return IlluminateContractsFilesystemFilesystem
     */
    protected function adapt(FilesystemInterface $filesystem)
    {
        return new FilesystemAdapter($filesystem);
    }

通過(guò)代碼里注釋,可以看出Storage::disk("s3")實(shí)際上返回的是這樣一段類似代碼:

(new IlluminateFilesystemFilesystemAdapter(new LeagueFlysystemFilesystem(new S3Adapter(new S3Client(), $options), $config))))

所以,Storage::disk("s3")->allFiles($parameters)或者Storage::disk("s3")->exists($parameters),實(shí)際上調(diào)用的是IlluminateFilesystemFilesystemAdapter這個(gè)對(duì)象的allFiles($parameters)和exists($parameters)方法。

3. IlluminateFilesystemFilesystemAdapter

查看FilesystemAdapter的源碼,提供了關(guān)于filesystem的增刪改查的一系列方法:

    /**
     * Determine if a file exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function exists($path)
    {
        // 實(shí)際上又是調(diào)用的driver的has()方法,$driver又是LeagueFlysystemFilesystem對(duì)象,
        // 查看LeagueFlysystemFilesystem對(duì)象的has()方法,
        // 實(shí)際上是通過(guò)LeagueFlysystemAwsS3v3AwsS3Adapter的has()方法,
        // 當(dāng)然最后調(diào)用的是AWS S3 SDK包的(new S3Client())->doesObjectExist($parameters)檢查S3上該文件是否存在
        return $this->driver->has($path);
    }
    
    /**
     * Get all of the files from the given directory (recursive).
     *
     * @param  string|null  $directory
     * @return array
     */
    public function allFiles($directory = null)
    {
        return $this->files($directory, true);
    }
    
    /**
     * Get an array of all files in a directory.
     *
     * @param  string|null  $directory
     * @param  bool  $recursive
     * @return array
     */
    public function files($directory = null, $recursive = false)
    {
        $contents = $this->driver->listContents($directory, $recursive);

        return $this->filterContentsByType($contents, "file");
    }
    
    /**
     * Pass dynamic methods call onto Flysystem.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws BadMethodCallException
     */
    public function __call($method, array $parameters)
    {
        return call_user_func_array([$this->driver, $method], $parameters);
    }

通過(guò)代碼注釋知道,Storage::disk("s3")->exists($parameters)實(shí)際上最后通過(guò)調(diào)用S3 SDK的(new S3Client())->doesObjectExist($parameters)檢查S3上有沒(méi)有該文件,Storage::disk("s3")->allFiles($parameters)也是同理,通過(guò)調(diào)用(new LeagueFlysystemAwsS3v3AwsS3Adapter(new S3Client(), $config))->listContents()來(lái)list contents of a dir.

根據(jù)上文的解釋,那Storage::disk("s3")->readStream($path)可以調(diào)用不?
可以的。實(shí)際上,IlluminateFilesystemFilesystemAdapter使用了PHP的重載(Laravel學(xué)習(xí)筆記之PHP重載(overloading)),通過(guò)__call($method, $parameters)魔術(shù)方法調(diào)用$driver里的$method,而這個(gè)$driver實(shí)際上就是(new LeagueFlysystemFilesystem),該Filesystem Abstract Layer中有readStream方法,可以調(diào)用。

Laravelgu官網(wǎng)中介紹通過(guò)Storage::extend($driver, Closure $callback)來(lái)自定義driver,這里我們知道實(shí)際上調(diào)用的是(new IlluminateFilesystemFilesystemManager($parameters))->extend($driver, Closure $callback),上文中提到該對(duì)象的resolve($name)代碼時(shí)會(huì)先檢查自定義驅(qū)動(dòng)有沒(méi)有,有的話調(diào)用自定義驅(qū)動(dòng),再看下resolve()代碼:

    /**
     * Resolve the given disk.
     *
     * @param  string  $name
     * @return IlluminateContractsFilesystemFilesystem
     *
     * @throws InvalidArgumentException
     */
    protected function resolve($name)
    {
        $config = $this->getConfig($name);

        // 檢查自動(dòng)以驅(qū)動(dòng)是否存在,存在的話,調(diào)用callCustomCreator來(lái)解析出$driver
        if (isset($this->customCreators[$config["driver"]])) {
            return $this->callCustomCreator($config);
        }

        $driverMethod = "create".ucfirst($config["driver"])."Driver";

        if (method_exists($this, $driverMethod)) {
            return $this->{$driverMethod}($config);
        } else {
            throw new InvalidArgumentException("Driver [{$config["driver"]}] is not supported.");
        }
    }    
   
   /**
     * Call a custom driver creator.
     *
     * @param  array  $config
     * @return IlluminateContractsFilesystemFilesystem
     */
    protected function callCustomCreator(array $config)
    {
        $driver = $this->customCreators[$config["driver"]]($this->app, $config);

        if ($driver instanceof FilesystemInterface) {
            return $this->adapt($driver);
        }

        return $driver;
    }     

extend()方法就是把自定義的驅(qū)動(dòng)注冊(cè)進(jìn)$customCreators里:

    /**
     * Register a custom driver creator Closure.
     *
     * @param  string    $driver
     * @param  Closure  $callback
     * @return $this
     */
    public function extend($driver, Closure $callback)
    {
        $this->customCreators[$driver] = $callback;

        return $this;
    }

總結(jié):上篇主要講述了Laravel Filesystem Bridge,該Bridge只是把League/Flysystem這個(gè)package簡(jiǎn)單做了橋接和封裝,便于在Laravel中使用。明天再寫下篇,主要學(xué)習(xí)下League/Flysystem這個(gè)package的源碼,League/Flysystem作為一個(gè)Filesystem Abstractor Layer,利用了Adapter Pattern來(lái)封裝各個(gè)filesystem的SDK,如AWS S3 SDK或Dropbox SDK。到時(shí)見。

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

RightCapital招聘Laravel DevOps

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30431.html

相關(guān)文章

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

    摘要:源碼解析這個(gè)類的源碼主要就是文件的操作和文件屬性的操作,而具體的操作是通過(guò)每一個(gè)實(shí)現(xiàn)的,看其構(gòu)造函數(shù)看以上代碼知道對(duì)于操作,實(shí)際上是通過(guò)的實(shí)例來(lái)實(shí)現(xiàn)的??梢钥聪碌氖褂蒙衔囊呀?jīng)說(shuō)了,使得對(duì)各種的操作變得更方便了,不管是還是得。 說(shuō)明:本文主要學(xué)習(xí)下LeagueFlysystem這個(gè)Filesystem Abstract Layer,學(xué)習(xí)下這個(gè)package的設(shè)計(jì)思想和編碼技巧,把自己的一...

    Luosunce 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記IoC Container實(shí)例化源碼解析

    摘要:說(shuō)明本文主要學(xué)習(xí)容器的實(shí)例化過(guò)程,主要包括等四個(gè)過(guò)程??聪碌脑创a如果是數(shù)組,抽取別名并且注冊(cè)到中,上文已經(jīng)討論實(shí)際上就是的。 說(shuō)明:本文主要學(xué)習(xí)Laravel容器的實(shí)例化過(guò)程,主要包括Register Base Bindings, Register Base Service Providers , Register Core Container Aliases and Set the ...

    ningwang 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Filesystem-從Dropbox中下載文件到AWS S3

    摘要:說(shuō)明本文主要講述了的文件系統(tǒng)的小,邏輯不復(fù)雜,主要就是把上的一個(gè)文件下載到本地,和下載到中。寫驅(qū)動(dòng)由于沒(méi)有驅(qū)動(dòng),需要自定義下在中寫上名為的驅(qū)動(dòng)同時(shí)在注冊(cè)下該就行。執(zhí)行命令后,顯示上文件從上下載到上的文件該邏輯簡(jiǎn)單,但很好玩。 說(shuō)明:本文主要講述了Laravel的文件系統(tǒng)Filesystem的小Demo,邏輯不復(fù)雜,主要就是把Dropbox上的一個(gè)文件下載到本地local,和下載到AWS...

    tylin 評(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
  • Laravel核心——Ioc服務(wù)容器源碼解析(服務(wù)器解析

    摘要:而函數(shù)作用是加載延遲服務(wù),與容器解析關(guān)系不大,我們放在以后再說(shuō)。在構(gòu)造之前,服務(wù)容器會(huì)先把放入中,繼而再去解析。利用服務(wù)容器解析依賴的參數(shù)。 make解析 首先歡迎關(guān)注我的博客: www.leoyang90.cn 服務(wù)容器對(duì)對(duì)象的自動(dòng)解析是服務(wù)容器的核心功能,make 函數(shù)、build 函數(shù)是實(shí)例化對(duì)象重要的核心,先大致看一下代碼: public function make($abst...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<