Controller

目录
[隐藏]

跟所有的Web 框架一样,Yangzie的Controller也是负责处理Web请求,每一个URL地址,只会映射到一个具体的控制器方法(action,见路由请求)中,在该方法中处理请求,并返回响应(Response)。

action中代码基本上分层三块:

// 获取数据
// 逻辑处理
// 设置数据给视图

获取数据的方式在不同的请求方法中稍许有点出入,后面会进行说明。

对应一个应用系统,逻辑处理通常是数据操作(见model)、接口调用等,最后把处理的结果设置给响应视图(通常情况下响应是返回视图,也可以是一个重定向YZE_Redirect)。

视图负责展示处理数据,展示的数据由action通过$this->set_view_data(‘key’, $value)设置;视图文件中通过$this->get_data(‘key’)来获取,yangzie的视图模版是php和html混和输出的模版文件。

http 有多种请求方法,Yangzie都支持,通常用得最多的是GET,POST和OPTIONS方法,当我们通过scripts脚本自动生成action时,该action是负责处理GET请求的方法,

GET请求:拉取一个响应,比如视图(html,json,xml…)
POST: 提交数据并得到一个响应,比如json
OPTIONS:用于跨站请求前向服务端咨询允许的头部信息或允许的源站信息等

1.GET请求

比如我们在test模块下增加add控制器,并用默认的action名时,生成的代码如下:

    public function index(){
        $request = $this->request;
        //$this->layout = 'tpl name';
        $this->set_view_data('yze_page_title', 'this is index in controller add');
    }

这里采取缺省的路由映射/test/add 映射到test模块,add_controller.class.php的index方法,浏览器上访问这个地址,就会进入index方法,并响应action对应的视图文件:views/add-index.tpl.php,关于控制器的action和起视图的关系,见视图系统

在GET请求中可以通过$this->request来获取请求中的数据,分别是:

  1. $this->request->get_from_get(“query name”): 获取地址上的get参数值
  2. $this->request->get_from_cookie(“query name”): 获取cookie的值
  3. $this->request->get_from_server(“query name”): 获取$_SERVER中的值,里面是一些环境变量

GET方法的视图是一个模版文件,位于views中,模版文件的命名规则是控制器名-action名.视图格式.php

  1. 控制器名,比如上面的add,注意控制器的文件名是控制器名_controller.class.php, 控制器的类名是控制器名_Controller
  2. action名,比如上面的index
  3. 视图格式,这是Yangzie视图系统独有的设计,响应的内容格式可以根据请求的url的后缀进行自动区分,比如/test/add则返回默认的tpl(HTML)视图;/test/add.json则返回json内容;/test/add.pdf,下载pdf文件;/test/add.jpeg,下载jpeg图片;
    对于tpl视图,对应一个布局文件,位于app/vendor/layouts/tpl.layout.php。布局文件负责构建HTML的主体内容,具体的action返回的只是里面的部分内容。

当然,GET请求也可以不用默认的模版文件输出响应,可以采用yangzie的其他响应类,也可以用其他action的模版,具体见视图系统

2.POST请求

post请求只是对一个URL的另外一种HTTP请求方式,在action上值需要单独定义个public方法,并以post_开头接口处理post请求,比如如果要post提交给/test/add,那么只需要定义如下的方法(post方法的定义需要手工添加,无法用脚本生成):

    public function post_index(){
        $request = $this->request;
    }

可以看到和GET请求映射的action比,就多了post_前缀,当POST请求时就会进入post_index方法。

POST请求获取数据的方式时通过$this->request->get_from_post(‘name’),当然获取的数据是需要以form表单形式提交的数据,如果是raw数据,需要通过file_get_content(‘php://input’)获取

POST处理结束后,如果没有指定任何响应,那么回返回GET请求的模版内容。
yangzie建议POST的响应要么返回一个YZE_REDIRECT重定向(适用于浏览器端原生表单提交的方式);或者返回一个接口调用的结果,比如JSON或者XML(适用于AJAX调用,或者接口调用)。

POST的响应和GET又些许不一样,对于浏览器来说,GET是回退无害的,并且GET会记录到浏览历史中,而POST不会,这意味着POST请求访问后,如果直接返回了GET请求的模版,那么可能导致浏览器上用户在会退时,可能导致不希望的结果。

3.OPTIONS请求

OPTIONS是一个特殊的请求,通常用户在跨越访问时,浏览器向服务端咨询服务器支持的内容,这些内容通常都以Header的方法体现,所以OPTIONS不会返回实际的内容,返回的都是一些HEADER,OPTIONS并不会进入具体的action方法执行,只会调用controller的response_headers方法,所以,每个控制器可以根据情况返回响应的Header即可

    public function response_headers()
    {
        return [
            "Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token, Redirect",
            "Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH",
            "Access-Control-Allow-Origin: *"
        ];
    }

4.其他HTTP请求

如果需要支持其他请求,那么只需要跟post一样,再定义一个方法并且用HTTP请求方法名作为前缀即可,比如delete_

5.异常处理

yangzie建议控制器中的action方法中除了返回响应外,不要有任何其他的输出,比如echo等,虽然这些输出最终也会返回到前端,但这些输出没在yangzie的响应处理体系中,他们的输出位置是不能控制的。

如果action中的逻辑处理出现了错误,则抛出异常即可,yangzie会捕获异常,并进行一些善后处理,比如回滚数据库的事物,同时提供一个给开发者最终如何处理异常的位置,就是控制器的exception方法,该方法默认的实现逻辑如下:

    public function exception(\Exception $e){
        $request = $this->request;
        $this->layout = 'error';
        //Post 请求或者返回json接口时,出错返回json错误结果
        $format = $request->get_output_format();
        if (!$request->is_get() || strcasecmp ( $format, "json" )==0){
        	$this->layout = '';
        	return YZE_JSON_View::error($this, $e->getMessage());
        }
    }

默认情况下,出错会使用error布局展示错误(位于app/vendor/layouts/error.layout.php),同时如果请求是非get请求或者明确指定了json响应格式,比如foo/bar.json,则不适用布局,并且返回json格式的错误结构体(见视图系统