环境配置

找到自己的【系统命令行】目录: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);
} }
?>

php 魔鬼训练的更多相关文章

  1. js 魔鬼训练

    1.Object.assign 偷梁换柱 / 融合 - 将多个对象合并到第一个对象中去.这样一来methods对象中就包含着data对象了.否则this无法正常访问data中的title var ne ...

  2. 接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket

    引子 下一篇标题是<深入理解MQ生产端的底层通信过程>,建议文章读完之前.或者读完之后,再读一遍我之前写的<RabbitMQ设计原理解析>,结合理解一下. 我大学时流行过一个韩 ...

  3. p90x 涵盖了全部方式的健身方式美国经典训练DVD

    http://baike.baidu.com/view/2602721.htm  p90x是美国经典训练DVD, 涵盖了全部方式的健身方式13张Beachbody P90X DVD全集,90天魔鬼训练 ...

  4. P3984 高兴的津津

    题目描述 津津上高中了.她在自己的妈妈的魔鬼训练下,成为了一个神犇,每次参加一次OI比赛必拿Au虐全场.每次她拿到一个Au后就很高兴.假设津津不会因为其它事高兴,并且她的高兴会持续T天(包包含获奖当天 ...

  5. 洛谷 P3984 高兴的津津

    P3984 高兴的津津 题目描述 津津上高中了.她在自己的妈妈的魔鬼训练下,成为了一个神犇,每次参加一次OI比赛必拿Au虐全场.每次她拿到一个Au后就很高兴.假设津津不会因为其它事高兴,并且她的高兴会 ...

  6. luogu P3984 高兴的津津

    题目描述 津津上高中了.她在自己的妈妈的魔鬼训练下,成为了一个神犇,每次参加一次OI比赛必拿Au虐全场.每次她拿到一个Au后就很高兴.假设津津不会因为其它事高兴,并且她的高兴会持续T天(包包含获奖当天 ...

  7. 洛谷 题解 P3984 【高兴的津津】

    潇洒の开始 大水题一枚/小声说话 先吐槽一下: 为什么津津经历了魔鬼训练就可以Au日常QWQ,人家也是早起晚睡的好吧 (谁说魔鬼训练就一定是早起晚睡的) 思路 津津的高兴是持续m天的,但是一旦在这m中 ...

  8. P1063 高兴的津津

    题目描述 津津上高中了.她在自己的妈妈的魔鬼训练下,成为了一个神犇,每次参加一次OI比赛必拿Au虐全场.每次她拿到一个Au后就很高兴.假设津津不会因为其它事高兴,并且她的高兴会持续T天(包包含获奖当天 ...

  9. Java Web 笔记(1)

    JavaWeb 学习笔记,狂神说java,链接:https://www.bilibili.com/video/av68833391 Java Web 1.基本概念 1.1.前言 web开发: web, ...

随机推荐

  1. elk+redis分布式分析nginx日志

    一.elk套件介绍 ELK 由 ElasticSearch . Logstash 和 Kiabana 三个开源工具组成.官方网站: https://www.elastic.co/products El ...

  2. 3.python基础补充(集合,collection系列,深浅拷贝)

    一.集合 1.集合(set): 把不同的元素组成一起形成集合,是python基本的数据类型.集合元素(set elements):组成集合的成员 python的set和其他语言类似, 是一个无序不重复 ...

  3. URAL 1654 Cipher Message 解题报告

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...

  4. 双系统重装windows后修复UBUNTU的GRUB

    1.问题背景 本子是win7和ubuntu10.04双系统,用的还算好,虽然只有在用QQ的时候还会用到win7,但还是保留windows.可是几天 前,win7突然总是蓝屏.死机,更重要是的背景变成黑 ...

  5. Linux下RPM、tar.gz、DEB格式软件包的区别

      初接解Linux的朋友一定对软件的安装特别头疼,同样都是for Linux,但RPM.tar.gz.DEB包还是有很大区别的,这种区别很有可能使你的安装过程进行不下去.那我们应该下载什么格式的包呢 ...

  6. 【VirtualBox】端口转发,ssh

    端口转发 VirualBox的设置 - 网络 - 端口转发 里面有主机IP.主机端口.子系统IP.子系统端口 设置后的含义是:当外部访问主机IP:主机端口后,将会把访问映射到虚拟机的子系统IP和子系统 ...

  7. 说说localStorage

    HTML5的本地存储是大势所趋,如果仅存储在内存中,则是sessionStorage,他们的语法都是一样,仅仅是一个存储在本地文件系统中,另一个存储在内存中(随着浏览器的关闭而消失),其语句如下: l ...

  8. Android 如何让EditText不自动获取焦点

    解决之道:在EditText的父级控件中找一个,设置成 android:focusable="true"     android:focusableInTouchMode=&quo ...

  9. Solr常用查询语法笔记

    1.常用查询 q - 查询字符串,这个是必须的.如果查询所有*:* ,根据指定字段查询(Name:张三 AND Address:北京) fq - (filter query)过虑查询,作用:在q查询符 ...

  10. 使用jQuery简单实现产品展示的图片左右滚动功能

    今天要做一个产品展示功能,由于产品比较多,一屏展示不完,所以想要做一个通过点击进行翻页的效果,在网上找了几个都不大好用,最后只能自己动手写了. 效果如下所示: 原理比较简单:将要滚动显示的区域的CSS ...