博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP_ThinkPHP
阅读量:5928 次
发布时间:2019-06-19

本文共 24502 字,大约阅读时间需要 81 分钟。

不使用框架的问题

在实际工作中,如果不使用框架会遇到的问题。

  1. 程序项目生命时间非常短(维护性,生命力弱)

  2. 分共协作开发项目,彼此代码风格不一致。

  3. 开发程序,喜欢挖坑。

  4. 开发者离职,需要有人维护该离职着的代码风格.

  5. 牵一发而动全身

框架的最大的特点使得程序的业务逻辑与数据模型分开。

相关信息

ThinkPhp, 面向过程,面向对象,轻量级。

重量级:功能多,OOP面向对象,维护性好,生命力顽强。

轻量级:功能实用,面向过程和面向对象混合开发。

clipboard.png

创建应用

  • 创建入口文件,并引入核心框架入口文件 (index.php/app.php)

// TP框架核心框架核心程序引入require('./ThinkPHP/ThinkPHP.php');
  • 访问文件地址,配置虚拟目录

执行流程

  • 运行入口文件

// 定义系统目录    define('APP_PATH', './');        // 修改为调试模式    define('APP_DEBUG', true);
  • TP的入口文件ThinkPHP.php

  • 载入Common/runtime.php

声明常量信息    执行:`load_runtime_file()`,作用:加载运行时所需要的文件 并负责自动目录生成     执行入口:`Think::Start();`
  • 执行:Lib/Core/Think.class.php

static public function start() {};  // 应用程序初始化    Think::buildApp(); // 预编译项目    App::run(); // 运行应用
  • 执行:Lib/Core/App.class.php

static public function run() {}; // 运行应用实例 入口文件使用的快捷方法    App::init(); // 应用程序初始化    Dispatcher::dispatch(); // URL调度    // 分析路由(控制器`MODULE_NAME`  方法`ACTION_NAME`) // e.g: index.php?c=控制器&a=方法   App::exec(); // 执行应用程序   通过反射ReflectionMethod使得控制器对象调用对应的方法.

控制器和简单模板创建

如何分离控制器

根据业务特点,把控制器分离(User, Goods)

路由解析

通过GET方式告知应用,请求控制器和操作方法.

  • GET最基本方式

http://www.tp.com/shop/go/index.php?m=User&a=register
  • 路径方式

http://www.tp.com/shop/go/index.php/User/register
  • 伪静态方式

http://www.tp.com/shop/go/User/register
  • 兼容模式 (兼容基本方式和路径方式)

http://www.tp.com/shop/go/index.php?s=User/login

Tpl目录下创建对应的控制器标识作为文件夹(Goods),对应控制器的动作作为访问文件(showlist.html)。

控制器中调用display();

display(); } // 查看商品的详细信息 public function detail() { $this->display(); } } ?>

模板引入框架中

把模板引入ThinkPH框架中,出现的样式路径,图片路径,JavaScript路径不正确。

CSS文件和图片文件位置原则:可以单独被访问.
配置资源的public文件,放置css,images,js等文件。
需要配置基本常量.

// 路径常量define('SITE_URL', 'http://tp.com/'); // 网站地址define('CSS_URL', SITE_URL . 'shop/go/public/css/'); // 前台页面CSS路径define('IMAGE_URL', SITE_URL . 'shop/go/public/images'); // 前台页面图片路径常量

模板中如何使用常量

利用thinkphp默认的模板引擎调用常量。{$Think.const.常量名}

空操作和空模块

空操作

空请求:http://xxxx/index.php?m=user&a=pink;

pink没有对应的操作动作,是一个空请求。

空操作,一个类实例化对象,对象调用类中不存在的方法。在OOP中有魔术方法,__call(),自动调用该魔术方法。

空操作处理:

  1. 对应的控制器中定义方法_empty()

  2. 在应用Common/common.php中添加一个函数名:__hack_action()

空模块

ThinkPHP中把MVC中的控制器称之为:模块(module).

空模块:http://xxxx/index.php?m=color&a=pink;

color不存在的控制器

空模块处理方式:

  1. 对应的控制器中定义模块:EmptyAction.class.php

  2. 在应用Common/common.php中添加一个函数名: __hack_module

项目分组设置

ThinkPHP模块的分组:

'APP_GROUP_LIST'        => 'home,admin',      // 项目分组设定,多个组之间用逗号分隔,例如'Home,Admin'

项目分组对路由的影响:

http://www.xxxx.com/index.php/分组名称/控制器/方法

分组的范围:

  1. Action控制器分组

  2. Tpl模板分组

  3. 配置文件

  4. 静态资源分组

frameset搭建后台页面

使用:frameset标签进行搭建.

获得常量信息:get_defined_constants(true); // true参数表示分类

修改路由链接(使用绝对地址)

                            

后台商品列表

后台商品列表-修改-增加

display(); } // 添加商品 public function add() { $this->display(); } // 修改商品 public function upd() { $this->display(); } } ?>

跨模块调用

  • 利用自动加载

$user = new UserAction();$user->number();
  • 系统提供:A函数调用

// A函数用于实例化Action 格式:[项目://][分组/]模块 // 调用当前项目$user = A('home/User');$user->number();// 调用不同项目中的控制器$user = A('book://Index');echo $user->info();
  • 系统提供:远程调用模块的操作方法 URL

// 远程调用模块的操作方法 URL 参数格式 [项目://][分组/]模块/操作方法echo R('home/User/number');

简单model模型创建

数据库连接

在配置文件中配置数据库基本信息

// 数据库  'DB_TYPE'               => 'mysql',      // 数据库类型  'DB_HOST'               => 'localhost',  // 服务器地址  'DB_NAME'               => 'shop',       // 数据库名  'DB_USER'               => 'root',       // 用户名  'DB_PWD'                => '',           // 密码  'DB_PORT'               => '',           // 端口  'DB_PREFIX'             => 'sw_',        // 数据库表前缀  'DB_FIELDTYPE_CHECK'    => false,        // 是否进行字段类型检查  'DB_FIELDS_CACHE'       => true,         // 启用字段缓存

数据库中每张数据表都对应一个数据model模型类。

简单model模型创建与使用

创建文件:GoodsModel.class.php

字段缓存:

// 出于性能考虑,要把数据表字段放入缓存中,下次访问就避免执行SQL语句重复执行。 // 前提,是生产模式,字段缓存有效.'DB_FIELDS_CACHE'       => true,         // 启用字段缓存

基类Model部分属性:

实例化的三种方法

  • 普通的实例化方法

$goods_model = new GoodsModel();
  • 快捷方式

// D(); D函数用于实例化Model 格式 项目://分组/模块$goods_model = D('Goods');
  • 实例化没有模型文件的Model

$model = new Model(); // 实例化基类// 指定实例化Model$model = M('CateGory');    // 调用M(); 函数 // M函数用于实例化一个没有模型文件的Model

查询数据select方法

查询基本使用

// 查询数据$goods_model = new GoodsModel();// 查询全部数据$info = $goods_model->select(); // select(记录主键值); 方法查询数据 // 返回二维数据// 查询一条记录$info = $goods_model->select(7);// 查询多条记录$info = $goods_model->select('17, 20, 23'); // SELECT * FROM `sw_goods` WHERE ( `goods_id` IN ('17',' 20',' 23') )

查询相关操作方法

find() 返回一条记录

// 返回一维数组, 每次只返回一条数据$info = $goods_model->find(7);    // SELECT * FROM `sw_goods` WHERE ( `goods_id` = 7 ) LIMIT 1

field() 固定字段

// 查询固定字段 // 指定查询字段 支持字段排除$info = $goods_model->field('goods_name, goods_price, goods_number, goods_cretae_time')->select();

limit() 查询条

// 查询条数// $info = $goods_model->limit(长度)// $info = $goods_model->limit(偏移量, 长度)$info = $goods_model->limit(5, 5)->select();

order() 排序

// 排序// $info = $goods_model->order(条件 倒序/正序);$info = $goods_model->order('goods_price desc')->select();// 链式调用$info = $goods_model->order('goods_price desc')->limit(5)->select();

order()Model不存在的方法,会执行魔术方法__call()自动调用

where() 设置条件

// 设置条件$info = $goods_model->where('goods_price > 5000')->select();

table() 设置表名

// 设置表名$info = $goods_model->table('sw_goods')->select();

group() 分组

// 分组$info = $goods_model->group('goods_category_id')->select();

模型相关方法分析

  1. Model.class.php 类本身就存在该方法。例如:where(), filed(), limit(), select()

  2. __call() 自动调用方法集成了一些方法,可以链式调用 例如:table(), order(), group()

getByXXX() 查询数据

返回一维数组信息.

根据指定字段查询数据信息

$info = $goods_model->getByGoods_price('5999'); // 自动调用`__call()`魔术方法

having() 设置查询条件

  1. 和where一样效果,比where 执行晚. 可以对结果结果集进行操作.

  2. having 可以和聚合函数一起使用

$info = $goods_model->having('goods_name like "A%"')->select();

model 聚合函数

// 聚合函数$info = $goods_model->where('goods_id>50')->select();$num = $goods_model->where('goods_id>50')->count(); // SELECT COUNT(*) AS tp_count FROM `sw_goods` WHERE ( goods_id>50 ) LIMIT 1 echo $num;$total_price = $goods_model->where('goods_id>50')->sum('goods_price'); // SELECT SUM(goods_price) AS tp_sum FROM `sw_goods` WHERE ( goods_id>50 ) LIMIT 1echo $total_price;

sum(字段),count(*/字段)max(字段)min(字段)avg(字段)

原生SQL语句

提供2个方法:

$model->query() 查询语句, 返回二维数据

$model->execute() 增加,修改,删除, 返回受影响记录数目

// 执行原生SQL// select g.goods_name, g.goods_price, c.cat_name from sw_goods as g left join sw_category as c on g.goods_category_id = c.cat_id;$sql = "select g.goods_name, g.goods_price, c.cat_name from sw_goods as g left join sw_category as c on g.goods_category_id = c.cat_id";$info = $goods_model->query($sql);

smaty模板使用

Extend/Vendor放入smart模板

ThinkPHP配置信息有两部分:convertion.phpLib/Behavior/* 配置

在配置文件中配置模板类型:

'TMPL_ENGINE_TYPE'        =>  'Smarty',     // 修改模板引擎

显示日志信息

配置信息中配置日志信息显示:

前提:必须调用$this->display()才会显示日志信息。就必须显示模板

'SHOW_PAGE_TRACE'           =>   true,   // 显示页面Trace信息

操作数据

数据添加

两种方式实现数据添加: 数组方式,AR方式

数组方式

// 模型对象$goods_model = new GoodsModel();// 实现数据添加// 数组下标与数据库字段名一致. // 获取数据$data = array(    'goods_name' => 'htc100',    'goods_price' => '3999',    'goods_numer' => 45,    'goods_weight' => 103);$goods_model->add($data); // 返回自动生成的ID值

AR 方式

Active Record 活跃记录

AR记录的规则:

  1. 数据库中的每个数据表对应一个

  2. 数据表中的每条记录都是一个类的一个对象

  3. 记录信息的每个字段都是对象的属性

// AR方式实现数据添加// 对象调用不存在的属性需要调用魔术方法`__set()`$goods_model->goods_name = 'iphone7puls';$goods_model->goods_price = '5700';$goods_model->goods_number = 41;$goods_model->goods_weight = 100;$rst = $goods_model->add(); // 返回影响记录的条数

收集表单数据

Array

$data = $_POST;$cnt = $goods_model->add($data);

AR方式

foreach( $_POST as $k => $v ) {    $goods_model->$k = $v;}$goods_model->add();

ThinkPHPcreate方式

$data = $goods_model->create();$cnt = $goods_model->add($data);

数据修改

save()方法保存数据

// 修改商品public function upd() {        $goods_model = new GoodsModel();        // 修改数据, 需要设置主键ID和where条件    $data = array(        'goods_id' => 55,        'goods_name' => '红米',        'goods_price' => 4000    );    $rst = $goods_model->save($data); // 返回受影响记录的数目    $data = array(        'goods_name' => '香米',        'goods_price' => 4000    );    $rst = $goods_model->where('goods_id=57')->save($data);     echo $rst;        $this->display();}

AR方式

// 主键方式$goods_model->goods_id = 58;$goods_model->goods_name = 'APPLE';$goods_model->goods_price = 4000;$goods_model->save();// where 条件方式$goods_model->goods_name = 'huawei';$goods_model->goods_price = 4000;$snt = $goods_model->where('goods_id=56')->save();

修改数据注意:设置where条件,或者主键条件

删除数据

delete(主键)

$goods_model->delete(57);

路由获取形式

// 获取参数形式// http://www.tp.com/index.php?m=控制器&a=操作&goods_id=100&goods_price=2300// http://www.tp.com/index.php/控制器/操作/参数1/值1/参数2/值2// function upd( 参数1, 参数2 ) {    // $_GET['goods_id'];// }// URL地址参数要与方法参数一致

错误信息处理

在控制器中调用方法:

$this->success('修改成功', __URL__ .'/showList');

系统会寻找dispatch_jump.tpl文件

Lib/Core/View.class.php中修改parseTemplate方法

/**     * 自动定位模板文件     * @access protected     * @param string $template 模板文件规则     * @return string     */    public function parseTemplate($template='') {        / 判断是否存在模板文件 移动到后面判断.        if(is_file($template)) {            return $template;        }    }

表单验证

前提:收集表单数据必须通过create()方法来收集. 定义的验证规则通过create()方法触发.

ThinkPHP自动验证:

UserModel.class.php中重写$_validate:

Smarty引入流程

  1. 控制器IndexAction.class.php

    function index()

    $this->display();  (父类Action的display)
  2. 父类ThinkPHP/Lib/Core/Action.class.php

    $this->view->display();
  3. ThinkPHP/Lib/Core/View.class.php

    function display()

    // 解析并获取模板内容$content = $this->fetch($templateFile,$content,$prefix);

    // 解析和获取模板内容 用于输出

    function fetch()

    tag('view_parse',$params);
  4. ThinkPHP/Conf/tags.php

    'view_parse' => array(

    'ParseTemplate', // 模板解析 支持PHP、内置模板引擎和第三方模板引擎  (Bahavior行为)

    ),

  5. parseTempliteBahavior.class.php

    function run()

    $class = 'TemplateSmarty'
    // ThinkPHP/Extend/Dirver/Template/TemplateSmarty.class.phpif(class_exists($class)) {    // 通过自动加载机制引入对应类文件.  $tpl   =  new $class;  $tpl->fetch($_content,$_data['var']);}else {  // 类没有定义  throw_exception(L('_NOT_SUPPERT_').': ' . $class);}
  6. ThinkPHP/Extend/Dirver/Template/TemplateSmarty.class.php

    public function fetch($templateFile,$var)

    // 寻找Smarty实体.      // ThinkPHP/Extend/Vendor/Smarty/Smarty.class.php      vendor('Smarty.Smarty#class');       // 获取真正的Smarty      $tpl            =   new Smarty();       C(); // 会读取配置文件信息

smarty布局与继承

利用extendsinclude完成

{extends file="public/layout.html"}{block name="main"}    // 子模板代码{/block}

{include file="public/ucenterleft.tpl"}

问题:当代码公共出去之后,对应不同标签需要显示不同的样式?

  1. 通过路由解析 (如何在模板中拿到路由中的操作方法$smarty.const.ACTION_NAME

  2. 通过路由参数

display() 显示模板的四种方法

ThinkPHP框架调用模板:

$this->display() ThinkPHP会自动把模板名称拼装好,与操作名一致。

调用当前模块下的模板:

$this->display(模板名字) 模板名字没有后缀

调用其它模块下的模板:

$this->display(模块/模板名)

相对路径找到模板文件:(相对于入口文件index.html

$this->dispaly(相对路径)

引入机制

import引入机制

例如:import('a.b.c'); // a/b/c.class.php

可以引入那些位置的类文件?

  1. 本身项目的类文件 [对应的类文件都需要创建在Lib目录下]

    import('@.dir.dir.file');e.g:import('@.Model.QqModel.class.php'); // Lib/Model/QqModel.class.php
  2. ThinkPHP核心类文件

    import('think.dir.dir.file');e.g:import('think.car.dirver');  // ThinkPHP/Lib/car/dirver.class.php
  3. 扩展的类文件(ThinkPHP/Extend), 第三库文件引入

    import('ORG.dir.dir.file');e.g: import('ORG.color.pink'); // ThinkPHP/Extend/Library/ORG/color/pink.class.php
  4. 引入一个特殊文件名的类文件。#号使用。

    // 找到文件为:// Lib/apple/bananer.good.flash.class.phpimport('@.apple.bananer#good#flash'); // 文件名为:`bananer.good.flash.class.php`

验证码

Image类没有在自动加载类中载入,需要手动载入。PHP底层的includerequire会影响原始的框架中的引入,可以使用框架中提供的import引入。

import('ORG/Util/Image');echo Image::buildImageVerify();
  • 显示验证码

  • 验证验证码

if ( !empty($_POST['captcha']) && md5($_POST['captcha']) == $_SESSION['verify'] ) {}

用户登陆

登陆信息在模型中验证

getByMg_name($name); // 用户名和密码是否正确 if ( $name_info != null ) { // 密码 if ( $name_info['mg_pwd'] != $pwd ) { return false; } else { return $name_info; } } else { return false; } } } ?>

thinkphp中的session

session的操作:

session(name, value) // 设置sessionsession(name, null) // 删除指定sessionsession(name) // 获取session信息session(null) // 清空全部session

验证验证码 --> 校验用户名和密码 --> 判断用户名 .

checkNamePwd($_POST['mg_name'], $_POST['mg_pwd']); // 判断密码 if ( $user_info != false ) { // 持久化用户信息(id和名字) session('mg_name', $user_info['mg_name']); session('mg_id', $user_info['mg_id']); // 页面重定向 $this->redirect('Index/index'); } else { echo '用户名或密码错误'; } } else { echo '验证码不正确'; } } $this->display(); } // 退出系统 public function logout() { // 删除session信息 session('mg_name', null); // 删除用户名 session('mg_id', null); // 删除id $this->redirect('Manager/login'); } // 生成验证码 public function verifyImg() { import('ORG/Util/Image'); echo Image::buildImageVerify(); } } ?>

数据分页

自定义的分页类

"个记录", "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; } public 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(){ return min($this->page*$this->listRows,$this->total); } private function first(){ $html = ""; if($this->page==1) $html.=''; else $html.="  {$this->config["first"]}  "; return $html; } private function prev(){ $html = ""; if($this->page==1) $html.=''; else $html.="  {$this->config["prev"]}  "; 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.=" {$page} "; } $linkPage.=" {$this->page} "; for($i=1; $i<=$inum; $i++){ $page=$this->page+$i; if($page<=$this->pageNum) $linkPage.=" {$page} "; else break; } return $linkPage; } private function next(){ $html = ""; if($this->page==$this->pageNum) $html.=''; else $html.="  {$this->config["next"]}  "; return $html; } private function last(){ $html = ""; if($this->page==$this->pageNum) $html.=''; else $html.="  {$this->config["last"]}  "; return $html; } private function goPage(){ return '    '; } public function fpage($display=array(0,1,2,3,4,5,6,7,8)) { $html[0]="  共有{$this->total}{$this->config["header"]}  "; $html[1]="  每页显示".($this->end()-$this->start()+1)."条,本页{$this->start()}-{$this->end()}条  "; $html[2]="  {$this->page}/{$this->pageNum}页  "; $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() {        $goods_model = new GoodsModel();        // 引入分页类    import('@.Components.Page');    // 计算当前记录总数目    $total = $goods_model->count();    // 每页5条    $per = 5;    // 实例化分页对象    $page = new Page($total, $per);    // 获得页面列表    $page_list = $page->fpage();    // $page_list = $page->fpage(array(3, 4, 5, 6, 7, 8));        // SQL语句,获得每页的信息    $sql = "select * from sw_goods " . $page->limit;    $info = $goods_model->query($sql);        // 设置数据    $this->assign('info', $info);    $this->assign('page_list', $page_list);    // 显示    $this->display();    }

缓存

把数据库中的信息获取出来,放到一个缓存介质里边,在相当长的一段时间之内,重复的数据在缓存中读取。

缓存介质:内存,file文件,数据库(超多张表,联表查询)。

clipboard.png

// 设置缓存public function sSet() {    // 缓存周期,默认永久。 增加缓存有效期    S('username', 'admin', 1800); // 1800 半个小时 // 过期自动删除    S('goods_info', array('apple', 'WeChat')); // 数组}// 获取缓存public function gGet() {    echo S('username');}// 删除缓存public function dDel() {    S('username', null);}

缓存使用规则:

public function getInfo() {        // 1. 首先要去缓存中获取商品信息    $g = S('info');    // 2. 缓存有商品信息,直接返回. // 否则去数据库查询数据返回,并放入缓存中,设置缓存周期.    if ( !empty($g) ) {        return $g;    } else {        $g = 'apple'. time();                // 数据放入缓存         S('info', $g, 10); // 设置时间        // 返回数据        return $g;    }    }

多语言设置

  • 配置行为

    在配置文件config.php中配置多语言参数

// 配置多语言参数    'LANG_SWITCH_ON'        => true,   // 默认关闭语言包功能'LANG_AUTO_DETECT'      => true,   // 自动侦测语言 开启多语言功能后有效'LANG_LIST'             => 'zh-cn, zh-tw, en-us', // 允许切换的语言列表 用逗号分隔'VAR_LANGUAGE'          => 'hl',        // 默认语言切换变量
  • 设置tags.php执行行为

array( 'ReadHtmlCache', 'CheckLang' // 读取静态缓存 , 检测语言 ), ); ?>
  • 定义语言文件

定义中文简体:../Lang/zh-us/admin/manager.php // 模块名称/控制器名称

定义中文繁体:../Lang/zh-tw/admin/manager.php // 模块名称/控制器名称

ThinkPHP中有在视图可以读取语言信息的变量$Think.language.username

Smarty中没有读取,需要通过控制器中的L()函数读取,然后赋值设置。

// 读取语言变量信息 // L(name); 读取指定语言信息// L();  把全部语言信息以数组信息返回$lang = L();$this->assign('lang', $lang);

自动完成

收集表单信息,把数据存入数据库中,可以使用自动完成机制,对即将入库的信息进行二次加密.

自动完成类似表单验证:表单验证在create()方法内部触发。 而自动完成和自动映射也都是通过create()触发。

手册:

自动完成,自动过滤,自动验证,自动映射,缓存,等操作都放入模型中操作(对于操作数据)。

// 自动完成    // 自动完成定义protected $_auto = array(    // array('填充字段', '填充内容', ['填充条件', '附加规则'])    array('password', 'md5', 3, 'function'),    array('user_time', 'time', 1, 'function'));

自动映射

// 自动映射, 把一个 form表单中的name和 数据库中的字段对应起来protected $_map = array(    'email' => 'user_emial',    'qq' => 'user_qq');

面向切面编程

程序开发,执行不同的环节,不同的功能利用不同的文件进行处理。

把大块的功能切割为小块的功能执行。

整体TP框架执行,内部不是一个文件从头到尾,不同的功能由不同的文件分别执行。

作用:

系统执行由许多不同程序的执行最终看到统一的效果。
有利于程序开发,维护。许多小功能文件分别开发。
可以把系统功能开发非常完善,有利于框架的整体协调工作。
系统升级也可以分为具体小功能模块升级。

tag("app_begin");    function tag()        配置tags变量信息        B()    function B()        实例化行为Behavior,调用run()方法tags.php

快捷函数

U(分组/模块/操作)根据参数获得具体url地址

A(项目://分组/模块)实例化模块
R(项目://分组/模块/操作)实例化模块并调用相关方法
C(名称)读取配置变量信息
L(名称)读取指定语言变量信息
D(); D函数用于实例化Model 格式 项目://分组/模块

RBAC

RBAC (rol base access) 基于角色的权限控制

用户权限分配:权限比较直观,一项项分配。

缺点:不利于权限管理。(分配繁琐,管理混乱)

clipboard.png

打包权限,分类管理。

利用角色对权限进行打包。

clipboard.png

3张数据表

  1. 权限数据表

  2. 角色数据表

  3. 系统用户数据表

--用户表CREATE TABLE IF NOT EXISTS `sw_manager` (  `mg_id` int NOT NULL AUTO_INCREMENT,  `mg_name` varchar(20) NOT NULL comment '名称',  `mg_pwd` varchar(32) NOT NULL comment '密码',  `mg_time` int unsigned NOT NULL comment '时间',  `mg_role_id` tinyint(1) unsigned not null default 0 comment '角色id',  PRIMARY KEY (`mg_id`)) ENGINE=InnoDB  DEFAULT CHARSET=utf8;--权限表CREATE TABLE IF NOT EXISTS `sw_auth` (  `auth_id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,  `auth_name` varchar(20) NOT NULL comment '名称',  `auth_pid` smallint(6) unsigned NOT NULL comment '父id',  `auth_c` varchar(32) not null default '' comment '模块',  `auth_a` varchar(32) not null default '' comment '操作方法',  `auth_path` varchar(32) NOT NULL comment '全路径',  `auth_level` tinyint not null default 0 comment '权限级别012',  PRIMARY KEY (`auth_id`)) ENGINE=InnoDB  DEFAULT CHARSET=utf8;--角色表CREATE TABLE IF NOT EXISTS `sw_role` (  `role_id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,  `role_name` varchar(20) NOT NULL comment '角色名称',  `role_auth_ids` varchar(128) not null default '' comment '权限ids,1,2,5',  `role_auth_ac` text comment '模块-操作',  PRIMARY KEY (`role_id`)) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

查询用户具体拥有的权限

// 用户 -- 角色 -- 权限// $_SESSION['mg_id'];// manager role auth            $model = M();$sql = "select r.role_auth_ids from sw_manager as m join sw_role as r on m.mg_role_id = r.role_id where m.mg_id = " .$_SESSION['mg_id'];$info = $model->query($sql);$auto_ids = $info[0]['role_auth_ids'];// 查询权限// 查询父权限$sql = "select * from sw_auth where auth_id in ($auto_ids) and auth_level=0";$p_auth_info = $model->query($sql);// 查询子权限$sql = "select * from sw_auth where auth_id in ($auto_ids) and auth_level=1";$s_auth_info = $model->query($sql);$this->assign('p_auth', $p_auth_info);$this->assign('s_auth', $s_auth_info);

在普通的控制器新增父类,继承当前的父类,而非框架中的Action父类。

query($sql); $SqlAC = $SqlAC[0]['role_auth_ac']; if (stripos($SqlAC, $AC) == false) { $this->error('没有权限访问', U('Index/right')); exit('没有权限访问'); } } } ?>

给角色分配权限

  1. 数据模拟权限控制

  2. 利用模拟数据进行权限控制

  3. 为角色进行具体权限分配(控制,view视图模板,Model接收处理数据distributeAuth

query($sql); $ac = ""; foreach($info as $v) { if ( !empty($v['auth_c']) && !empty($v['auth_a']) ){ $ac .= $v['auth_c'] . '-'. $v['auth_a'] . ','; } } $ac = rtrim($ac, ','); // 拼凑SQL语句 $sql = "update sw_role set role_auth_ids='$ids', role_auth_ac='$ac' where role_id = " . $role_id; return $this->execute($sql); } }?>

管理权限

添加权限

控制器:

order('auth_path')->select(); $this->assign('info', $info); $this->display(); } /** * 添加权限 */ public function add() { if ( !empty($_POST) ) { $auth = new AuthModel(); $rst = $auth->saveAuth($_POST); if ( $rst ) { $this->success('添加权限成功', U('Auth/showlist')); } } else { // 获取全部权限 $info = D('Auth')->select(); $this->assign('info', $info); foreach( $info as $k => $v ) { if ($v['auth_level'] == 1) { $info[$k]['auth_name'] = '-/'. $v['auth_name']; } else if ( $v['auth_level'] == 2 ) { $info[$k]['auth_name'] = '-/-/' . $v['auth_name']; } } // 组装 array([]); $authinfo = array(); foreach($info as $v) { $authinfo[$v['auth_id']] = $v['auth_name']; } $this->assign('authinfo', $authinfo); $this->display(); } } }?>

模型:

add($info); // 返回id 值 // auth_path // 全路径 // 如果权限是顶级权限 auth_path === auth_id本身记录id值; // 如果权限不是顶级权限 auth_path === 父级的auth_id - 本身id if ( $auth_pid == 0 ) { $auth_path = $auth_id; } else { // 获得父级的auth_path $p_info = $this->find($auth_pid); $p_auth_path = $p_info['auth_path']; $auth_path = $p_auth_path . '-' . $auth_id; } // 等级 auth_level // 根据auth_level处理 10-11-35 查找'-'的个数就是auth_level的值 $auth_level = count(explode('-', $auth_path))-1; // update $data = array( 'auth_id' => $auth_id, 'auth_path' => $auth_path, 'auth_level' => $auth_level ); return $this->save($data); } } ?>

转载地址:http://umevx.baihongyu.com/

你可能感兴趣的文章
网站分析系统
查看>>
一站式解决,Android 拍照 图库的各种问题
查看>>
JavaScript匿名函数以及在循环中的匿名函数
查看>>
中国HBase技术社区第五届MeetUp ——HBase技术解析及应用实践(深圳站)
查看>>
lsof命令
查看>>
阿里云云计算ACP考试知识点(标红为重点)
查看>>
从零开始来看一下Java泛型的设计
查看>>
嵌入式WiFi芯片价格战已经打响 MCU企业该醒悟了
查看>>
Shell编程基础
查看>>
二叉树的实现(C#)
查看>>
系统日子打印记录
查看>>
【矩阵乘法】OpenJ_POJ - C17F - A Simple Math Problem
查看>>
[旧博客]Python 第一次
查看>>
Verify the Developer App certificate for your account is trusted on your device.
查看>>
神经网络- receptive field
查看>>
java.lang.NoClassDefFoundError: org.ksoap2.serialization.SoapObject
查看>>
centos7.0搭建svn服务器
查看>>
JS多个对象添加到一个对象中
查看>>
九度 1376 最近零子序列
查看>>
yii---where or该如何使用
查看>>