php 魔鬼训练

环境配置

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


}
?>

 

posted @ 2016-08-06 18:50  贝尔塔猫  阅读(448)  评论(0编辑  收藏  举报