环境配置
找到自己的【系统命令行】目录:bin
/usr/bin #mac系统
/bin #ubuntu系统
再找到Php的编译器,这个根据你的安装路径来判断,mac默认的路径如下
cd /usr/bin #mac系统默认路径
cd /usr/local/php/bin/ #我的ubuntu中php的安装路径
./php -v #测试
新建php文件命名为lee(注意,#! 后面的参数是你的php编译器路径,这里我使用了mac自带的php编译器。这样一来,无论将文件放置在哪里,都可以用php编译器来运行该文件)
#! /usr/bin/php
<?php
echo "I am god".PHP_EOL;
?>
将lee复制到【系统命令行】目录中
sudo cp ./lee /usr/bin #mac系统的Bin的路径
这样一来,无论在什么路径下载命令行中输入:lee 都可以输出“I am god”
完成了自己的命令行
正式开始
demo1
知识点:
&& 这里并不是并且的意思,而是表达式如果成立,则执行后面的语句
PHP_EOL 这里是换行的意思。因为Linux和window换行的语法不一样【\n和\r\n】,所以使用这种写法统一
#! /usr/bin/php
<?php
echo "I am god".PHP_EOL;
$result = '';
if($argc > 1) //执行lee时,自己算是一个参数,所以如果有第二个参数就一定是大于1的
{
'-v' == $argv[1] && $result = 'god version is 1.0';
} $result != '' && exit($result.PHP_EOL);
?>
demo2:
新建类库lee_class
知识点: fgets(STDIN) 获取用户键盘输入
<?php
class lee
{
static $VERSION = 'god version is 1.1';
static $project_name = ''; //项目名称
static $project_author = ''; //项目作者 static function init()
{
echo "input your project name : ";
self::$project_name = fgets(STDIN); echo "input your author name : ";
self::$project_author = fgets(STDIN); return 'lee init complete';
}
}
?>
修改lee
#! /usr/bin/php
<?php
require('lee_func');
require('lee_class');
$result = '';
if($argc > 1)
{
'-v' == $argv[1] && $result = lee::$VERSION;
'init' == $argv[1] && $result = lee::init();
}
$result != '' && exit($result.PHP_EOL);
echo 'I am god'.PHP_EOL;
?>
demo3:
修改lee_class
知识点:__callStatic 未定义的静态函数调用时,会触发该函数
<?php
require('lee_config');
class lee
{
static $v = 'god version is 1.2';
static function init()
{
$lee_config = new lee_config(); echo "input your project name : ";
$lee_config->project_name = fgets(STDIN);//项目名称 echo "input your author name : ";
$lee_config->project_author = fgets(STDIN);//项目作者 $json = json_encode($lee_config); return file_put_contents(getcwd().'/god.json',$json).' of bytes is written'.PHP_EOL.'god config is created';
} //未定义的静态函数调用时,会触发该函数
static function __callStatic($m,$static_func)
{
exit("static function '{$m}' is not define".PHP_EOL);
}
}
?>
添加类lee_config
<?php class lee_config
{
//项目名称
public $project_name; //项目作者
public $project_author;
} ?>
修改lee (添加了php版本的“反射”来动态获取用户输入并且转换为属性或者方法)
知识点:利用php版本的“反射”来动态获取用户输入并且转换为属性或者方法
#! /usr/bin/php
<?php
require('lee_class');
$result = '';
if($argc > 1)
{
$p = $argv[1];
if(substr($p, 0,1) == '-')
{
//有'-'说明是属性,利用php版本的“反射”获取属性,当然还要判断一下属性是否存在
$p = substr($p,1);
//由于属性的调用格式是$name,所以这里有两个$,
$result = isset(lee::$$p)?lee::$$p:"command -{$p} is undefind";
}
else
{
//否则就是方法或者事件,利用php版本的“反射”获取方法,当然还要判断一下方法是否存在
$result = lee::$p();
}
}
$result != '' && exit($result.PHP_EOL);
?>
demo4:生成项目雏形
修改lee_class
<?php
require('lee_config');
class lee
{
static $v = 'god version is 1.2';
static function init()
{
$lee_config = new lee_config(); echo "input your project name : ";
$lee_config->project_name = fgets(STDIN);//项目名称 echo "input your author name : ";
$lee_config->project_author = fgets(STDIN);//项目作者 $json = json_encode($lee_config); return file_put_contents(getcwd().'/lee.json',$json).' of bytes is written'.PHP_EOL.'god config is created';
} static function config()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$result = '';
foreach ($obj as $key => $value) {
$result .= $key.' = '.$value.PHP_EOL;
}
return $result;
} static function make()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
!file_exists(getcwd().'/'.$obj->project_name) && mkdir(getcwd().'/'.$obj->project_name);
} //未定义的静态函数调用时,会触发该函数
static function __callStatic($m,$static_func)
{
exit("static function '{$m}' is not define".PHP_EOL);
}
}
?>
demo5:加强骨架
添加类lee_frame,专门管理骨架
<?php
class lee_frame
{
public $folder = ""; //项目文件夹
public $entry = ""; //入口文件
function __construct($name)
{
$this->folder = getcwd().'/'.$name;
$this->entry = $this->folder.'/index.php';
} function run()
{
!file_exists($this->folder) && mkdir($this->folder); //创建项目文件夹
!file_exists($this->entry) && file_put_contents($this->entry,''); //创建项目入口
}
}
?>
优化了config的名称,修改一下lee_class和lee_config
<?php
require('lee_config');
class lee
{
static $v = 'god version is 1.2';
static function init()
{
$lee_config = new lee_config(); echo "input your project name : ";
$lee_config->name = fgets(STDIN);//项目名称 echo "input your author name : ";
$lee_config->author = fgets(STDIN);//项目作者 $json = json_encode($lee_config); return file_put_contents(getcwd().'/lee.json',$json).' of bytes is written'.PHP_EOL.'god config is created';
} static function config()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$result = '';
foreach ($obj as $key => $value) {
$result .= $key.' = '.$value.PHP_EOL;
}
return $result;
} static function make()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
require('lee_frame');
$lee_frame = new lee_frame($obj->name);
$lee_frame->run();
} //未定义的静态函数调用时,会触发该函数
static function __callStatic($m,$static_func)
{
exit("static function '{$m}' is not define".PHP_EOL);
}
}
?>
简化了名称lee_config
<?php class lee_config
{
//项目名称
public $name; //项目作者
public $author;
} ?>
demo6:继续加强骨架
将lee_frame搬家到更深的目录,同时也是为了优化框架和学习命名空间
core\frame\lee_frame
知识点:命名空间,在不同的命名空间下可以定义同名的类。但是注意有个致命,这样一来所有new class的类实例化,默认都会加上命名空间,最简单的解决方法就是:new \class
<?php
namespace core\frame;
class lee_frame
{
public $folder = ""; //项目文件夹
public $entry = ""; //入口文件
function __construct($name)
{
$this->folder = getcwd().'/'.$name;
$this->entry = $this->folder.'/index.php';
} function run()
{
!file_exists($this->folder) && mkdir($this->folder); //创建项目文件夹
!file_exists($this->entry) && file_put_contents($this->entry,''); //创建项目入口
}
}
?>
修改lee_class
知识点:1、__autoload 如果new未找到的类,会触发这个函数
2、use core\frame\lee_frame 加载命名空间,这样一来所有lee_frame的类,都只会加载命名空间为core\frame的类了
<?php
require('lee_config');
use core\frame\lee_frame;
//如果new未找到的类,会触发这个函数
function __autoload($className)
{
$className = str_replace('\\', '/', $className);
require($className);
} class lee
{
static $v = 'god version is 1.2';
static function init()
{
$lee_config = new lee_config(); echo "input your project name : ";
$lee_config->name = str_replace("\n","",fgets(STDIN)); //项目名称 echo "input your author name : ";
$lee_config->author = str_replace("\n","",fgets(STDIN)); //项目作者 $json = json_encode($lee_config); return file_put_contents(getcwd().'/lee.json',$json).' of bytes is written'.PHP_EOL.'god config is created';
} static function config()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$result = '';
foreach ($obj as $key => $value) {
$result .= $key.' = '.$value.PHP_EOL;
}
return $result;
} static function make()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$lee_frame = new lee_frame($obj->name);
$lee_frame->run();
} //未定义的静态函数调用时,会触发该函数
static function __callStatic($m,$static_func)
{
exit("static function '{$m}' is not define".PHP_EOL);
}
}
?>
demo7:渲染Php模板
修改lee_class
知识点:将变量赋值给类中的属性,在php中,哪怕属性没有在类中初始化/定义,那么在赋值的时候也可以当场定义的。
<?php
require('lee_config');
use core\frame\lee_frame;
//如果new未找到的类,会触发这个函数
function __autoload($className)
{
$className = str_replace('\\', '/', $className);
require($className);
} class lee
{
static $v = 'god version is 1.2';
static function init()
{
$lee_config = new lee_config(); echo "input your project name : ";
$lee_config->name = str_replace("\n","",fgets(STDIN)); //项目名称 echo "input your author name : ";
$lee_config->author = str_replace("\n","",fgets(STDIN)); //项目作者 $json = json_encode($lee_config); return file_put_contents(getcwd().'/lee.json',$json).' of bytes is written'.PHP_EOL.'god config is created';
} static function config()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$result = '';
foreach ($obj as $key => $value) {
$result .= $key.' = '.$value.PHP_EOL;
}
return $result;
} static function make()
{
$json = file_get_contents(getcwd().'/lee.json');
$obj = json_decode($json);
$lee_frame = new lee_frame($obj->name);
$lee_frame->name = $obj->name; //将项目名传入类中
$lee_frame->author = $obj->author; //将作者名传入类中
$lee_frame->run();
} //未定义的静态函数调用时,会触发该函数
static function __callStatic($m,$static_func)
{
exit("static function '{$m}' is not define".PHP_EOL);
}
}
?>
新增index.tpl
知识点:奇思淫巧
<?php echo '<?php'.PHP_EOL; ?>
/**
* name:<?php echo $name; ?>
* User: <?php echo $author.PHP_EOL;; ?>
* Date: <?php ini_set('date.timezone','Asia/Shanghai'); echo date('Y-m-d') ?>
*/
echo "hello world";
修改lee_frame
知识点:extract(get_object_vars($this)); //这个东西比较复杂,首先将指定的类中的属性化为一个数组,然后extract解析数组
<?php
namespace core\frame;
class lee_frame
{
public $folder = ""; //项目文件夹
public $entry = ""; //入口文件
function __construct($name)
{
$this->folder = getcwd().'/'.$name;
$this->entry = $this->folder.'/index.php';
} function run()
{
//创建项目文件夹(如果不存在)
!file_exists($this->folder) && mkdir($this->folder);
//打开缓存区,不让内容输出到界面去
ob_start();
//这个东西比较复杂,首先将指定的类中的属性化为一个数组,然后extract解析数组
extract(get_object_vars($this));
//获取模板内容(需要好好研究学习一下模板的小技巧)
include dirname(__FILE__).'/tpl/index.tpl';
//获取缓冲区的内容
$contents = ob_get_contents();
//关闭并且清除缓冲区
ob_end_clean();
//创建项目入口(覆盖)
file_put_contents($this->entry,$contents);
}
}
?>
demo8 : 开启php内置的服务器
#套路
php -S localhost:9900 -t 目录 #demo
/usr/bin/php -S localhost:9900 -t /Users/apple/Desktop/lee/test
demo9
修改lee_frame
知识点:1、反射
2、get_defined_functions 获取所有已定义的变量
3、get_defined_functions 获取所有函数(包含内置和自定义)
4、文件操作 scandir
<?php
namespace core\frame;
class lee_frame
{
public $folder = ""; //项目文件夹
public $entry = ""; //入口文件
function __construct($name)
{
$this->folder = getcwd().'/'.$name;
$this->entry = $this->folder.'/index.php';
} function compile()
{
//获取项目/code下所有的文件
$_files = scandir($this->folder.'/code');
foreach($_files as $_file)
{
//匹配如aaa.var.php的文件
if(preg_match("/\w+\.var|func\.php$/i", $_file))
{
require($this->folder.'/code/'.$_file);
}
} unset($_files); //摧毁变量,仅仅是为了下面的get_defined_vars
unset($_file); //摧毁变量,仅仅是为了下面的get_defined_vars $var_results = var_export(get_defined_vars(),true);
$result = '<?php'.PHP_EOL
."extract({$var_results})"; file_put_contents($this->folder.'/vars', $result); //获取所有自定义函数
$func_results = get_defined_functions()['user']; //拼接的函数字符串
$func_str = '<?php '.PHP_EOL
."/*".PHP_EOL
."* compile by lee {date(Y-m-d h:i:s)}".PHP_EOL
.'*/'.PHP_EOL; foreach ($func_results as $func)
{
//反射
$f = new \ReflectionFunction($func);
$start=$f->getStartLine(); //函数所在文件位置的起始行
$end=$f->getEndLine(); //函数所在文件位置的结束行
$file_arr = file($f->getFileName()); //根据路径获取所有的内容,根据内容的换行作为数组的索引
$func_arr = array_slice($file_arr, $start - 1,$end - $start + 1); //根据上面的数组,返回纯函数的行内容
$func_str .= implode($func_arr); //获取函数纯字符串
} file_put_contents($this->folder.'/functions', $func_str); } function run()
{
//创建项目文件夹(如果不存在)
!file_exists($this->folder) && mkdir($this->folder);
//打开缓存区,不让内容输出到界面去
ob_start();
//这个东西比较复杂,首先将指定的类中的属性化为一个数组,然后extract解析数组
extract(get_object_vars($this));
//获取模板内容(需要好好研究学习一下模板的小技巧)
include dirname(__FILE__).'/tpl/index.tpl';
//获取缓冲区的内容
$contents = ob_get_contents();
//关闭并且清除缓冲区
ob_end_clean();
//创建项目入口(覆盖)
file_put_contents($this->entry,$contents);
} }
?>
demo10
添加lee_mvc
<?php namespace core\frame;
class lee_mvc
{
public $classNmae = ''; //类名
public $classComment = ''; //类的注释
public $classMethods = array(); //类中所有的方法 function __construct($cname)
{
$this->classNmae = $cname;
//类反射
$f = new \ReflectionClass($cname);
//获取类的注释
$this->classComment = $f->getDocComment();
//获取类中所有的方法,返回的数组中值,实际上是反射(函数)
$this->classMethods = $f->getMethods();
} function IsController()
{
return preg_match('/@Controller/', $this->classComment);
} function getRequestMapping()
{
$arr1 = array();
foreach ($this->classMethods as $value) {
//获取类方法的注释
$arr2 = $this->getRequestMappingResult($value);
if($arr2)
{
$arr1 = array_merge($arr1,$arr2);
}
}
return $arr1;
} function getRequestMappingResult($medhod)
{
//@RequestMapping("/getme",Method=GET);
if(preg_match('/@RequestMapping\("(.{2,50})",Method=(\w{3,8})\);/', $medhod->getDocComment(),$result))
{
$Method = $medhod->getName(); //方法名
$RequestUrl = $result[1]; //url地址
$RequestMethod = $result[2]; //post或者get
return array(
$RequestUrl => array('RequestMethod'=>$RequestMethod,'Class'=>$this->classNmae,'Method'=>$Method)
);
}
return false;
}
}
修改lee_frame
<?php
namespace core\frame;
use core\frame\lee_mvc;
ini_set('date.timezone','Asia/Shanghai'); class lee_frame
{
public $folder = ""; //项目文件夹
public $entry = ""; //入口文件
function __construct($name)
{
$this->folder = getcwd().'/'.$name;
$this->entry = $this->folder.'/index.php';
} function compile()
{
//获取项目/code下所有的文件
$_files = scandir($this->folder.'/code');
foreach($_files as $_file)
{
//匹配如aaa.var.php的文件
if(preg_match("/\w+\.var|func|class\.php$/i", $_file))
{
require($this->folder.'/code/'.$_file);
}
} unset($_files); //摧毁变量,不要污染到自定义的变量,也是为了下面的get_defined_vars
unset($_file); //摧毁变量,不要污染到自定义的变量,也是为了下面的get_defined_vars $var_results = var_export(get_defined_vars(),true);
$result = '<?php'.PHP_EOL
."extract({$var_results});"; file_put_contents($this->folder.'/vars', $result); //获取所有自定义函数
$func_results = get_defined_functions()['user']; //拼接的函数字符串
$func_str = "<?php ".PHP_EOL
."/*".PHP_EOL
."* compile by lee ".date('Y-m-d h:i:s').PHP_EOL
."*/".PHP_EOL; foreach ($func_results as $func)
{
//反射(函数)
$f = new \ReflectionFunction($func);
$start=$f->getStartLine(); //函数所在文件位置的起始行
$end=$f->getEndLine(); //函数所在文件位置的结束行
$file_arr = file($f->getFileName()); //根据路径获取所有的内容,根据内容的换行作为数组的索引
$func_arr = array_slice($file_arr, $start - 1,$end - $start + 1); //根据上面的数组,返回纯函数的行内容
$func_str .= implode($func_arr); //获取函数纯字符串
} file_put_contents($this->folder.'/functions', $func_str); //获取项目中所有的类
$class_Result = get_declared_classes();
//获取当前类名的键
$class_key = array_search(__CLASS__, $class_Result);
//我也不知道为啥排到当前类之后的类就是自定义的类,算了先写再说吧
$class_Result = array_slice($class_Result, $class_key + 1);
$arr1 = array();
foreach ($class_Result as $value)
{
$mvc = new lee_mvc($value);
if($mvc->IsController())
{
$arr2 = $mvc->getRequestMapping();
$arr1 = array_merge($arr1,$arr2);
}
} file_put_contents($this->folder.'/request_route', "<?php ".PHP_EOL." return ".var_export($arr1,true).";"); } function run()
{
//创建项目文件夹(如果不存在)
!file_exists($this->folder) && mkdir($this->folder);
//打开缓存区,不让内容输出到界面去
ob_start();
//这个东西比较复杂,首先将指定的类中的属性化为一个数组,然后extract解析数组
extract(get_object_vars($this));
//获取模板内容(需要好好研究学习一下模板的小技巧)
include dirname(__FILE__).'/tpl/index.tpl';
//获取缓冲区的内容
$contents = ob_get_contents();
//关闭并且清除缓冲区
ob_end_clean();
//创建项目入口(覆盖)
file_put_contents($this->entry,$contents); //开启我心爱的小耗子
echo "lee server is started in 9900".PHP_EOL;
system('/usr/bin/php -S localhost:9900 -t '.$this->folder);
} }
?>