php微框架 flight源码阅读——1.自动加载
先来看下框架的单入口文件index.php,先引入了Flight.php框架类文件。
<?php
require 'flight/Flight.php';
Flight::route('/', function(){
echo 'hello world!';
});
Flight::start();
Flight.php中定义了Flight类,类里面先定义了3个魔术方法,这三个魔术方法是为了防止当前类被实例化
// Don't allow object instantiation
private function __construct() {}
private function __destruct() {}
private function __clone() {}
如果试着去new Flight会提示如下错误:
Fatal error: Uncaught Error: Call to private Flight::__construct() from invalid context in /usr/local/var/www/flight135/index.php:3 Stack trace: #0 {main} Next Error: Call to private Flight::__destruct() from context '' in /usr/local/var/www/flight135/index.php:3 Stack trace: #0 {main} thrown in /usr/local/var/www/flight135/index.php on line 3
接着定义了一个重载方法__callStatic()
,在index.php中执行Flight::route('/', 'hello')
就会调用该__callStatic
,其中$name
就是'route'
,$params
就是自己写的hello
函数。在__callStatic()
中调用了当前类的app()
静态方法,这里为什么不使用self::app()
来调用呢?
/**
* Handles calls to static methods.
*
* @param string $name Method name
* @param array $params Method parameters
* @return mixed Callback results
* @throws \Exception
*/
public static function __callStatic($name, $params) {
$app = Flight::app();
return \flight\core\Dispatcher::invokeMethod(array($app, $name), $params);
}
接着就是在static app()
中开始处理自动加载了
/**
* @return \flight\Engine Application instance
*/
public static function app() {
static $initialized = false;
if (!$initialized) {
require_once __DIR__.'/autoload.php';
self::$engine = new \flight\Engine();
$initialized = true;
}
return self::$engine;
}
进入到autoload.php来看,引入了core目录下的Loader.php类文件,Loader就是加载器。
autoload.php
require_once __DIR__.'/core/Loader.php';
\flight\core\Loader::autoload(true, dirname(__DIR__));
Loader中定义了加载存放哪些类型:$classes
(类路径数组),$instances
(对象数组),$dirs
(框架目录路径数组)
/**
* Registered classes.
*
* @var array
*/
protected $classes = array();
/**
* Class instances.
*
* @var array
*/
protected $instances = array();
/**
* Autoload directories.
*
* @var array
*/
protected static $dirs = array();
autoload()中使用spl_autoload_register
将当前类(__CLASS__
)中的loadClass方法注册为加载的执行方法。
/**
* Starts/stops autoloader.
*
* @param bool $enabled Enable/disable autoloading
* @param array $dirs Autoload directories
*/
public static function autoload($enabled = true, $dirs = array()) {
if ($enabled) {
spl_autoload_register(array(__CLASS__, 'loadClass'));
}
else {
spl_autoload_unregister(array(__CLASS__, 'loadClass'));
}
if (!empty($dirs)) {
self::addDirectory($dirs);
}
}
/**
* Autoloads classes.
*
* @param string $class Class name
*/
public static function loadClass($class) {
$class_file = str_replace(array('\\', '_'), '/', $class).'.php';
foreach (self::$dirs as $dir) {
$file = $dir.'/'.$class_file;
if (file_exists($file)) {
require $file;
return;
}
}
}
接下来我们试着按照flight自动加载的方式,写个简单的自动加载进行测试:
/autoload/index.php
<?php
class MyClass{
public static function __callStatic($name, $params){
self::app();
}
public static function app(){
require_once __DIR__.'/Loader.php';
Loader::autoload(true, dirname(__DIR__));
new \autoload\Test();
}
}
MyClass::test();
new \autoload\Test2();
var_dump(Loader::getClasses());//array(2) { [0]=> string(36) "/usr/local/var/www/autoload/Test.php" [1]=> string(37) "/usr/local/var/www/autoload/Test2.php" }
/autoload/Loader.php
<?php
class Loader {
public static $dirs = [];
public static $classes = [];
public static function autoload($enabled=true, $dirs=[]) {
if ($enabled) {
spl_autoload_register([__CLASS__, 'loadClass']);
} else {
spl_autoload_unregister([__CLASS__, 'loadClass']);
}
if (!empty($dirs)) {
self::addDirectory($dirs);
}
}
public static function loadClass($class) {
$class_file = str_replace(['\\', '_'], '/', $class).'.php';
foreach (self::$dirs as $dir) {
$file = $dir.'/'.$class_file;
if (file_exists($file)) {
require $file;
self::$classes[] = $file;
return;
}
}
}
public static function addDirectory($dir) {
if (is_array($dir) || is_object($dir)) {
foreach ($dir as $value) {
self::addDirectory($value);
}
}
else if (is_string($dir)) {
if (!in_array($dir, self::$dirs)) self::$dirs[] = $dir;
}
}
public static function getClasses(){
return self::$classes;
}
}
/autoload/Test.php
<?php
namespace autoload;
class Test {}
/autoload/Test2.php
<?php
namespace autoload;
class Test2 {}
被 1 篇内容引用
421 声望
26 粉丝
推荐阅读
记一次在centos7上编译安装mosquitto的过程
首先把mosquitto最新源码包克隆到本地 {代码...} 或者下载压缩包 {代码...} 然后解压tar xzvf mosquitto-2.0.14.tar.gz接着进入解压目录 {代码...} 执行到cmake ..时,提示如下 {代码...} 提示cmake版本小于CMake...
parvin阅读 1.3k
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。
王中阳Go赞 4阅读 1.8k评论 2
一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。
煎鱼赞 4阅读 2.2k
Laravel入门及实践,快速上手ThinkSNS+二次开发
【摘要】自从ThinkSNS+不使用ThinkPHP框架而使用Laravel框架之后,很多人都说技术门槛抬高了,其实你与TS+的距离仅仅只是学习一个新框架而已,所以,我们今天来说说Laravel的入门。
ThinkSNS赞 1阅读 2.5k
我让chatGPT用PHP写一个MVC框架,不仅写出来,还能跑!
没想到写出来的框架确实挺简单的,但是又没觉得哪里不对,于是我尝试把这个框架放到服务器试试能不能跑起来,最后还真的可以跑起来,为了让大家能够看到这个框架的演示,我直接爬一个热搜,然后便于展示数据。
TANKING赞 1阅读 1.7k
开发一个全网搜索引擎的大致流程
由于对搜索引擎技术很感兴趣,便开始尝试开发一个搜索引擎。在参考了网上有限的资料后,加上自己钻研,最终开发出了一个小型的全网搜索引擎,底部有项目地址和搜索测试图片。
会飞的鸟赞 1阅读 5.7k评论 1
快速上手 Go CGO,掌握在 Go 里写 C!
大家好,我是煎鱼。最近因为各种奇怪的原因,接触到了 Go 特色之一 CGO。这方面的相关内容也相对少一些,给大家抛砖引玉。毕竟很多跨语言调用,还是会依赖 CGO 这个特性。希望大家在真正要用时有个前置知识垫肚子...
煎鱼赞 1阅读 1.4k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。