惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 聂微东
Forbes - Security
Forbes - Security
IT之家
IT之家
P
Privacy International News Feed
宝玉的分享
宝玉的分享
小众软件
小众软件
Google DeepMind News
Google DeepMind News
美团技术团队
G
GRAHAM CLULEY
T
Tor Project blog
Recorded Future
Recorded Future
I
Intezer
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
Hugging Face - Blog
Hugging Face - Blog
A
About on SuperTechFans
Scott Helme
Scott Helme
WordPress大学
WordPress大学
F
Full Disclosure
D
Docker
G
Google Developers Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cyberwarzone
Cyberwarzone
The Last Watchdog
The Last Watchdog
V
V2EX
www.infosecurity-magazine.com
www.infosecurity-magazine.com
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Security Latest
Security Latest
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recent Announcements
Recent Announcements
P
Palo Alto Networks Blog
L
LINUX DO - 热门话题
V
Visual Studio Blog
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
腾讯CDC
H
Heimdal Security Blog
博客园 - 【当耐特】
Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy & Cybersecurity Law Blog
S
Securelist
Vercel News
Vercel News
J
Java Code Geeks

mafeifan 的编程技术分享

mafengwo-mp3-downloader | mafeifan 的编程技术分享 示例页面 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 查看 default namespace 下的 default service account名称 mafeifan 的编程技术分享 检查日志 | mafeifan 的编程技术分享 bridge fdb show dev flannel.1 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 数据收集原理分析 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 几种方法 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 check the export on the very top of this document so we can use $do mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 运维自动化之ANSIBLE | mafeifan 的编程技术分享 延伸 -- 关于前端路由 xdebug 3 和 2 的区别
mafeifan 的编程技术分享
2026-01-16 · via mafeifan 的编程技术分享

问题1 为什么可以直接用Facade ​

比如Cache::get('key');

Laravel 的入口文件是 public/index.php,此文件载入了 autoload.php, app.php 2个文件:

php

require __DIR__.'/../bootstrap/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';

顾名思义 autoload.php 实现了自动加载,app.php 和容器相关。

初始化容器的过程这里不详细解说,不是本文重点。

初始化容器后,执行了以下代码:

php

// 得到 App\Http\Kernel 实例对象
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
 
// 执行对象handle 方法,此方法继承自 Illuminate\Foundation\Http\Kernel
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

让我们去看下 handle() 做了些什么:

php

public function handle($request)
{
    //......省略......
    $response = $this->sendRequestThroughRouter($request);
    //......省略......
}

sendRequestThroughRouter 方法:

php

protected function sendRequestThroughRouter($request)
{
    //......省略......
    // 启动一些启动器,诸如异常处理,配置,日志,Facade,运行环境监测等
    $this->bootstrap();
    //......省略......
}

bootstrap 方法:

php

public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
       $this->app->bootstrapWith($this->bootstrappers());
    }
}

$this->bootstrappers() 中返回 $this->bootstrappers 保存的数据:

php

protected $bootstrappers = [
    'Illuminate\Foundation\Bootstrap\DetectEnvironment',
    'Illuminate\Foundation\Bootstrap\LoadConfiguration',
    'Illuminate\Foundation\Bootstrap\ConfigureLogging',
    'Illuminate\Foundation\Bootstrap\HandleExceptions',
    // 可以看到 
    'Illuminate\Foundation\Bootstrap\RegisterFacades',
    'Illuminate\Foundation\Bootstrap\RegisterProviders',
    'Illuminate\Foundation\Bootstrap\BootProviders',
];

RegisterFacades此类就是实现 Facade 的一部分,bootstrap 方法中 $this->app->bootstrapWith 会调用类的 bootstrap 方法:

php

class RegisterFacades
{
    public function bootstrap(Application $app)
    {
        //......省略......
        AliasLoader::getInstance($app->make('config')->get('app.aliases'))->register();
    }
}

$app->make('config')->get('app.aliases') 返回的是 config/app.php 配置文件中 'aliases' 键对应的值,

我们继续往下看 AliasLoader::getInstance 方法:

php

    /**
     * Get or create the singleton alias loader instance.
     *
     * @param  array  $aliases
     * @return \Illuminate\Foundation\AliasLoader
     */
    public static function getInstance(array $aliases = [])
    {
        if (is_null(static::$instance)) {
            return static::$instance = new static($aliases);
        }

        $aliases = array_merge(static::$instance->getAliases(), $aliases);

        static::$instance->setAliases($aliases);

        return static::$instance;
    }

回头再看

AliasLoader::getInstance($app->make('config')->get('app.aliases'))->register();中调用了 AliasLoader->register 方法:

php

public function register()
{
    if (!$this->registered) {
        $this->prependToLoaderStack();
        
        $this->registered = true;
    }
}

prependToLoaderStack 方法:

这里注册了当前对象中 load 方法为自动加载函数

php

protected function prependToLoaderStack()
{
    spl_autoload_register([$this, 'load'], true, true);
}

load 方法:

php

public function load($alias)
{
    if (isset($this->aliases[$alias])) {
        return class_alias($this->aliases[$alias], $alias);
    }
}

这里的 $this->aliases 即是 AliasLoader:getInstance 中实例化一个对象: new static($aliases) 时构造函数中设置的:

php

private function __construct($aliases)
{
    $this->aliases = $aliases;

这里 class_alias 是实现 Facade 的核心要点之一,该函数原型:

bool class_alias ( string $original, string $alias[, bool $autoload = TRUE ] )

第三个参数默认为 true,意味着如果原始类(string $original)没有加载,则自动加载。 更多该函数的解释请自行翻阅手册。

问题2 为什么可以像静态方法一样调用任何类的方法 ​

打开vendor/laravel/framework/src/Illuminate/Support/Facades/Cache.php

php

class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }
}

看一下 父类 Illuminate\Support\Facades,发现父类中实现了魔术方法 __callStatic:

php

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

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

        return $instance->$method(...$args);
    }

谜底就是通过魔术方法去实现的。

自己实现 ​

php

namespace Illuminate\Support\Facades {
    
    class Facades {
        public function __call($name, $params) {
            return call_user_func_array([$this, $name], $params);
        } 
        public static function __callStatic($name, $params) {
            return call_user_func_array([new static(), $name], $params);
        }  
    }
    
    class Cache extends Facades {
        protected function fn($a, $b) {
            echo "function parameters: ${a} and ${b}<br>";    
        }
        protected function static_fn($a, $b) {
            echo "static function parameters: ${a} and ${b}<br>";      
        }
    }
    
}
namespace {
    
    class Autoload {
        public $aliases;
        public function __construct($aliases = []) {
            $this->aliases = $aliases;
        }
        public function register() {
            spl_autoload_register([$this, 'load'], true, true);
            return $this;
        }
        public function load($alias) {
            if (isset($this->aliases[$alias])) {
                return class_alias($this->aliases[$alias], $alias);
            }    
        }
    }
    
    $aliases = [
        'Cache' => Illuminate\Support\Facades\Cache::class,
    ];
    $autoloader = (new Autoload($aliases))->register();
    Cache::fn(3,6);
    Cache::static_fn(4,7);
    
}

参考 ​

https://blog.csdn.net/hizzana/article/details/53212323