搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > OpenFramework > 【php开源】一个mvc框架的诞生之Application类input方法

【php开源】一个mvc框架的诞生之Application类input方法

OpenFramework 2018-02-28

开篇说明过,我所实现的框架全局都由Application类接管。那么接下来将讲到对于一个动态网站很重要的功能-——‘数据接收’。


我所设计的不管是表单数据还是url传值乃至$_SERVER,$_COOKIE,$_ENV,php://input等都通过Applicaiton::input()进行获取。那么接下来将讲解下如何做到一个方法获取。并且还得注意一点也是非常重要的一点,数据过滤。这点对于安全来讲非常重要,那么我将通过自定义闭包函数以及内置方法来实现自定义过滤方法与默认过滤方法


回顾第一篇讲到的,框架启动通过Application::run()方法,执行Application::check()检测框架运行环境,如果是路由机制,调用linkphp\boot\Env::requestRouterHandle()方法,处理路由请求


具体class::Env类代码段


namespace linkphp\boot;
use linkphp\Application;

class Env
{

   static private $_instance;

   private $_request;

   private $_env;

   static public function getInstance()
   {
       if(!isset(self::$_instance)){
           self::$_instance = new self();
       }
       return self::$_instance;
   }

   //操作相应模式
   public function selectEnvModel($_env_object)
   {
       $this->_env = Application::get('envmodel');
       $this->_request = Application::get('request')
->
request();
       return $this;
   }

   public function requestRouterHandle()
   {
       $this->_request->setQueryParam();
       $this->_env->initialize();
       return $this;
   }

   public function requestCmdHandle()
   {
       $this->_request->setCmdParam(
Application::
input('server.argv'));
       $this->_env->initialize();
       return $this;
   }

}


进入Env::requestRouterHandle()方法,首先设置请求参数,进入linkphp\boot\http\HttpRequest::serQueryParam()方法


namespace linkphp\boot\http;

class HttpRequest
{

   private $cmd;

   private $cmd_param = [];

   private $cookie;

   private $env;

   private $server;

   private $_response;

   private $_input;

   private $queryParam = [];

   //请求方法
   private $request_method;

   //数据
   private $data;

   private $request_http_accept = 'json';

   public function __construct(ResponseDriver $response,

Input $input)
   {
       $this->_response = $response;
       $this->_input = $input;
   }

   public function setData($data)
   {
       $this->data = $data;
       $this->_response->setRequest($this);
       return $this;
   }

   public function setRequestMethod($method)
   {
       $this->request_method = $method;
       $this->_response->setRequest($this);
       return $this;
   }

   public function setRequestHttpAccept($accept)
   {
       $this->request_http_accept = $accept;
       $this->_response->setRequest($this);
       return $this;
   }

   public function getData()
   {
       return $this->data;
   }

   public function getRequestMethod()
   {
       return $this->request_method;
   }

   public function getRequestHttpAccept()
   {
       return $this->request_http_accept;
   }

   /**
    * 响应请求返回response 实例对象
    * @return Object[ResponseDriver] $this->_response
    */
   public function setResponse()
   {
       $this->_response->getDriver()->setResponse(
$this
->_response->getDriver()->output($this->data));

       return $this->_response->getDriver();
   }

   /**
    * 响应请求输出结果
    * @return $this->_request_http_accept
    */
   public function send()
   {
       $this->_response->getDriver()->setResponse(
$this
->_response->getDriver()->output($this->data))->send();
   }

   /**
    * 当前请求 HTTP_CONTENT_TYPE
    * @access public
    * @return string
    */
   public function contentType()
   {
       $contentType = $this->server('CONTENT_TYPE');
       if ($contentType) {
           if (strpos($contentType, ';')) {
               list($type) = explode(';', $contentType);
           } else {
               $type = $contentType;
           }
           return trim($type);
       }
       return '';
   }

   public function start()
   {
       return $this;
   }

   public function isMethod($method)
   {
       return $this->getRequestMethod() === $method;
   }

   public function isGet()
   {
       return $this->isMethod('get');
   }

   public function isPost()
   {
       return $this->isMethod('post');
   }

   public function isDelete()
   {
       return $this->isMethod('delete');
   }

   public function isPut()
   {
       return $this->isMethod('put');
   }

   public function isPatch()
   {
       return $this->isMethod('parch');
   }

   public function isHead()
   {
       return $this->isMethod('head');
   }

   public function isOptions()
   {
       return $this->isMethod('options');
   }

   public function setQueryParam()
   {
       $this->queryParam = array_merge($this->get(),

$this->post(),
$this
->file(),$this->server(),$this->cookie(),$this->env());
       return $this;
   }

   public function get($key='',$filter='')
   {
       return $this->_input->get($key,$filter);
   }

   public function post($key='',$filter='')
   {
       return $this->_input->post($key,$filter);
   }

   public function file($key='')
   {
       return $this->_input->file($key);
   }

   public function server($key='')
   {
       return $this->_input->server($key);
   }

   public function cookie($key='')
   {
       return $this->_input->cookie($key);
   }

   public function env($key='')
   {
       return $this->_input->env($key);
   }

   public function getInput($filter='')
   {
       return $this->_input->getInput($filter);
   }

   public function input($key = '',$filter)
   {
       if ($pos = strpos($key, '.')) {
           // 指定参数来源
           list($method, $key) = explode('.', $key, 2);
           if (in_array($method, ['get', 'post', 'file',
'server',
'cookie', 'env'])) {
               return $this->$method($key,$filter);
           }
       }
       return $key=='' ? $this->queryParam[$key] :
$this
->queryParam[$key];
   }

   public function setCmdParam($command)
   {
       if(is_array($command) && count($command)>1){
           $this->cmd = $command[1];
       }
   }

   public function cmd($key)
   {
       return $this->cmd_param[$key];
   }

}


设置请求参数方法


public function setQueryParam()
{
   $this->queryParam = array_merge($this->get(),$this->post(),
$this
->file(),
$this
->server(),$this->cookie(),$this->env());
   return $this;
}


将本次请求的所有get ,post,file,cookie,server,env等参数全部进行合并保存至$this->queryParam属性中。通过这个方法即将本次请求的相关参数全部存储,那么如何用到就是接下来要将的重点。


回到Application::input()input方法中


static public function input($param,$filter='')
{
   return self::httpRequest()->input($param,$filter);
}


最终调用的也是linkphp\boot\http\HttpRequest::input()方法接收两个参数一个键值一个过滤方法,上面也贴了代码段,回到上面看看具体实现了哪些功能


public function input($key = '',$filter)
{
   if ($pos = strpos($key, '.')) {
       // 指定参数来源
       list($method, $key) = explode('.', $key, 2);
       if (in_array($method, ['get', 'post', 'file',
'server', 'cookie', 'env'])) {
           return $this->$method($key,$filter);
       }
   }
   return $key=='' ? $this->queryParam : $this->queryParam[$key];
}


首先第一个参数可以通过input('test')或者具体调用get获取其他参数则通过,input('get.test')则只会从get请求的参数中获取


接下来我们以get请求参数获取为例,看看HttpRequest::get()方法做了哪些


public function get($key='',$filter='')
{
   return $this->_input->get($key,$filter);
}


框架初始化后就会通过构造方法将linkphp\boot\http\Input()类注入保存到$this->_input属性中那么最终调用的是linkphp\boot\http\Input::get()方法,看下执行代码段


public function get($key='',$filter)
{
   return $key=='' ? $this->param($_GET,$filter) :
$this->param($_GET[$key],$filter);
}


调用了Input::param()


public function param($data,$filters)
{
   $filter = $this->getFilter($filters);
   if (is_array($data)) {
       array_walk_recursive($data, [$this, 'filterValue'],

$filter);
       reset($data);
   } else {
       $this->filterValue($data,'',$filter);
   }
   return $data;
}


首先获取过滤方法调用Input::getFilter()方法,之后判断传入的传入的数据是否是数组,如果是数组通过array_walk_rocursive方法依次将数组中元素传入本类中filterValue方法中进行过滤


private function getFilter($filter)
{
   $filter = $filter ?: $this->filter();
   if (is_string($filter) && false === strpos($filter, '/'))
{
       $filter = explode(',', $filter);
   } else {
       $filter = (array) $filter;
   }
   return $filter;
}


public function filterValue(&$value,$key,$filters)
{
   foreach($filters as $filter){
       if($filter instanceof Closure){
           // 调用函数或者方法过滤
           $value = call_user_func($filter, $value);
       }
   }
   return $this->filterExp($value);
}


最终实现的自定义闭包过滤方法也是通过本类filterValue方法中进行实现,将传入的过滤参数判断是否为闭包函数如果是进行执行闭包,在这里是用引用参数传递保证

【php开源】一个mvc框架的诞生之Application类input方法


Happy New Year | 新年快乐


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《【php开源】一个mvc框架的诞生之Application类input方法》的版权归原作者「开源助手」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注开源助手微信公众号

开源助手微信公众号:oshelper

开源助手

手机扫描上方二维码即可关注开源助手微信公众号

开源助手最新文章

精品公众号随机推荐