综合演示

演示说明

框架思想 ppt

  1. 以框架衔接各技术边界, 降低成本, 提高效率
  2. 从研发到测试, 并行解决方案
  3. 上下层透明, 易于数据分布, 方便环境扩展

演示部署

  1. 下载演示代码 demo
    解压到项目根目录 /flow 中
    修改框架配置文件: 'config' => '/flow/config.php'
  2. 安装单点登录 sso
    配置框架配置文件: 'db' 连接一个数据库
    访问 /include/of/?c=of_base_sso_main 并登录 admin 123456 自动创建数据库
    修改系统分页中"sso"中 "对接" 下拉为 "前后台对接", 点击保存
  3. 访问 /flow/index.php
    用 sso 里的帐号 admin 123456 进行登录

涉及功能

  1. 单点登录系统(负责帐号及权限管理) sso
  2. htmlLoad html共享(负责静态html实现include功能) htmlLoad
  3. html模版引擎(负责无缝将html和php整合) htmlTpl
  4. 接口规则验证(负责校验数据是否符合指定规矩) data::rule
  5. 接口测试工具(负责接口单元测试) tool::check
  6. 错误日志(负责记录前后端数据库的错误)errorLog

入口讲解

/flow/index.php

<?php
/**
 * 描述 : 控制层共享文件, 控制层文件与类名相同, 以$_GET['a']作为方法名(默认index)
 */
//加载核心
require dirname(dirname(__FILE__)) . '/include/of/of.php';

//已登录
if (of_base_sso_tool::check()) {
    //展示首页界面
    $_GET += array('c' => 'flow_ctrl_main', 'a' => 'index');
    //无权访问 sso 中的权限校验, 推荐使用类似 class::action 方式设置权限键, 这样可以统一判断
    of_base_sso_tool::role("{$_GET['c']}::{$_GET['a']}") || $_GET = array('c' => 'flow_ctrl_main', 'a' => 'unRole');
//未登录
} else {
    //登录中
    if (
        isset($_GET['c']) && $_GET['c'] === 'flow_ctrl_main' && 
        isset($_GET['a']) && $_GET['a'] === 'login'
    ) {
        //启动定时器
        of_base_com_timer::timer();
    } else {
        //展示登录界面
        $_GET = array('c' => 'flow_ctrl_main', 'a' => 'door');
    }
}

//调度 类名, 动作, 安全校验,允许访问的文件返回值必须与此相同,false=不通过
$result = of::dispatch($_GET['c'], $_GET['a'], true);
//控制层返回数组时, 转换为 json 结构 接口通信核心
if (is_array($result)) echo of_base_com_data::json($result);

无权访问

展示界面 flow_ctrl_main::unRole

<?php
/**
 * 描述 : 无权访问界面
 */
public function unRole() {
    //向视图层传入基础数据 title, info
    $this->view->title = '无权访问';
    $this->view->info = '您无权访问当前页面, 请联系管理员开通';
    //通知模版引擎编译
    $this->display('/error.html');
}

模版代码 /view/error.html

<!-- 简单说, 模版就是使用 html 方式写 php 代码 -->
<h2 class="font-bold" __html="$this->title">服务器内部错误</h2>
<div class="error-desc">
    <!--<? echo $this->info; ?>-->服务器好像出错了...
    <br/><a _href="/flow/" href="index-2.html" class="btn btn-primary m-t">主页</a>
</div>

登录界面

单点登录 flow_ctrl_main::door

<?php
/**
 * 描述 : 显示登录界面
 */
public function door() {
    //调用 html模版引擎, 编译静态页面
    $this->display('/login.html');
}

登录接口 flow_ctrl_main::login

<?php
/**
 * 描述 : 登录帐号
 */
public function login() {
    if (isset($_POST['user']) && isset($_POST['pwd']) && isset($_POST['captcha'])) {
        //验证通过
        if (of_base_com_com::captcha($_POST['captcha'])) {
            //校验用户名和密码 调用 sso 接口
            $state = of_base_sso_tool::login(array(
                'user' => &$_POST['user'],
                'pwd'  => &$_POST['pwd']
            ));

            //登录成功
            if ($state === true) {
                echo 'done';
            //登录出错
            } else if ($state) {
                echo $state['msg'];
            //登录失败
            } else {
                echo '帐号密码错误';
            }
        //验证失败
        } else {
            echo '验证码错误';
        }
    }
}

单点退出 flow_ctrl_main::logout

<?php
/**
 * 描述 : 退出帐号
 */
public function logout() {
    //调用 sso 退出
    of_base_sso_tool::logout();
    L::header(ROOT_URL . '/flow/index.php');
}

接口演示

请求验证 flow_ctrl_main::__construct

<?php
/**
 * 描述 : 请求验证, 放在构造函数中的验证可以进行单元测试
 */
public function __construct() {
    //定义全局规则
    $rule = array(
        'getMsgs' => array(
            'get' => array(
                'size' => 'int'
            )
        )
    );

    L::rule($rule);
}

实现接口 flow_ctrl_main::getMsgs

<?php
/**
 * 描述 : 获取消息列表
 * 注明 : 
 *      标准响应结构 {
 *          "code" : 正整型, 200 成功, 400 请求参数类型校验失败, 
 *              3xx 半失败半成功, 且有效
 *              4xx 因请求参数导致的错误
 *              5xx 因内部错误导致的问题
 *          "data" : 可扩展的数据数据
 *          "info" : 字符串的响应信息
 *      }
 */
public function getMsgs() {
    $data = array(
        'list' => array(
            array(
                'img'   => '/img/a1.jpg',
                'name'  => '谨斯里',
                'title' => '上传了一个文件',
                'time'  => '2014.11.8 12:22',
                'msgs'  => '消息1',
            ), ...
        )
    );
    return array(
        'code' => 200,
        'data' => &$data,
        'info' => "读取成功"
    );
}

数据填充 /flow/view/index.html

<div id="ibox" _style="'display: none;'" class="ibox-content">
    <div name="list" class="feed-activity-list">
        <div v-for="item in list" class="feed-element">
            <img name="img" class="pull-left img-circle" :src="VIEW_URL + item.img" src="img/a1.jpg">
            <div class="media-body ">
                <small name="time" class="pull-right" v-text="item.msgs">5分钟前</small>
                <strong name="name" v-text="item.name">谨斯里</strong> 
                <font name="title" v-text="item.title">上传了一个文件</font>
                <br>
                <small name="msgs" class="text-muted" v-text="item.time">2014.11.8 12:22</small>
            </div>
        </div>
    </div>
</div>

<script>
//通过接口填充数据
$.post(ROOT_URL + '/flow/index.php?c=flow_ctrl_main&a=getMsgs&size=5', function (data) {
    //标准响应结构
    if (data.code === 200) {
        //利用 Vue 填充数据
        var app = new Vue({
            el: $('#ibox').show().get(0),
            data: {
              list: data.data.list
            }
        });
    }
    L.open('tip')('提示消息: ' + data.info);
}, 'json');
</script>

接口测试

请求验证 flow_ctrl_main::apiTest

<?php
/**
 * 描述 : 接口测试
 */
public function apiTest() {
    //模拟GET, POST, COOKIE 等数据
    //$_POST = array('aa' => '123');
    $error = of_base_tool_test::check('flow_ctrl_main', 'getMsgs');

    if ($error) {
        echo '<pre>';
        echo 'flow_ctrl_main::getMsgs    ';
        echo '<a href="?c=flow_ctrl_main&a=apiTest&size=1" style="color: red;">传入size为int的get参数会响应正确信息</a> ';
        print_r($error);
        echo '</pre>';
    } else {
        echo '无数据返回';
    }
}

错误提示

  1. 在debug模式下,出现错误时会有醒目的信息提示
  2. 不管是否debug模式,都可以通过访问 框架目录/index.php?c=of_base_error_tool 来查阅以往错误的详细信息