#> RESTKHZ _

休止千鹤 | 我依旧是一名平凡的学生

自写PHP MVC框架(2)

  休止千鹤  |    22/12/2020

很抱歉,第一篇写完放鸽子放了这么久. 这里接着前文[这里]继续

上一篇设计到了一个请求进入index.php后,在路由之前的事情.

这篇我们跟随一个请求,看看在路由和控制器基类里发生了什么.

路由Router.class.php

路由可能是整个框架的一个败笔.
由Ugly调用start静态方法启动路由,从这里开始.为了兼容特殊uri格式,所以看起来有些奇怪的代码. 我都进行了注释.

<?php
namespace Ugly;

/**
 * Ugly Router, very ugly as its name.
 */
class Router extends Ugly
{
  /**
  * Start() do nothing but only let everything run.
  */
  public static function Start()
  {
      $uri = self::_parsing(); //这里开始,解析请求URL
      self::dispatch($uri);  //这里在解析结束后,开始分发,调用内核namespace之外的类(控制器初始化)
  }

  /*
  * Parsing URL into $uri
  * [0]=>controller [1]=>action [>2]=>params
  * Do not set any param as same as the name of the Action....
  */
  protected static function _parsing()
  {
    $uri = explode('/', trim(parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH), '/'));
    self::$controller = !empty($uri[0]) ? ucfirst($uri[0]) : self::$config['DEFAULT_ROUTE']['CONTROLLER'];//如果这里没有接收到控制器,那么就把配置中默认控制器拿出来放这里
    self::$action = !empty($uri[1]) ? $uri[1] : self::$config['DEFAULT_ROUTE']['ACTION'];//同上,默认的动作
    //cut up params into KV array 这里在分割参数并且交替放入数组.我觉得我实现这里写的很啰嗦,肯定有更好的办法.为什么分割?因为我这请求格式是restkhz.com/[c]/[a]/[参数名]/[参数]/[参数名]/[参数]
    $raw_param = array_slice($uri, 2);
    $count = count($raw_param);
    if($count==1) {
      self::$param = $raw_param;
      return;
    }
    $k=[]; $v=[]; $c=0;
    $it=$count-1;
    for ($i = 0; $i < $it; $i=$i+2) {
        $k[$c] = $raw_param[$i];
        $v[$c] = $raw_param[$i+1];
        $c++;
    }
    self::$param = array_combine($k, $v);
  }

  public static function dispatch()//分发请求
  {
    $controller = '\Controller\\' . self::$controller;
    $controllerObj = new $controller;
    if(method_exists($controller,self::$action)){//下面代码是为了兼容/post/helloworld这样的格式.此时只有控制器没有具体Action名称,所以先判断是否存在.这样的格式有利于搜索引擎爬取.
      call_user_func_array(array($controllerObj,self::$action), array(self::$param));
    } else {
      $param = self::$action;
      self::$action = self::$config['DEFAULT_ROUTE']['ACTION'];
      call_user_func_array(array($controllerObj,self::$action), array($param));
    }
  }

}

好了,到这里,一个请求完成了解析,并且开始调起具体控制器和参数.

控制器基类Controller.class.php

这里是所有控制器基类,namespace依旧是Ugly,内核空间.它应该具备所有控制器共有的功能.

  1. 加载一个视图引擎,从Ugly.class.php那里克隆过来.(我不知道这个方法好不好,但是就这样写了)
  2. 加载一些共有小部件(Widgets)这些东西是我考虑以后开发可以灵活扩展控制器公用功能, 而尽可能不要修改这个文件(这边写的有问题,所以在下面代码里已经移除)由于有点不太符合中间件定义所以改名小部件XD
  3. 检查其它控制器有没有定义init()函数,如果定义了就引导. 这样可以灵活的让每个控制器运行时,先运行一个函数,可以进行权限检查之类的. 当然一开始设想是权限检查这类的可以作为Widgets灵活插入,如此以来可以减少init()重复工作.
  4. Json函数定义, 这里初始化了Json的接收和发送.一开始也想作为Widgets无奈Widgets出了点猫饼…直接硬生生的塞这里了.不要学我,谢谢…
<?php
namespace Ugly;

//use Widget\ViewsCounter;

/**
 * Mother Controller.
 * 1. Include view engine
 * 2. Load widgets
 * 3. and some dirty functions be defined here...
 * 4. Check init() for every controller.
 * 5. Session started here
 */
class Controller
{
  public $view;
  /**
   * Reply with a json
   */
  public function echo_json($array) {
    echo json_encode($array);
  }

  /**
   * Sometimes we will get a Json in POST body.
   * So we use this func, in order to get the request
   * @return object when success
   * @return boole when...craped
   */
  public function get_json()
  {
    $raw = file_get_contents('php://input');
    $json = json_decode($raw);
    if($json){
      return $json;
    } else {
      return false;
    }
  }

  /**
   * Init $_JSON[]
   */
  private function _constructJson()
  {
    $raw = file_get_contents('php://input');
    $json = json_decode($raw, true);
    global $_JSON;
    if($json){
      $_JSON = $json;
    }
  }

  /**
   * clone a view engine from Ugly core
   */
  function __construct()
  {
      session_start();
      $this->_constructJson();
      $this->view = clone Ugly::$view;
      if (method_exists(get_called_class(), 'init')) {
        $this->init();
      }
  }

  function outputJson($json=[],$status=200,$msg='') {
      echo '{"status":' . $status . ', "data":' . json_encode($json) . ',"msg":"'. $msg .'"}';
  }

  function __destruct(){

  }
  /**
   * Load widgets here
   */
  function LoadWidgets()
  {

  }

}

Views:

 Comments


(no comments...maybe you can be the first?)