thinkPHP

来源:互联网 发布:先科s608数据升级网址 编辑:程序博客网 时间:2024/06/03 03:15

一、           Introduction

Php框架是很多代码的集合。这些代码是程序结构的代码而不是业务代码。代码中有许多函数、类、功能类包。框架的代码按照一定标准组成一个有机的功能体,这个功能体里边有许多设计模式如mvc、单例、ar等。

使用框架的好处,快速、稳定、高效的搭建程序系统;维护性、灵活性、适应客户需求得到最大化加强;注意力集中在业务层面;节省代码工作量。

常见的框架

Zendframeword,php语言公司发布的,功能丰富,重量级框架。

Yii,自己人的框架,重量级框架,纯oop框架,将代码的重用性发挥到了极致,速度非常快。

Cakephp,运用诸如ActiveRecord、AssociationDataMapping、FrontController和MVC等著名设计模式的快速开发框架。

Symfony,一个基于MVC模式的面向对象的php5框架。

thinkPHP,轻量级框架。内如oop和面向过程代码都存在,自己人的框架。早起的思想来源于struts,使用面向对象的开发结构和MVC模式,融合了struts的action和dao思想和jsp的tablig,ror的orm映射和activerecord模式,封装了crud和一些常用操作,单一入口模式。

Thinkphp的目录结构

到官网下载,然后解压。其中,Application目录,存放开发的项目;public,存放静态资源文件。thinkPHP,存放框架资源文件。其中,commem,存放函数库;conf,放配置文件;lang,语言包;library,资源文件目录。ThinkPHP.php,框架接口文件,每个应用都要引入。在library目录中,behavior,行为文件目录;think,框架功能类目录;vendor,第三方完整功能目录包,比如smarty。在think目录中,App.class.php、Think.class.php是外界使用需要的文件。

二、           使用入门

1.       自动搭建项目系统架构

将thinkphp目录拷贝到工作站目录下,然后创建三个项目目录,比如shop、book、car等。

在shop目录下创建一个接入文件,index.php,内容为:

<?php

//利用thinkphp开发shop商城系统

//入口程序文件

 

//引入接口文件,ThinkPHP/ThinkPHP.php

include ("../ThinkPHP/ThinkPHP.php");

然后,运行这个接口目录,就会在shop目录中,自动生成项目系统的目录架构。

2.       路由形式

路由是,系统从RUL参数中分析当前请求的分组、控制器和操作的过程。

为了是访问路由看起来好看,更具有隐蔽性,thinkphp提供了4种书写路由的形式。

基本的get形式http://网址/index.php?m=分组&c=控制器&a=操作方法

Pathinfo路径形式默认的方式http://网址/index.php/分组/控制器/操作方法

Rewrite重写形式,使用伪静态技术省略index.php入口文件http://网址/分组/控制器/操作方法

兼容形式http://网址/index.php?s=/分组/控制器/操作方法

3.       创建控制器

<?php

/*

 * 创建前台分组的会员控制器

 */

namespace Home\Controller;

use Think\Controller;

//父类Controller:ThinkPHP/LIbrary/Think/Controller.class.php

class UserController extends Controller {

    //登陆系统

    public function login(){

        echo"loginning";

    }

}

4.       创建视图模版

为了便于开发,可以设置错误模板模式。在index.php入口文件设置define(“APP_DEBUG”, true);//生产模式define(“APP_DEBUG”, false)//生产模式。

在文件目录中,创建好模板。在控制器中,调用模板:

    public function login(){

        //调用视图

        //display(),是父类controller的方法

        //$this->display();//没有传参,视图模版名称与当前操作方法名称一致 

//       $this->display("register");//调用当前User视图模板下的其他的模板文件

       $this->display("Goods/showlist");//调用其他控制器下的模板文件

    }

5.       将已有的模板与tp框架相结合

在home目录下创建Public目录,在Public目录下创建css目录、js目录、img目录。将已有模板的对应文件copy到对应目录下。然后在视图中引入css等文件。

在模板中引入css文件,最好不要使用相对路径,会受到路由的影响。请使用绝对路径。如果是外部css文件中的图片,请使用相对路径引入,是相对于css文件本身的。为了维护的方便,可以在入口文件中设置css、图片文件、js的引用地址为常量。比如:

//设置css、图片文件、js的引用地址常量

define("CSS_URL","/tp/shop/Home/Public/css/");

define("IMG_URL","/tp/shop/Home/Public/img/");

define("JS_URL","/tp/shop/Home/Public/js/");

6.       后台页面搭建

关于分组设置,同一个项目中,由于业务规则的划分,有多个相关的功能模板,它们都有独立的控制器、view视图、配置文件、函数库文件等,为了开发维护方便,就给它们创建独立的分组,每个分组有自己的一套。

在shop目录下,创建一个Admin目录。在Admin目录下创建Controller目录、View目录。

创建后台控制器,ManagerController.class.php。类似前端的方式,在后台,结合tp框架和模板文件。

比如,首页控制器:

<?php

 

/*

 * 后台首页控制器

 */

namespace Admin\Controller;

use Think\Controller;

class IndexController extends Controller {

    //头部

    public function head(){

        $this->display();

    }

   

    //左侧

    public function left(){

        $this->display();

    }

   

    //右侧

    public function right(){

        $this->display();

    }

   

    //集成页面

    public function index(){

        $this->display();

    }

}

在页面中,如果使用了frame,其中有src引入文件,不要使用相对路径,要使用绝对路径,以免受路由影响。Tp框架提供了一些常量,以减少代码工作量,其中部分如下:

__MODULE__:路由地址分组信息(/shop/index.php/分组)

__CONTROLLER__:路由地址控制器信息(/shop/index.php/分组/控制器)

__ACTION__:路由地址操作方法信息(/shop/index.php/分组/控制器/操作方法)

__SELF__:路由地址的全部信息(/tp/shop/index.php/分组/控制器/操作方法/名称/值/名称/值)

MODULE_NAME:分组名称

CONTROLLER_NAME:控制器名称

ACTION_NAME:操作方法名称

比如:

<frame  name=left src=”__CONTROLLER__/left.html” frameborder=0  noresize />

7.       相关细节

关于配置文件,有ThinkPHP/Conf/conversion.php,系统主要配置文件;shop/Common/Conf/Config.php,当前shop项目的配置文件;shop/Home/Conf/config.php,当前shop项目的Home分组的配置文件。如果存在同名的配置变量,后者会覆盖前者。系统里面并不是全部变量都是在conversion.php里面定义,此外,在Behavior行为文件里边有定义一部分,在框架的代码角落里边有零星的一点。

关于跟踪信息,需要在配置文件里面定义配置变量,SHOW_PAGE_TRACE,C()函数可以读取或设置配置变量,如C(name, value)设置,C(name)读取。在自己项目里面设置跟踪信息,比如在shop的common/conf/config.php中,

<?php

return array(

       //'配置项'=>'配置值'

    //使页面底部显示跟踪信息

    'SHOW_PAGE_TRACE' => true,

);

可以在控制器中,设置哪里需要显示跟踪,哪里不需要显示跟踪,比如:

    public function head(){

        //设置配置信息,使得头部不要显示跟踪信息

        C('SHOW_PAGE_TRACE',false);

        $this->display();

}

关于默认分组设置,如果不设置分组,浏览器会默认index.php紧跟着的为分组。因为tp框架系统没有比较,要给其设置一个比较参数。复制conversion.php中的DEFUALT_MODULE到shop的配置文件下。比如:

<?php

return array(

       //'配置项'=>'配置值'

    //使页面底部显示跟踪信息

    'SHOW_PAGE_TRACE' => true,

    //设置默认分组

    'DEFAULT_MODULE' =>'Home',//系统默认

    //允许访问的分组信息

    'MODULE_ALLOW_LIST' =>array('Home', 'Admin'),

);

8.       关于框架的两种模式

即开发设计模式和生产模式。

开发模式,每次请求会加载每个应用程序文件,比较耗费资源,错误提示友好,会自动清除common-runtime.php文件,会依次加载每个需要的文件。

生产模式,该模式比较节省资源,会把请求过程中的一些通用程序文件给编译到一个文件里边,错误信息模糊,不方便调试。

三、           开启smarty模版引擎

在conversion.php文件中,可以设置模板引擎。将'TMPL_ENGINE_TYPE'      => 'Think',     // 默认模板引擎 以下设置仅对使用Think模板引擎有效拷贝到shop项目的配置文件中。将值改为Smarty,比如:

<?php

return array(

       //'配置项'=>'配置值'

    //使页面底部显示跟踪信息

    'SHOW_PAGE_TRACE' => true,

    //设置默认分组

    'DEFAULT_MODULE' =>'Home',//系统默认

    //允许访问的分组信息

    'MODULE_ALLOW_LIST' =>array('Home', 'Admin'),

    //设置smarty模板引擎

    'TMPL_ENGINE_TYPE'      => 'Smarty',     // 默认模板引擎

);

关于smarty模板{}标记有冲突的解决。

{}与css或js有冲突,在{}与内容中间设置空格;使得{}左右标记符换行;外部引入css、js;设置{literal}{/literal};变换smarty的标记符号。

可以通过配置TMPL_ENGINE_CONFIG配置变量为Smarty做相关配置。比如:

<?php

return array(

       //'配置项'=>'配置值'

    //使页面底部显示跟踪信息

    'SHOW_PAGE_TRACE' => true,

    //设置默认分组

    'DEFAULT_MODULE' =>'Home',//系统默认

    //允许访问的分组信息

    'MODULE_ALLOW_LIST' =>array('Home', 'Admin'),

    //设置smarty模板引擎

    'TMPL_ENGINE_TYPE'      => 'Smarty',     // 默认模板引擎

    //配置smarty相关变量

    'TMPL_ENGINE_CONFIG' =>array(

        'left_delimiter' =>'**',

        'right_delimiter' => '##',

    ),

);

在模板页面中

**literal##内部内容不会被smarty解析**/literal##

四、           数据库操作Model模型

1.       数据库设置

在conversion.php中,有相关的设置变量。由于同一个框架下有多个项目,每个项目的数据库信息有所不同,所以拷贝到shop项目,进行设置。比如:

        /* 数据库设置 */

    'DB_TYPE'               =>  'mysql',    // 数据库类型

    'DB_HOST'               =>  'localhost', // 服务器地址

    'DB_NAME'               =>  'shop',          // 数据库名

    'DB_USER'               =>  'root',     // 用户名

    'DB_PWD'                =>  '123456',          // 密码

    'DB_PORT'               =>  '3306',       // 端口

    'DB_PREFIX'             =>  'sw',   // 数据库表前缀

    'DB_PARAMS'                =>  array(), // 数据库连接参数   

    'DB_DEBUG'                   =>  TRUE, // 数据库调试模式 开启后可以记录SQL日志

    'DB_FIELDS_CACHE'       => true,        // 启用字段缓存

    'DB_CHARSET'            =>  'utf8',     // 数据库编码默认采用utf8

2.       创建Model类

<?php

 

/*

 *goods模型

 */

namespace Model;

use Think\Model;

//父类Model:Think/Library/Think/Model.class.php

class GoodsModel extends Model {

   

}

然后实例化goodsmodel,需要体现命名空间

    public function showlist(){

        $goods = new\Model\GoodsModel();

        dump($goods);

        $this->display();

    }

对于数据库表中没有前缀的表,或者特殊的表,在定义model时需要声明表的真名,比如:

<?php

/*

 *特殊表的模型

 */

namespace Model;

use Think\Model;

//父类Model:Think/Library/Think/Model.class.php

class EnglishModel extends Model {

    protected $trueTableName ="english";

}

3.       实例Model对象的两种方式

实例化普通model对象,使用$model = new \Model\xxxModel();

实例化基类Model对象,可以实现对数据库的基本操作。

$model = D();//实例化基类Model,没有关联任何表

$model = D(‘Goods’);//实例化父类Model对象,并操作xx_goods业务数据表。即使不创建具体model模型类文件,也可以对数据表的数据进行操作。

如果一个数据表没有特殊的方法要求,可以通过D(xxx)进行操作。

比如:

    public function showlist(){

        //实例化普通model对象

//        $goods = new\Model\GoodsModel();

//        dump($goods);

        //实例化基类model对象

//        $obj = D();//实例化父类model对象

        $obj = D('User');

        dump($obj);

        $this->display();

    }

五、           数据基本操作

1.       数据查询操作

调用方法,model对象->select();

具体:

$model->select();

$model->select(主键,id值);

$model->select(‘id1,id2,id3,…’);//查询主键信息在条件范围内的记录

使用select()方法会始终返回一个二维数组。

比如:

    public function showlist(){

        //实例化普通model对象

        $goods = new\Model\GoodsModel();

        $info =$goods->select();

        $info =$goods->select(12);

        $info =$goods->select("12,13,14");

//        dump($info);

        //以下两个方法被直接定义到父类controller里面,对smarty相关方法的封装

        $this->assign('info',$info);

        $this->display();

    }

查询中的辅助方法

Where()条件$model->where(条件值);//条件值就是sql语句中where后边的结果值

Limit()限制条数$model->limit(数字);//严格查询数字条数的记录

Field()限制查询字段$model->field(字段1,字段2,字段3);

Order()排序$model->order(‘排序条件asc/desc’);

Group()分组查询groupby,$model->group(分组条件);

Having()条件设置方法。Having设置条件的效果与where使用效果类似。区别是where语句的字段,必须是数据表中存在的字段;having语句字段必须是查询结果集中存在的字段。

比如:

    public function showlist(){

        //实例化普通model对象

        $goods = new\Model\GoodsModel();       

//        $info =$goods->select(12);

//        $info =$goods->select("12,13,14");

//        dump($info);

        //设置查询条件

        $goods ->where("goods_name like '%基%' and goods_price > 1500");

        $info =$goods->select();

        //limit限制条数

        $goods -> limit(5);

        $info =$goods->select();

        $goods -> limit(21,9);

        $info =$goods->select();

        //field,限制查询字段

        $goods ->field('goods_name,goods_price');

        $info =$goods->select();

        //排序

        $goods ->order("goods_price desc");

        $info =$goods->select();

        //分组查询

        $goods ->group("goods_brand_id");

        $goods ->field("goods_brand_id,count(*)");

        $info = $goods->select();

       // dump($info);

       //having

        $goods ->having("goods_price > 1000");

        $info =$goods->select();

        //以下两个方法被直接定义到父类controller里面,对smarty相关方法的封装

        $this->assign('info',$info);

        $this->display();

    }

以上具体方法使用的时候可以一并使用多个,形成连贯操作,没有顺序要求。比如:

    public function showlist(){

        //实例化普通model对象

        $goods = new\Model\GoodsModel();       

//        $info =$goods->select(12);

//        $info =$goods->select("12,13,14");

//        dump($info);

//        $info = $goods ->group('goods_brand_id') -> field("goods_brand_id,count(*)") ->select();

//        dump($info);

        $info = $goods ->where('goods_price > 1000') -> field("goods_name,goods_price")-> select();

        $this->assign('info',$info);

        $this->display();

    }

2.       添加数据

调用方法,model对象->add()

具体有两种使用方式

数组方式$数组 = array(元素(键名=>值),元素(键名=>值),…);$model(普通对象)->(数组);

注意,数组的元素键名与数据表字段的名称必须一致。

AR(Active Record活跃记录)方式

$model->属性= 值;

$model->属性= 值;

$model->add();

AR规范要求,一个model模型类与一个具体的数据表对应;model模型的实例化对象与数据表的一条记录对应;model对象的属性与记录的字段对应。Tp框架的AR是仿真产品,因为每个业务model模型类里并不存在对应数据表的字段。

add()方法返回新纪录的主键id值。

比如:

    //添加商品

    public function tianjia(){

        $goods = D('Goods');

        //数组方式添加

//        $arr = array(

//           'goods_name' =>'haha',

//            'goods_price' =>500,

//            'goods_weight'=> 12,

//            'goods_number'=>23,

//        );

//        $z =$goods->add($arr);

//        dump($z);

        //AR方式添加

        $goods -> goods_name ="heihei";

        $goods -> goods_price= 443;

        $goods -> goods_number= 23;

        $goods -> goods_weight= 13;

        $z = $goods->add();

        dump($z);

        $this->display();

    }

3.       数据修改操作

调用方法:model对象->save();

有两种方式

数组方式,$model->save(数组);

注意:数组的元素下标属性字段必须与数据表字段保持一致。

AR方式,$model->属性(字段)=值; $model->属性(字段)=值;$model->save();

save()方法返回为受影响的记录条数。

注意:数据修改必须设置条件,主键id或where()方法,二选一,否则失败。

    public function upd(){

        $goods = D('Goods');

//        $goods -> goods_id =155;

        $goods -> goods_name ="heheh";

        $goods -> goods_price= 323;

        $goods -> goods_number= 23;

        $z = $goods ->where("goods_id > 160") -> save();

        dump($z);

        $this->display();

    }

4.       后台实现商品添加

1)       制作添加表单

注意表单元素的属性名与数据表字段的对应。

2)       商品控制器,进行判断添加

    public function tianjia(){

        $goods = D('Goods');

        //判断是展示还是收集信息

        if (!empty($_POST)) {

//            dump($_POST);

            $z = $goods ->add($_POST);

            if ($z) {

                //页面跳转

               //$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);

               // $this ->redirect("showlist",array(), 2, '数据添加成功');

                //如果设置参数,可以get方法传递,比如

                $this ->redirect("showlist",array('name' => 'hah','age' => 12), 2, '数据添加成功');          

            } else {

                $this ->redirect("tianjia",array(), 2, '数据添加失败');

            }

        } else {

            $this ->display();

        }     

    }

3)     窗体顶端

5.       后台实现商品修改

首先get参数的传递,需要修改为路由形式,比如:<a href=”{$smarty.const.__CONTROLLER__}/upd/goods_id/{$v.goods_id}”>修改</a>

然后,控制操作方法接收get参数,可以不需要使用$_GET方法,而是通过方法的形参接收,这类似某些其他语言的框架的方法。

    //三个形参的方式是给upd方法传递的形参

    public functionupd($goods_id){

        $goods = D('Goods');

        //dump($goods_id);

//        dump($height);

//        dump($addr);

        //find()方法获得数据表记录,每次通过一维数组返回一个记录结果

        //$model对象->find();没有设置参数获得第一条结果

        //$model对象->find(数字);获得主键为参数值的记录结果

//        $info = D('Goods')-> select($goods_id);

//        两个业务逻辑,展示和收集

        if (!empty($_POST)) {

            $z = $goods->save($_POST);

            if ($z) {

                //页面跳转

               //$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);

               // $this ->redirect("showlist",array(), 2, '数据添加成功');

                //如果设置参数,可以get方法传递,比如

                $this ->redirect("showlist",array(), 2, '数据修改成功');

            } else {

                $this ->redirect("upd",array('goods_id' => $goods_id), 2, '数据修改失败');

            }

        } else {

            $info = D('Goods')-> find($goods_id);

            $this ->assign('info', $info);

            $this ->display();

        }   

    }

 

六、           实现表单的自动验证

1.       实现前台用户注册

创建控制器及其操作方法

    //注册

    function register(){

        $user = D('user');

        //两个逻辑,显示和收集

        if (!empty($_POST)) {

            $_POST['user_hobby']= implode(',', $_POST['user_hobby']);

            dump($_POST);

            $z = $user ->add($_POST);

//            dump($z);

        } else {

            $this->display();

        }

    }

2.       实现表单自动验证

重写父类的_validate成员,定义验证规则

<?php

 

 

/*

 *user模型

 */

namespace Model;

use Think\Model;

//父类Model:Think/Library/Think/Model.class.php

class UserModel extends Model {

    //是否批量获得全部验证信息

    protected $patchValidate =true;

    //通过定义$_validate成员,设置表单验证规则

    protected $_validate = array(

//        array(字段,规则,错误提示,验证条件,附加规则,验证时间);

        array('username', 'require','用户名必须填写'),

        array('username', '', '该用户名已经被使用', 0, 'unique'),

        array('password','require', '密码必须填写'),

        array('password2','require', '确认密码必须填写'),

        array('password2','password', '两次密码必须一致', 0, 'confirm'),

        array('user_email','email', '邮箱不能为空', 0),

        array('user_email','email', '邮箱格式不正确', 2),

        array('user_qq','number', 'qq必须是数字组成'),

        array('user_qq', '5,12','qq必须是5到12位', 0, 'length'),

        array('user_xueli','2,3,4,5', '学历必须选择一个', 0, 'in'),

        array('user_hobby','check_hobby', '爱好必须选择两项以上', 1, 'callback'),

    );

    //定义一个方法进行爱好的验证

    function check_hobby($arg){

        if (count($arg) < 2) {

            return false;

        }

        return true;

    }

}

编写控制器的方法,调用create方法,进行验证

    function register(){

        $user = new\Model\UserModel();

        //两个逻辑,显示和收集

        if (!empty($_POST)) {

//           $_POST['user_hobby'] = implode(',', $_POST['user_hobby']);

            $info = $user ->create();//收集表单,过滤表单信息,非法字段过滤,表单自动验证

            //通过create的返回值判断验证是否成功

            if ($info) {

               $info['user_hobby'] = implode(',', $info['user_hobby']);

                $z = $user ->add($info);

                if ($z) {

                    $this->redirect('Index/index');

                }

            } else {

                $this ->assign('errorinfo',$user -> getError());

            }

        }

        $this->display();

    }

在注册模板中使用输出的验证提示信息,如:

<span  style=”coloe:red;”>{$errorinfo.user_hobby|default:''}</span>

七、           命名空间

php5.3后引入的技术,java中的老技术,被php引用。

1.       命名空间的含义

在php程序中,语法规则要求同名称的函数、类名、常量在一个请求里边不允许出现多次。如果有的应用程序不得已必须出现多个同名的函数、类名、常量,可以把它们放到不同的空间里面做请求。这个不同的空间称为命名空间。

2.       命名空间的使用

通过namespace关键字可以声明命名空间。语法:namespace 空间名称;

命名空间针对函数、类名、const常量三部分起作用,并统称为元素。

常量的声明,define(名称,值);//在类外部声明常量与命名空间没有关系,同名常量只能声明一次

const  名称=值;//与命名空间有关系。

Const可以在类内部声明常量信息。Const也可以在类外部声明常量。

使用命名空间的时候const可以放到类外部声明常量。

同名称的多个常量,可以分别定义到不同的命名空间里。

比如:

<?php

namespace haha;

function getInfo(){

       echo "hah";

}

const HOST = "localhost";

namespace haha2;

function getInfo(){

       echo "heihei";

}

const HOST = "127.0.0.1";

任素在没有任何限制的时候,会访问当前空间的元素,当前空间按照就近原则算。比如:

<?php

namespace haha;

function getInfo(){

       echo "hah";

}

const HOST = "localhost";

namespace haha2;

function getInfo(){

       echo "heihei";

}

const HOST = "127.0.0.1";

getInfo();

echo HOST;

如果访问指定空间的元素,需要进行空间限制,\空间名\访问的信息,比如:

<?php

namespace haha;

function getInfo(){

       echo "hah";

}

const HOST = "localhost";

namespace haha2;

function getInfo(){

       echo "heihei";

}

const HOST = "127.0.0.1";

getInfo();

echo HOST;

echo "<hr />";

\haha\getInfo();

echo \haha\HOST;

3.       多级命名空间及三种方式访问元素

命名空间中存放的元素,有时候多了,为了便于管理,可以对元素进行分门别类的存储。也就是说命名空间可以设置为多级空间。多级空间的最后一级空间就称为子级空间。

三种访问元素的方式分别是,非限定名称方式;完全限定名称方式;限定名称方式。

比如:

<?php

//多级命名空间

namespace beijing\haha\heieh;

class Person {

       public $name ="jim";

}

 

namespace tianin\hll\looe;

class Person {

       public $name ="tom";

}

 

$obj = new Person();

echo $obj -> name;

echo "<hr />";

$obj1 = new \beijing\haha\heieh\Person();

echo $obj1 -> name;

以限定名称方式

<?php

namespace tianjin\hie\ah\hei;

const USER = "user3";

 

namespace beijing\haha\hei;

const USER = "user1";

 

namespace tianjin\hie\ah;

const USER = "user2";

//限定名称方式

//表示当前空间+本身空间\元素

 

echo hei\USER;

4.       引入机制

命名空间声明为多级空间,在其他空间内部访问的时候,需用通过完全限定名称方式,这个完全限定方式不便于开发、维护,为了降低复杂度,可以在当前空间把指定的空间给引入进来,进而可以方便地通过限定名称的方便的形式使用其他空间的元素。

1)       空间引入的例子

<?php

namespace bj\hd\sd;

const USER = "haha1";

 

namespace tj\bu\zhi;

const USER = "haha2";

 

function getInfo(){

       echo "eeeee";

}

const NAME = "hehe";

 

namespace sz\nh\gm;

const USER = "haha3";

//项目需要频繁访问其他空间元素,如果使用完全限定,有麻烦且后续难维护

//引入其他空间,可以使用限定名称方式访问,限定名称就是引入空间的最后一级

use tj\bu\zhi;

echo zhi\NAME;

zhi\getInfo();

2)       元素引入

语法:use  空间\空间\空间\类元素;

空间引入可以解决完全限定名称访问元素的繁琐型,但是还需通过限定名称方式访问,如果引入空间的元素是类,就可以直接把这个类引入到当前空间,使用时就可以通过非限定名称方式访问。注意,只能做类元素引入,函数和常量不可以。

为了防止引入类与当前空间存在同名类导致冲突,可以在引入类元素时使用别名,语法:use 空间\元素 as  别名;

比如:

<?php

namespace bj\hd\sd;

class Person {

       static $name ="user1";

 

}

 

namespace sz\nh\gm;

class Person {

       static $name ="user2";

}

const USER = "haha3";

//bj\hd\sd\Person类元素直接引入

use bj\hd\sd\Person as P;

echo Person::$name;

echo "<hr />";

echo P::$name;

5.       公共空间

一个php文件里边没有namespace关键字声明,则该文件的元素都存在于公共空间,访问公共空间的元素统一设置为\元素。

比如:

<?php

namespace bj;

function f1(){

       echo "haha";

}

const NAME = "hehe";

//引入文件空间对当前空间没有影响

include("demo7.php");//公共空间

f1();//当前空间是bj

echo "<br />";

echo \NAME;

echo "<br />";

echo NAME;

f2();

 

<?php

const NAME = "heih";

function f2(){

       echo "xixi";

}

6.       使用命名空间的注意问题

声明命名空间的当前脚本的第一个namespace关键字前面不能有任何代码,header头也要下在下边;

命名空间是虚拟抽象的空间,不是真实存在的目录;

同一个请求的多个文件可以使用同名命名空间名称,只要这些文件里没有同名称、同类型的元素就可以。

7.       关于tp框架中的命名空间

比如在UserController类中

namespaceHome\Controller;//声明命名空间

useThink\Controller;//空间类元素引入

八、           实现验证码

1.       生成验证码

使用tp框架提供的验证码类

注意在类开始前引入验证码类

use Think\Verify;

    //生成验证码

    public function verifyImg(){

        $cfg = array(

            'imageH' => 45,

            'imageW' => 100,

            'length' => 4,

            'fontSize' => 15,

            'fontttf' =>'1.ttf',

        );

        //实例化verify类对象

        $very = newVerify($cfg);//完全限定名称方式

        $very -> entry();

}

2.       输出验证码

在登陆模板显示验证码

<img  src=”{$smarty.const.__CONTROLLER__/verifyImg}”  alt=”yzm” onclick=”this.src=’ {$smarty.const.__CONTROLLER__/verifyImg}’/Math.random()”/>

3.       校验验证码

    public function login(){

        //两个业务逻辑,展示表单,收集表单

        if ($_POST) {

            //验证码的校验

            $vry = new\Think\Verify();

            if ($vry ->check($_POST['captcha'])) {

                echo "正确";

            } else {

                echo "错误";

            }

        }

        $this->display();    

    }

九、           附件上传

1.       上传图片

使用tp框架下的Upload类。

编写模板页面中的上传商品信息的表单,注意form中添加enctype=”multipart/form-data”属性。

    public function tianjia(){       

        $goods = D('Goods');

        //判断是展示还是收集信息

        if (!empty($_POST)) {

//            dump($_POST);

            //处理上传的商品图片

            if($_FILES['goods_pic']['error'] == 0) {

                $cfg = array(

                    'rootPath'=> 'uploads/',//保存根目录

 

                );

                $up = new\Think\Upload($cfg);

                //uploadOne()会返回上传文件的存储在服务器的名字和路径等信息

                $z = $up->uploadOne($_FILES['goods_pic']);

//                dump($up ->getError());

                //把上传的图片保存到数据表记录里面

                $bigpathname =$up -> rootPath . $z['savepath'] . $z['savename'];

               $_POST['goods_big_img'] = $bigpathname;

            }

            $info = $goods->create();

            $z = $goods ->add($info);

            if ($z) {

                //页面跳转

               //$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);

               // $this ->redirect("showlist",array(), 2, '数据添加成功');

                //如果设置参数,可以get方法传递,比如

                $this ->redirect("showlist",array('name' => 'hah','age' => 12), 2, '数据添加成功');

            } else {

                $this ->redirect("tianjia",array(), 2, '数据添加失败');

            }

        } else {

            $this ->display();

        }     

    }

2.       制作缩略图

把一个已有图片打开,裁出某个部分,经过放大、缩小,把处理好的部分放到另外一个图片里边,显示出来。

    public functiontianjia(){       

        $goods = D('Goods');

        //判断是展示还是收集信息

        if (!empty($_POST)) {

//            dump($_POST);

            //处理上传的商品图片

            if($_FILES['goods_pic']['error'] == 0) {

                $cfg = array(

                    'rootPath'=> './uploads/',//保存根目录

 

                );

                $up = new\Think\Upload($cfg);

                //uploadOne()会返回上传文件的存储在服务器的名字和路径等信息

                $z = $up->uploadOne($_FILES['goods_pic']);

//                dump($up ->getError());

                //把上传的图片保存到数据表记录里面

                $bigpathname =$up -> rootPath . $z['savepath'] . $z['savename'];

               $_POST['goods_big_img'] = $bigpathname;

                //给上传图片制作缩略图

                $im = new\Think\Image();

                $im ->open($bigpathname);//打开被处理的图片

                $im ->thumb(125,125);//制作缩略图

                //保存缩略图到服务器

                $smallpathname =$up -> rootPath . $z['savepath'] . "small_" . $z['savename'];

                $im ->save($smallpathname);//保存缩略图到服务器

                //把制作好的缩略图保存到数据表记录

               $_POST['goods_small_img'] = $smallpathname;

            }

            //exit;

            $info = $goods->create();

            $z = $goods ->add($info);

            if ($z) {

                //页面跳转

               //$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);

               // $this ->redirect("showlist",array(), 2, '数据添加成功');

                //如果设置参数,可以get方法传递,比如

                $this ->redirect("showlist",array('name' => 'hah','age' => 12), 2, '数据添加成功');

            } else {

                $this ->redirect("tianjia",array(), 2, '数据添加失败');

            }

        } else {

            $this ->display();

        }

3.       在模板中显示图片

设置图片路径的常量在index.php中

//设置静态图片地址

define('SITE_URL','http://www.php2.com/tp/shop/');

在添加方法中,去除图片的./

$_POST['goods_big_img']= ltrim($bigpathname, './');

$_POST['goods_small_img']= ltrim($smallpathname, './');

十、           数据分页

在shop项目下,创建Tools目录,创建Page.class.php类

<?php

 

/*

 * 分页工具类

 */

namespace Tools;

class Page {

    private $total; //数据表中总记录数

    private $listRows; //每页显示行数

    private $limit;

    private $uri;

    private $pageNum; //页数

    private$config=array('header'=>"个记录", "prev"=>"上一页", "next"=>"下一页", "first"=>"首 页","last"=>"尾 页");

    private $listNum=8;

    /*

     * $total

     * $listRows

     */

    public function__construct($total, $listRows=10, $pa=""){

        $this->total=$total;

       $this->listRows=$listRows;

       $this->uri=$this->getUri($pa);

       $this->page=!empty($_GET["page"]) ? $_GET["page"]: 1;

       $this->pageNum=ceil($this->total/$this->listRows);

       $this->limit=$this->setLimit();

    }

 

    private function setLimit(){

        return "Limit".($this->page-1)*$this->listRows.",{$this->listRows}";

    }

 

    private function getUri($pa){

       $url=$_SERVER["REQUEST_URI"].(strpos($_SERVER["REQUEST_URI"],'?')?'':"?").$pa;

        $parse=parse_url($url);

       if(isset($parse["query"])){

               parse_str($parse['query'],$params);

               unset($params["page"]);

               $url=$parse['path'].'?'.http_build_query($params);

 

        }

 

        return $url;

    }

 

    function __get($args){

       if($args=="limit")

                return$this->limit;

        else

                return null;

    }

 

    private function start(){

        if($this->total==0)

                return 0;

        else

                return($this->page-1)*$this->listRows+1;

    }

 

    private function end(){

        returnmin($this->page*$this->listRows,$this->total);

    }

 

    private function first(){

        $html = "";

        if($this->page==1)

                $html.='';

        else

               $html.="&nbsp;&nbsp;<ahref='{$this->uri}&page=1'>{$this->config["first"]}</a>&nbsp;&nbsp;";

 

        return $html;

    }

 

    private function prev(){

        $html = "";

        if($this->page==1)

                $html.='';

        else

               $html.="&nbsp;&nbsp;<ahref='{$this->uri}&page=".($this->page-1)."'>{$this->config["prev"]}</a>&nbsp;&nbsp;";

 

        return $html;

    }

 

    private function pageList(){

        $linkPage="";

 

        $inum=floor($this->listNum/2);

 

        for($i=$inum; $i>=1;$i--){

               $page=$this->page-$i;

 

                if($page<1)

                        continue;

 

               $linkPage.="&nbsp;<ahref='{$this->uri}&page={$page}'>{$page}</a>&nbsp;";

 

        }

 

       $linkPage.="&nbsp;{$this->page}&nbsp;";

 

 

        for($i=1; $i<=$inum;$i++){

           $page=$this->page+$i;

           if($page<=$this->pageNum)

                   $linkPage.="&nbsp;<ahref='{$this->uri}&page={$page}'>{$page}</a>&nbsp;";

            else

                    break;

        }

 

        return $linkPage;

    }

 

    private function next(){

        $html = "";

        if($this->page==$this->pageNum)

            $html.='';

        else

           $html.="&nbsp;&nbsp;<ahref='{$this->uri}&page=".($this->page+1)."'>{$this->config["next"]}</a>&nbsp;&nbsp;";

 

        return $html;

    }

 

    private function last(){

        $html = "";

       if($this->page==$this->pageNum)

                $html.='';

        else

               $html.="&nbsp;&nbsp;<ahref='{$this->uri}&page=".($this->pageNum)."'>{$this->config["last"]}</a>&nbsp;&nbsp;";

 

        return $html;

    }

 

    private function goPage(){

        return'&nbsp;&nbsp;<input type="text"onkeydown="javascript:if(event.keyCode==13){varpage=(this.value>'.$this->pageNum.')?'.$this->pageNum.':this.value;location=\''.$this->uri.'&page=\'+page+\'\'}"value="'.$this->page.'" style="width:25px"><inputtype="button" value="GO" onclick="javascript:varpage=(this.previousSibling.value>'.$this->pageNum.')?'.$this->pageNum.':this.previousSibling.value;location=\''.$this->uri.'&page=\'+page+\'\'">&nbsp;&nbsp;';

    }

    function fpage($display=array(0,1,2,3,4,5,6,7,8)){

       $html[0]="&nbsp;&nbsp;共有<b>{$this->total}</b>{$this->config["header"]}&nbsp;&nbsp;";

       $html[1]="&nbsp;&nbsp;每页显示<b>".($this->end()-$this->start()+1)."</b>条,本页<b>{$this->start()}-{$this->end()}</b>条&nbsp;&nbsp;";

        $html[2]="&nbsp;&nbsp;<b>{$this->page}/{$this->pageNum}</b>页&nbsp;&nbsp;";

       $html[3]=$this->first();

       $html[4]=$this->prev();

       $html[5]=$this->pageList();

       $html[6]=$this->next();

       $html[7]=$this->last();

        $html[8]=$this->goPage();

        $fpage='';

        foreach($display as$index){

               $fpage.=$html[$index];

        }

        return $fpage;

    }

}

 

在商品列表方法中实现分页效果

    public function showlist(){

        //实现分页效果

       

        //实例化普通model对象

        $goods = new\Model\GoodsModel();

        //获得数据的总记录数

        $total = $goods ->count();

        $per = 7;

        //实例化分页对象

        $page_obj = new\Tools\Page($total, $per);

        //拼接sql语句获得每页信息

        $sql = "select *from sw_goods order by goods_id desc " . $page_obj -> limit;

        $info = $goods ->query($sql);

        //获得页码列表

        $pagelist = $page_obj-> fpage();

       

        $this ->assign('pagelist', $pagelist);

        $this ->assign('info', $info);

        $this -> display();

    }

十一、   登陆功能的实现

实现后台的登陆功能。

在管理员控制类的登陆方法中

    public function login(){

        //两个业务逻辑,展示表单,收集表单

        if ($_POST) {

            //验证码的校验

            $vry = new\Think\Verify();

            if ($vry ->check($_POST['captcha'])) {

                //验证用户名和密码

                $manager = new\Model\ManagerModel();

                $info = $manager-> checkNamePwd($_POST['admin_user'], $_POST['admin_psd']);

                if ($info) {

                    //给用户信息做session持久化操作

                   session('admin_id', $info['mg_id']);

                   session('admin_name', $info['mg_name']);

                    //页面跳转到后台页面

                    $this ->redirect('Index/index');

                } else {

                    echo"cuowu";

                }

               

            } else {

                echo "错误";

            }

        }

        $this->display();    

    }

实现退出方法

    //退出系统

    function logout(){

        session(null);

        $this ->redirect("login");

    }

十二、   RBAC

role  base access  control,基于角色的用户访问权限。

在每个角色下有一些权限。用户à组à权限。用户和组对应,组和权限对应。管理员只需要考虑用户是哪个组即可,操作非常容易、简便、高效。是科学的权限设置方式。

1.       数据表的设计

一个管理员表,一个角色表,一个权限表。

管理员表中有管理员的基本信息和角色id。角色表中有角色信息,角色具有的权限的id,角色的权限的控制器和操作组成的字符串。权限表中有权限的基本信息,父权限的id,权限的控制器,权限的操作,权限的全路径(父权限id-父权限id-本身id),权限等级。

2.       用户登陆系统显示对应权限

    //左侧

    public function left(){

        //计划,admin_id-->role_id-->auth_ids

        $admin_id =session('admin_id');

        $admin_name =session('admin_name');

        //获得管理员信息

        $admin_info =D('Manager') -> find($admin_id);

        //获得角色id

        $role_id =$admin_info['mg_role_id'];

        //获得权限ids

        $role_info = D('Role')-> find($role_id);

        $auth_ids =$role_info['role_auth_ids'];

        //获得权限信息

        $auth_infoA = D('Auth') ->where("auth_level=0 and auth_id in ($auth_ids)") -> select();

        $auth_infoB = D('Auth')-> where("auth_level=1 and auth_id in ($auth_ids)") ->select();

        $this ->assign('auth_infoA', $auth_infoA);

        $this ->assign('auth_infoB', $auth_infoB);

//        dump($auth_infoA);

//        dump($auth_infoB);

        $this->display();

    }

3.       设置超级管理员显示全部权限

使用判断显示全部权限

    public function left(){

        //计划,admin_id-->role_id-->auth_ids

        $admin_id =session('admin_id');

        $admin_name =session('admin_name');

        //获得管理员信息

        $admin_info =D('Manager') -> find($admin_id);

        //获得角色id

        $role_id =$admin_info['mg_role_id'];

        //获得权限ids

        $role_info = D('Role')-> find($role_id);

        $auth_ids = $role_info['role_auth_ids'];

        //获得权限信息

        //admin要显示全部权限

        if($admin_name==='admin') {

            $auth_infoA =D('Auth') -> where("auth_level=0") -> select();

            $auth_infoB =D('Auth') -> where("auth_level=1") -> select();

        }else {

            $auth_infoA =D('Auth') -> where("auth_level=0 and auth_id in ($auth_ids)")-> select();

            $auth_infoB =D('Auth') -> where("auth_level=1 and auth_id in ($auth_ids)")-> select();

        }

        $this -> assign('auth_infoA',$auth_infoA);

        $this ->assign('auth_infoB', $auth_infoB);

//        dump($auth_infoA);

//        dump($auth_infoB);

        $this->display();

    }

然后,注意,将功能标签与超链接修改

href=” {$smarty.const.__MODULE__}/{$v1.auth_c}/{$v1.auth_a}”;

4.       角色列表展示

创建RoleController控制器showlist方法

<?php

 

/*

 * 后台角色控制器

 */

namespace Admin\Controller;

use Think\Controller;

 

class RoleController extends Controller {

    function showlist(){

        //获取角色全部数据

        $info = D('Role') ->select();

        $this ->assign('info', $info);

        $this -> display();

    }   

}

5.       权限分配

创建分配权限的方法,展示权限表单

    //权限分配

    function fenpei($role_id){

        //根据$role_id获得被分配权限的角色信息

        $role_info = D('Role')-> find($role_id);

        //获得被分配的全部权限并分配给模板使用

        $auth_infoA = D('Auth')-> where("auth_level=0") -> select();

        $auth_infoB = D('Auth')-> where("auth_level=1") -> select();

        $this ->assign('auth_infoA', $auth_infoA);

        $this ->assign('auth_infoB', $auth_infoB);

        $this ->assign('role_info', $role_info);

        $this -> display();

    }

6.       收集权限表单的信息

注意给角色分配角色,需要以隐藏域传递其id。<input type="hidden" name="role_id"value="{$role_info.role_id}" />

完善分配权限的方法

    //权限分配

    function fenpei($role_id){

        //两个逻辑,展示,收集

        $role = new\Model\RoleModel();

        if(!empty($_POST['authid'])) {

           //处理表单传递的数据

            $z = $role ->saveAuth($_POST['authid'], $_POST['role_id']);

            if ($z) {

                $this ->redirect('showlist', array(), 2, '分配权限成功');

            } else {

                $this ->redirect('fenpei', array('role_id' => $role_id), 2, '分配权限失败');

            }

        } else {

            //根据$role_id获得被分配权限的角色信息

            $role_info = $role-> find($role_id);

            //获得被分配的全部权限并分配给模板使用

            $auth_infoA =D('Auth') -> where("auth_level=0") -> select();

            $auth_infoB =D('Auth') -> where("auth_level=1") -> select();

            $this ->assign('auth_infoA', $auth_infoA);

            $this ->assign('auth_infoB', $auth_infoB);

            $this ->assign('role_info', $role_info);

            $this ->display();

        }      

    }

创建RoleModel类和处理authid和更新数据表的方法

<?php

 

/*

 *role模型

 */

namespace Model;

use Think\Model;

//父类Model:Think/Library/Think/Model.class.php

class RoleModel extends Model {

    //权限分配

    function saveAuth($authid,$role_id){

        //把$authid由array变为string

        $authids = implode(',',$authid);

        //根据字符串的authid查询分配的全部权限信息获得它们的控制器和方法

        $auth_info = D('Auth')-> select($authids);

        $s = "";

        foreach ($auth_info as $k=> $v) {

            if(!empty($v['auth_c']) && !empty($v['auth_a'])) {

                $s .=$v['auth_c'] . "-" . $v['auth_a'] . ",";

            }

          

        }

        $s = rtrim($s, ',');//去除右侧,

        $sql = "updatesw_role set role_auth_ids='$authids',role_auth_ac='$s' whererole_id='$role_id'";

        return $this ->execute($sql);

    }

}

7.       在更新权限时显示已有权限

在显示分配的方式中,需要获得该角色的权限,将其转为数组,然后在模板中,判断权限是否在这个角色的权限数组中,如果在就checked。

    //权限分配

    function fenpei($role_id){

        //两个逻辑,展示,收集

        $role = new \Model\RoleModel();

        if(!empty($_POST['authid'])) {

           //处理表单传递的数据

            $z = $role ->saveAuth($_POST['authid'], $_POST['role_id']);

            if ($z) {

                $this ->redirect('showlist', array(), 2, '分配权限成功');

            } else {

                $this ->redirect('fenpei', array('role_id' => $role_id), 2, '分配权限失败');

            }

        } else {

            //根据$role_id获得被分配权限的角色信息

            $role_info = $role-> find($role_id);

            //获得已经拥有的权限信息,并变为array

            $haveauth =explode(',', $role_info['role_auth_ids']);

            //获得被分配的全部权限并分配给模板使用

            $auth_infoA =D('Auth') -> where("auth_level=0") -> select();

            $auth_infoB =D('Auth') -> where("auth_level=1") -> select();

            $this ->assign('auth_infoA', $auth_infoA);

            $this ->assign('auth_infoB', $auth_infoB);

            $this ->assign('role_info', $role_info);

            $this ->assign('haveauth', $haveauth);

            $this ->display();

        }

       

    }

在模板中判断,比如:

<input  type="checkbox"name="authid[]" value="{$v1.auth_id}" {ifin_array($v.auth_id, $haveauth)}checked="checked"{/if}  />

8.       权限维护

展示权限列表

控制器,AuthController,操作,showlist。

使用全路径字段排序。

<?php

 

/*

 * 后台权限控制器

 */

namespace Admin\Controller;

use Think\Controller;

 

class AuthController extends Controller {

    //权限列表展示

    function showlist(){

        //获取权限全部数据

        $info = D('Auth') ->order ('auth_path') -> select();

        $this ->assign('info', $info);

        $this -> display();

    }   

}

在模板中,使用权限等级字段实现缩进,比如:{$v.auth_name|indent:$v.auth_level:'../'}

9.       权限添加

展示权限表单

    //添加权限

    function tianjia(){

        //两个逻辑,展示,收集

        $auth = new\Model\AuthModel();

        if ($_POST) {

            dump($_POST);

        } else {

            //获得被选取的上级权限

            $auth_infoA = $auth-> where('auth_level=0') -> select();

            $this ->assign('auth_infoA', $auth_infoA);

            $this ->display();

        }

    }

收集表单信息,并录入数据表

    function tianjia(){

        //两个逻辑,展示,收集

        $auth = new\Model\AuthModel();

        if ($_POST) {

            //表单收集到4个信息,另两个字段需要计算

            //在saveData方法中实现path/level的制作,最终完成整条记录信息

            $z = $auth ->saveData($_POST);

            if ($z) {

                $this ->redirect('showlist', array(), 2, '添加权限成功');

            } else {

                $this ->redirect('tianjia', array(), 2, '添加权限失败');

            }

        } else {

            //获得被选取的上级权限

            $auth_infoA = $auth-> where('auth_level=0') -> select();

            $this ->assign('auth_infoA', $auth_infoA);

            $this ->display();

        }

    }

创建AuthModel中的制作path和level,更新整条数据的方法

<?php

 

/*

 *auth模型

 */

namespace Model;

use Think\Model;

//父类Model:Think/Library/Think/Model.class.php

class AuthModel extends Model {

    //实现path/level的制作,并完成新记录的全部字段的写入

    function saveData($data){

        //先将4个字段插入数据表,并获得生成的id

        $newid = $this ->add($data);

        //根据新生成的id,制作path和level

        //path,如果本身是顶级权限,path就是新生成的id

        //level,如果本身是顶级权限,level为0,否则为1

        if ($data['auth_pid'] ==0) {

            $path = $newid;

            $level = 0;

        } else {

            $path =$data['auth_pid'] . "-" . $newid;

            $level = 1;

        }

        //生成level也可以计算path中-的个数得到

//        $level =substr_count($path, '-');

        //更新新生成的记录的path和level

        $sql = "updatesw_auth set auth_path='$path',auth_level=$level where auth_id=$newid";

        return $this -> execute($sql);      

    }

}

10.   禁止翻墙访问

如果只是根据程序的逻辑设计根据用户-角色显示其对应的权限,但是并没有限制用户访问一些其不具备的权限,就会出现访问漏洞。也可以通过手动输入控制器、操作方法路由信息进而访问本身不存在的权限。这就是翻墙访问。

制作一个AdminController,通过构造方法做限制,然后让后台控制器都继承这个AdminController。然后AdminController继承tp的Controller。

<?php

 

/*

 * 限制访问的控制器,后台控制器的父类控制器

 */

namespace Tools;

use Think\Controller;

 

class AdminController extends Controller {

    //构造方法

    function __construct() {

        //先执行父类构造方法,避免功能缺失

        parent::__construct();

        //用户访问权限的控制过滤功能

        //获得目前访问的控制器和操作方法,并连接为字符串,然后判断是否在其应该访问的范围内

        $nowac = CONTROLLER_NAME. "-" . ACTION_NAME;

        //获得用户的权限列表信息

        $admin_id =session('admin_id');

        $admin_name = session('admin_name');

        $admin_info =D('Manager') -> find($admin_id);

        $role_id =$admin_info['mg_role_id'];

        $role_info = D('Role')-> find($role_id);

        $auth_ac =$role_info['role_auth_ac'];

        //strpos($s1, $s2),判断$s1从左开始第一次出现$s2下标信息,并返回该下标信息,没有出现返回false

        //当前权限没有出现在权限里面

        //当前权限没有出现在默认允许的权限里面

        //当前用户还不是超级管理admin

        $allow_ac ="Manager-login,Manager-logout,Manager-verifyImg,Index-left,Index-index,Index-head,Index-right";

        if (strpos($auth_ac,$nowac) === false && strpos($allow_ac, $nowac) === false &&$admin_name != 'admin') {

            exit("没有权限");       

        }  

    }

}

11.   登陆验证

没有登陆系统的用户访问后台,要禁止其自动跳转到登陆页面去。在AdminController中控制登陆验证。

<?php

 

/*

 * 限制访问的控制器,后台控制器的父类控制器

 */

namespace Tools;

use Think\Controller;

 

class AdminController extends Controller {

    //构造方法

    function __construct() {

        //先执行父类构造方法,避免功能缺失

        parent::__construct();

        //用户访问权限的控制过滤功能

        //获得目前访问的控制器和操作方法,并连接为字符串,然后判断是否在其应该访问的范围内

        $nowac = CONTROLLER_NAME. "-" . ACTION_NAME;

        //获得用户的权限列表信息

        $admin_id = session('admin_id');

        $admin_name =session('admin_name');

        //session中admin_id或admin_name为空

        //没有登陆系统的判断

        $group_url = __MODULE__;

        $yunxu_ac ="Manager-login, Manager-verifyImg";

//        if (empty($admin_id)&& $nowac != 'Manager-login' && $nowac != 'Manager-verifyImg'){

//            $this ->redirect('Manager/login');

//        }

        if (empty($admin_id)&& strpos($yunxu_ac, $nowac) === false) {

//            $this ->redirect('Manager/login');

            $js = <<<eof

                    <scripttype="text/javascript">

                    //top使得整个frame框架都条状

                       window.top.location.href = "$group_url/Manager/login";

                   </script>

eof;

            echo $js;           

        }

        $admin_info =D('Manager') -> find($admin_id);

        $role_id =$admin_info['mg_role_id'];

        $role_info = D('Role')-> find($role_id);

        $auth_ac =$role_info['role_auth_ac'];

        //strpos($s1, $s2),判断$s1从左开始第一次出现$s2下标信息,并返回该下标信息,没有出现返回false

        //当前权限没有出现在权限里面

        //当前权限没有出现在默认允许的权限里面

        //当前用户还不是超级管理admin

        $allow_ac ="Manager-login,Manager-logout,Manager-verifyImg,Index-left,Index-index,Index-head,Index-right";

        if (strpos($auth_ac, $nowac) === false&& strpos($allow_ac, $nowac) === false && $admin_name !='admin') {

            exit("没有权限");       

        }  

    }

}