daem0n 发表于 2017-11-13 17:15

新人入坛小分享:超简化的自定义PHP小框架

写PHP后台服务的同学可能会接触到symfony、ThinkPHP、Laravel、Yii等框架,框架出现的缘由大概是前人做项目做的比较多,对于需求中常出现的功能予以封装,制定一些规则,在此框架下,使用者可以快速的搭建出自己的应用,不过,不同的框架其重量不一,学习曲线也不一样,而且对框架使用一段时间后,大多数人都会想深入源码去探究一番,那么,以下的代码希望给有需要的同学给予一些提示。

需求:实现类似http://site/module/action?params的url规则的小框架

1 框架的文件结构
|----index.php
|---config.php
|---myapp/
|---utils/
|----thirdLibs/

2 代码
2.1 index.php
<?php
    if (array_key_exists("DOCUMENT_ROOT", $_SERVER)) {
         require_once($_SERVER["DOCUMENT_ROOT"] . '/config.php');
    } else {
         require_once(dirname(__FILE__) . '/config.php');
   }
   
   $req_uri = $_SERVER["REQUEST_URI"];
   $req_path = $_SERVER["PATH_INFO"];

    /* 预处理路径 */
   $path_segs = array();
    $tmp_path_segs = explode("/", $req_path);
    foreach ($tmp_path_segs AS $k => $v) {
      if ($v != "") {
            $path_segs[] = $v;
      }
    }

    $cls_name = "";
    $method_name = "";
    /* 路由解析 */
    $path_len = count($path_segs);
    if ($path_len == 0) {
      $cls_name = "Home";
      $method_name = "index";
    } else if ($path_len == 1) {
      $cls_name = $path_segs;
      $method_name = "index";
    } else if ($path_len == 2) {
      $cls_name = $path_segs;
      $method_name = $path_segs;
    } else {
      die("未能识别的路径");
    }
    $cls_name = ucwords($cls_name);

    $req_method = $_SERVER["REQUEST_METHOD"];
    if ($req_method == "POST") {
      $post_data = file_get_contents("php://input");
      $content_type = $_SERVER["CONTENT_TYPE"];
      if ($content_type == "application/json") {
            /* 特别处理json上传的情况 */
            $post_json_obj = json_decode($post_data, true);
            $_POST = array();
            foreach ($post_json_obj AS $k => $v) {
                $_POST[$k] = $v;
            }
            //var_dump($_POST);
      }
    }

    /* 加载对应的类和方法 */
    require_once(APP_PATH . '/' . $cls_name . ".class.php");
    $ref_cls = new ReflectionClass($cls_name);
    $instance = $ref_cls->newInstance();
    $cls_method = $ref_cls->getmethod($method_name);
    $cls_method->invokeArgs($instance, array());
?>

2.2 config.php
    date_default_timezone_set("PRC");
    /* 设置项目路径,方便后面使用 */
    if (array_key_exists("DOCUMENT_ROOT", $_SERVER)) {
      define("PROJ_PATH", $_SERVER["DOCUMENT_ROOT"]);
    } else {
      define("PROJ_PATH", dirname(__FILE__));
    }
    /* 定义小功能部件的路径,即开发时你自己封装的一些功能函数或类 */
    define("UTILS_PATH", PROJ_PATH . "/utils");
    /* 定义第三方库的路径 */
    define("THIRDLIBS_PATH", PROJ_PATH . "/thirdLibs");
   /* 定义app的名称*/
    define("APP_NAME", "myApp");
   /* 设置app的路径*/
    define("APP_PATH", PROJ_PATH . "/" . APP_NAME);
    /* 加载app的配置 */
    require_once(APP_PATH . '/config.php');

3 配置
3.1 nginx
   按照路由规则,可以按照以下配置到文件中,例如myApp.conf(搜索参考ThinkPHP的nginx配置)
   log_formatmyapp.com'$remote_addr - $remote_user [$time_local] "$request" '
             '$status $body_bytes_sent "$http_referer" '
             '"$http_user_agent" $http_x_forwarded_for';
    server {
      listen       8088;
      server_name myapp.com;
      ssi on;
      autoindex off;
      ssi_silent_errors on;
      ssi_types text/shtml;

      charset utf-8;

      root /data/www/myapp;
      index index.php index.html index.htm default.html default.htm default.php;

      location / {
            try_files $uri @rewrite;
      }

      location @rewrite {
            set $static 0;
            if ($uri ~ \.(css|js|jpg|jpeg|png|gif|ico|woff|eot|svg|css\.map|min\.map)$) {
                set $static 1;
            }

            if ($static = 0) {
                rewrite ^/(.*)$ /index.php/$1 last;
                break;
            }
       }

       location ~ /backend/.*\.php$ {
      deny all;
       }

       location ~ ^(.+\.php)(.*)$ {
         fastcgi_index index.php;
         include fastcgi_params;
         set $path_info "";
         set $real_script_name $fastcgi_script_name;
         if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
               set $real_script_name $1;
               set $path_info $2;
         }
         fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
         fastcgi_param SCRIPT_NAME $real_script_name;
         fastcgi_param PATH_INFO $path_info;
         fastcgi_param SERVER_NAME $host;
         fastcgi_pass 10.51.127.68:9000;
         server_name_in_redirect off;
       }

       location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
       {
         root /data/www/bijiashufang;
         expires      30d;
       }

       location ~ .*\.(js|css)?$
       {
         expires      12h;
       }

      access_log/data/logs/wwwlogs/bijiashufang.com.logbijiashufang.com;
}

3.2 php-fpm
   略,网上搜索即可找到。

4 测试使用
在myapp目录下增加文件Home.php.class,
    class Home {
      public function __construct() {}
      public function index() {
            echo "你正在访问的是Home类index方法";
      }
    }
在浏览器上访问http://myapp.com,看是否正确

5 总结
例子比较简单,据我的理解(可能不完全正确),写框架的大致思路是这样的,然后还有加入一些功能可插拔设计、缓存加速、登录/cookie等流程的集成等,框架逐渐变重,变复杂,如果设计的比较好,接口完整稳定,那么很多功能组件就可以替代性的使用。

由于在破解方面比较小白,暂且贡献点编程上的思路,欢迎交流,谢谢!

suyam 发表于 2017-11-13 18:42

虽然不怎么了解,还是很感动
页: [1]
查看完整版本: 新人入坛小分享:超简化的自定义PHP小框架