Laravel5.5解析-bootstrap列表-LoadConfiguration

扩展:PHP预定义接口

Closure
Closure代表匿名函数类,我们所使用的匿名函数是Closure的一个实例,高频使用静态方法bind与bindTo实现匿名函数与实例或类的绑定

final class Closure function bindTo($newthis, $newscope = ‘static’) { }

class Demo
{
    private static $static_attribute = 'static_attribute_init';
    public $general_attribute = '$general_attribute_init';

    public function show_message(){
        echo '$static_attribute now is '.self::$static_attribute."\n";
        echo '$general_attribute now is '.$this->general_attribute."\n";
    }
}
$callback = function(){
    self::$static_attribute = 'static_attribute_change';
    $this->general_attribute = 'general_attribute_change';
};
$demo = new Demo;
$func = $callback->bindTo($demo,Demo::class);//返回绑定的匿名函数
$func();
$demo->show_message();

输出:
$static_attribute now is static_attribute_change
$general_attribute now is general_attribute_change
bindTo函数的第一个参数是将匿名函数绑定到一个实例,默认为null,当前匿名函数使用到this关键字,顾需要绑定到实例,
bindTo函数的第二个参数是声明匿名函数的作用域,默认为static,当前匿名函数使用到self关键字,顾需要绑定到Demo类作用域,
在绑定实例后如果要更改private属性,则需要声明作用域
final class Closure static function bind(Closure $closure, $newthis, $newscope = ‘static’) { }
使用静态方法调用实现匿名函数绑定

ArrayAccess
提供数组式访问对象接口,实现方式依据继承接口的类自定义,接口摘要

ArrayAccess {
	/* 方法 */
	abstract public offsetExists ( mixed $offset ) : boolean
	abstract public offsetGet ( mixed $offset ) : mixed
	abstract public offsetSet ( mixed $offset , mixed $value ) : void
	abstract public offsetUnset ( mixed $offset ) : void
}
class Container implements ArrayAccess
{
    private $data = [];
    //$container[$offset] = $value;
    public function offsetSet($offset, $value){
        if(is_null($offset)){
            $this->data[] = $value;
        }else{
            $this->data[$offset] = $value;
        }
    }
    //isset($container[$offset]);
    public function offsetExists($offset){
        return isset($this->data[$offset]) ?:false;
    }
    //unset($container[$offset]);
    public function offsetUnset($offset){
        if(isset($this->data[$offset])){
            unset($this->data[$offset]);
        }
    }
    //$container[$offset];
    public function offsetGet($offset){
        if(isset($this->data[$offset])){
            return $this->data[$offset];
        }
        return null;
    }
}
$container = new Container();

Traversable
检验一个类是否可以被foreach遍历接口,必须由IteratorAggregate或Iterator接口实现

$checkout = $obj instanceof Traversable;//仅对继承了Traversable接口的实例返回true,对由数组临时转换的对象同样返回false

Iterator
迭代器接口

Iterator extends Traversable {
	/* 方法 */
	abstract public current ( void ) : mixed
	abstract public key ( void ) : scalar
	abstract public next ( void ) : void
	abstract public rewind ( void ) : void
	abstract public valid ( void ) : bool
}
class Implementation_Iterator implements Iterator
{
    private $index = 0;
    private $list = [
        'first','second','third'
    ];

    public function __construct(){
        $this->index = 0;
    }

    public function rewind(){
        echo __FUNCTION__."() ### ";
        $this->index = 0;
    }

    public function current(){
        echo __FUNCTION__."() ### ";
        return $this->list[$this->index];
    }

    public function key(){
        echo __FUNCTION__."();\n";
        return $this->index;
    }

    public function next(){
        echo __FUNCTION__."() ### ";
        $this->index++;
    }

    public function valid(){
        echo __FUNCTION__."() ### ";
        return isset($this->list[$this->index]);
    }
}
$implementation_Iterator = new Implementation_Iterator;
foreach($implementation_Iterator as $key => $value){
    echo $key."\n".$value."\n";
}

foreach()触发迭代器执行相关函数,执行结果如下:
rewind() ### valid() ### current() ### key();
0
first
next() ### valid() ### current() ### key();
1
second
next() ### valid() ### current() ### key();
2
third
next() ### valid() ###

IteratorAggregate
聚合是迭代器

IteratorAggregate extends Traversable {
/* 方法 */
abstract public getIterator ( void ) : Traversable
}

getIterator()返回实现了Iterator或Traversable 接口的类的一个实例。也就是说可以返回一个聚合迭代器,类似递归的方式,但最终一个聚合迭代器一定是返回Iterator迭代器;

<?php
class Implementation_IteratorAggregate implements IteratorAggregate
{
    public $username = "artisan";
    public $action = "Implementation IteratorAggregate";

    public function getIterator(){
        return new ArrayIterator($this);
    }
}
$implementation_iteratorAggregate = new Implementation_IteratorAggregate;
foreach($implementation_iteratorAggregate as $key => $value){
    echo 'key : '.$key.' --- value : '.$value."\n";
}
?>

getIterator()返回的实例是php标准库(SPL)中实现的迭代器;
在ArrayIterator类继承Iterator,实现rewind()、vaild()、current()、next()、key()等方法;
foreach()的执行过程中依旧是按照顺序执行Iterator的相关方法,执行结果如下:
key : username — value : artisan
key : action — value : Implementation IteratorAggregate

Serializable
自定义序列化接口

Serializable {
	/* 方法 */
	abstract public serialize ( void ) : string
	abstract public unserialize ( string $serialized ) : mixed
}
class Implementation_Serializable implements Serializable
{
    private $data;
    public function __construct()
    {
        $this->data = 'private data';
    }

    public function serialize(){
        return serialize($this->data);
    }

    public function unserialize($data){
        $this->data = unserialize($data);
    }

    public function getData(){
        return $this->data;
    }
}
$implementation_serializable = new Implementation_Serializable;
$ser = serialize($implementation_serializable);
$new_implementation_serializable  = unserialize($ser);
echo $new_implementation_serializable->getData();

自定义serialize()与unserialize()的动作

Generator
Generator实现了Iterator,即核心函数依旧是rewind->valid->current->key->next…,但generator不可以被继承,php应用程序中使用关键字yield调用Generator

Generator implements Iterator {
	/* 方法 */
	public current ( void ) : mixed
	public key ( void ) : mixed
	public next ( void ) : void
	public rewind ( void ) : void
	public send ( mixed $value ) : mixed
	public throw ( Exception $exception ) : void
	public valid ( void ) : bool
	public __wakeup ( void ) : void
}

功能简介

function fib($n)
{
    $cur = 1;
    $prev = 0;
    for ($i = 0; $i < $n; $i++) {
        yield $cur;
        $temp = $cur;
        $cur = $prev + $cur;
        $prev = $temp;
    }
}
//函数没有返回值,但是$fibs是有数据的
$fibs = fib(9);
var_dump($fibs instanceof Generator);
foreach($fibs as $fib){
    echo '---' .$fib;
}

输出
bool(true)
—1---1—2---3—5---8—13—21—34

应用场景:节省内存,用时间换空间

$start_time = microtime(true);
function xrange($num = 100000){
    for($i = 0 ; $i < $num ; ++ $i){
        yield $i;
    }
}

$generator = xrange();
echo 'memory:' . memory_get_usage() . ' time:' . (microtime(true) - $start_time);

memory:391216 time:1.5974044799805E-5%

$start_time = microtime(true);
function xrange2($num = 100000){
    $arr = [];
    for ($i=0; $i <$num ; ++$i) {
        array_push($arr , $i);
    }
    return $arr;
}

$arr = xrange2();
echo 'memory:' . memory_get_usage() . ' time:' . (microtime(true) - $start_time);

memory:4589376 time:0.0042829513549805

呼~~~:扩展知识到此结束,LoadConfiguration实例的实现过程中使用到了Iterator预定义借口

实现LoadConfiguration

bootstrap()

	//class Iluminate\Foundation\Bootstrap\LoadConfiguration
    public function bootstrap(Application $app)
    {
        $items = [];
		//校验是否存在缓存配置文件
        if (file_exists($cached = $app->getCachedConfigPath())) {
            $items = require $cached;
            $loadedFromCache = true;
        }
		//创建$config实例并存储在容器中
        $app->instance('config', $config = new Repository($items));
		//不存在缓存配置文件到时候加载配置文件
        if (! isset($loadedFromCache)) {
            $this->loadConfigurationFiles($app, $config);
        }
		//检测开发环境
        $app->detectEnvironment(function () use ($config) {
            return $config->get('app.env', 'production');
        });
		//设置时区
        date_default_timezone_set($config->get('app.timezone', 'UTC'));
		//设置编码字符集
        mb_internal_encoding('UTF-8');
    }

上述的核心方法是loadConfigurationFiles()

	//class Iluminate\Foundation\Bootstrap\LoadConfiguration
    protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {
    	//获取config目录下的文件名称组成的数组
        $files = $this->getConfigurationFiles($app);
        //将config目录下的文件名即文件内容存储在$config内
        foreach ($files as $key => $path) {
            $repository->set($key, require $path);
        }
    }

getConfigurationFiles()使用了IteratorAggregate和SPL中的Iterator

    protected function getConfigurationFiles(Application $app)
    {
        $files = [];
        $configPath = realpath($app->configPath());
		//Finder继承了IteratorAggregate
        foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) {
            $directory = $this->getNestedDirectory($file, $configPath);
            $files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath();
        }

        ksort($files, SORT_NATURAL);
        return $files;
    }

Finder::create()->files()->name(’*.php’)->in($configPath)

	//class Symfony\Component\Finder\Finder
    public static function create()
    {
    	//创建并返回实例
        return new static();
    }
    
    public function files()
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
        return $this;
    }
    
    public function name($pattern)
    {
        $this->names[] = $pattern;
        return $this;
    }
    
    public function in($dirs)
    {
        $resolvedDirs = [];
        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
            	//$this->normalizeDir($dir):/usr/local/var/www/auth/config
                $resolvedDirs[] = $this->normalizeDir($dir);
            }
        }
		//$this->dirs = [];
        $this->dirs = array_merge($this->dirs, $resolvedDirs);
		
        return $this;
    }

上述Finder的方法使用链式操作设定相关参数,在foreach的时候出发getIterator()

	//class Symfony\Component\Finder\Finder
    public function getIterator()
    {
    	...
        return $this->searchInDirectory($this->dirs[0]);
        ...
    }
    
    private function searchInDirectory($dir)
    {
        $exclude = $this->exclude;//[]
        $notPaths = $this->notPaths;//[]

        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $exclude = array_merge($exclude, self::$vcsPatterns);//$exclude = self::$vcsPatterns
        }

        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $notPaths[] = '#(^|/)\..+(/|$)#';//$notPaths = "#(^|/)\..+(/|$)#";
        }
        
		...
		
        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;

		...
		//创建自定义继承了\RecursiveDirectoryIterator的iterator实例,细节请查看php官网SPL定义的Iterator
        $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
        //使用SPL过滤目录iterator,过滤.git等目录
        if ($exclude) {
            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude);
        }
		//使用SPL递归迭代iterator
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);

		...
		//使用SPL文件类型过滤iterator
        if ($this->mode) {
            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }
        //使用SPL文件名称过滤iterator
        if ($this->names || $this->notNames) {
            $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }

		...
        //使用SPL文件路径过滤iterator
        if ($this->paths || $notPaths) {
            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
        }

		...

        return $iterator;
    }

追踪Iterator的current()

	//class namespace Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator
    public function current()
    {
    	//获取$subPathname,默认为"" 
        if (null === $subPathname = $this->subPath) {
            $subPathname = $this->subPath = (string) $this->getSubPath();
        }
        //获取文件名称
        $subPathname .= $this->getFilename();
        //获取路径名称
        if ('/' !== $basePath = $this->rootPath) {
            $basePath .= $this->directorySeparator;
        }
        //返回SplFileInfo实例
        return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
    }

回到getConfigurationFiles(),执行每一个文件并将文件路径即名称存储在$files数组中

    protected function getConfigurationFiles(Application $app)
    {
        $files = [];
        $configPath = realpath($app->configPath());
		//Finder继承了IteratorAggregate
        foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) {
            $directory = $this->getNestedDirectory($file, $configPath);
            $files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath();
        }

        ksort($files, SORT_NATURAL);
        return $files;
    }

$files:
array:11 [▼
“app” => “/usr/local/var/www/auth/config/app.php”
“auth” => “/usr/local/var/www/auth/config/auth.php”
“broadcasting” => “/usr/local/var/www/auth/config/broadcasting.php”
“cache” => “/usr/local/var/www/auth/config/cache.php”
“database” => “/usr/local/var/www/auth/config/database.php”
“filesystems” => “/usr/local/var/www/auth/config/filesystems.php”
“mail” => “/usr/local/var/www/auth/config/mail.php”
“queue” => “/usr/local/var/www/auth/config/queue.php”
“services” => “/usr/local/var/www/auth/config/services.php”
“session” => “/usr/local/var/www/auth/config/session.php”
“view” => “/usr/local/var/www/auth/config/view.php”
]
回到loadConfigurationFiles():

	//class Iluminate\Foundation\Bootstrap\LoadConfiguration
    protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {
    	//获取config目录下的文件名称组成的数组
        $files = $this->getConfigurationFiles($app);
        //将config目录下的文件名即文件内容存储在$config内
        foreach ($files as $key => $path) {
            $repository->set($key, require $path);
        }
    }

遍历 f i l e s 将 信 息 存 储 在 files将信息存储在 filesrepository中:

	//class Illuminate\Config\Repository
    public function set($key, $value = null)
    {
        $keys = is_array($key) ? $key : [$key => $value];
        foreach ($keys as $key => $value) {
            Arr::set($this->items, $key, $value);
        }
    }
	//class Illuminate\Support\Arr
	public static function set(&$array, $key, $value)
    {
		...

        $array[array_shift($keys)] = $value;

        return $array;
    }

$reposiroty:
Repository {#24 ▼
#items: array:11 [▼
“app” => array:13 [▶]
“auth” => array:4 [▶]
“broadcasting” => array:2 [▶]
“cache” => array:3 [▶]
“database” => array:4 [▶]
“filesystems” => array:3 [▶]
“mail” => array:9 [▶]
“queue” => array:3 [▶]
“services” => array:4 [▶]
“session” => array:15 [▶]
“view” => array:2 [▶]
]
}
回到bootstrap(),开始检测开发环境,设定时区及编码集,很简单的回调函数这里就不尽兴解释了

	//class Iluminate\Foundation\Bootstrap\LoadConfiguration
    public function bootstrap(Application $app)
    {
        $items = [];
		//校验是否存在缓存配置文件
        if (file_exists($cached = $app->getCachedConfigPath())) {
            $items = require $cached;
            $loadedFromCache = true;
        }
		//创建$config实例并存储在容器中
        $app->instance('config', $config = new Repository($items));
		//不存在缓存配置文件到时候加载配置文件
        if (! isset($loadedFromCache)) {
            $this->loadConfigurationFiles($app, $config);
        }
		//检测开发环境
        $app->detectEnvironment(function () use ($config) {
            return $config->get('app.env', 'production');
        });
		//设置时区
        date_default_timezone_set($config->get('app.timezone', 'UTC'));
		//设置编码字符集
        mb_internal_encoding('UTF-8');
    }

OK,到这里结束吧。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值