资讯专栏INFORMATION COLUMN

PHP_ThinkPHP

wind3110991 / 2613人阅读

摘要:相关信息,面向过程,面向对象,轻量级。轻量级功能实用,面向过程和面向对象混合开发。找到文件为文件名为验证码类没有在自动加载类中载入,需要手动载入。底层的和会影响原始的框架中的引入,可以使用框架中提供的引入。

不使用框架的问题

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

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

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

开发程序,喜欢挖坑。

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

牵一发而动全身

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

相关信息

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

重量级:功能多,OOP面向对象,维护性好,生命力顽强。
轻量级:功能实用,面向过程和面向对象混合开发。

创建应用

创建入口文件,并引入核心框架入口文件 (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(),自动调用该魔术方法。

空操作处理:

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

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

空模块

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

空模块:http://xxxx/index.php?m=color&a=pink;
color不存在的控制器

空模块处理方式:

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

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

项目分组设置

ThinkPHP模块的分组:

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

项目分组对路由的影响:
http://www.xxxx.com/index.php/分组名称/控制器/方法

分组的范围:

Action控制器分组

Tpl模板分组

配置文件

静态资源分组

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();

模型相关方法分析

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

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

getByXXX() 查询数据

返回一维数组信息.
根据指定字段查询数据信息

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

having() 设置查询条件

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

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 1
echo $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记录的规则:

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

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

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

// 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自动验证:TP自动验证

UserModel.class.php中重写$_validate:

Smarty引入流程

控制器IndexAction.class.php
function index()

  $this->display();
  (父类Action的display)    

父类ThinkPHP/Lib/Core/Action.class.php

  $this->view->display();

ThinkPHP/Lib/Core/View.class.php
function display()

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

// 解析和获取模板内容 用于输出
function fetch()

tag("view_parse",$params);

ThinkPHP/Conf/tags.php
"view_parse" => array(

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

),

parseTempliteBahavior.class.php
function run()

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

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"}

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

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

通过路由参数

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

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

调用当前模块下的模板:
$this->display(模板名字) 模板名字没有后缀

调用其它模块下的模板:
$this->display(模块/模板名)

相对路径找到模板文件:(相对于入口文件index.html
$this->dispaly(相对路径)

引入机制

import引入机制

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

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

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

import("@.dir.dir.file");
e.g:import("@.Model.QqModel.class.php"); // Lib/Model/QqModel.class.php

ThinkPHP核心类文件

import("think.dir.dir.file");
e.g:import("think.car.dirver");  // ThinkPHP/Lib/car/dirver.class.php

扩展的类文件(ThinkPHP/Extend), 第三库文件引入

import("ORG.dir.dir.file");
e.g: import("ORG.color.pink"); // ThinkPHP/Extend/Library/ORG/color/pink.class.php

引入一个特殊文件名的类文件。#号使用。

// 找到文件为:// Lib/apple/bananer.good.flash.class.php
import("@.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) // 设置session
session(name, null) // 删除指定session
session(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.="  page-1)."">{$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.="  page+1)."">{$this->config["next"]}  ";

        return $html;
    }

    private function last(){
    $html = "";
        if($this->page==$this->pageNum)
            $html.="";
        else
            $html.="  pageNum)."">{$this->config["last"]}  ";

        return $html;
    }

    private function goPage(){
        return "  pageNum.")?".$this->pageNum.":this.value;location="".$this->uri."&page="+page+""}" value="".$this->page."" style="width:25px">pageNum.")?".$this->pageNum.":this.previousSibling.value;location="".$this->uri."&page="+page+""">  ";
    }
    
    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文件,数据库(超多张表,联表查询)。

// 设置缓存
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) 基于角色的权限控制

用户权限分配:权限比较直观,一项项分配。
缺点:不利于权限管理。(分配繁琐,管理混乱)

打包权限,分类管理。
利用角色对权限进行打包。

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("没有权限访问");
            }
            
        }
        
    } 

?>

给角色分配权限

数据模拟权限控制

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

为角色进行具体权限分配(控制,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);
        }
        
    } 
?>

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22247.html

相关文章

发表评论

0条评论

wind3110991

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<