thinkphp 学习日志

此文章仅对我所学内容的一个复习    也算是我php学习的一个总复习



thinkphp的行为 理解
用户访问某个方法是一个行为  
程序实例化一个类是一个行为
甚至是为一个变量赋值也是一个行为
那么  thinkphp 我们这里探讨的行为是什么呢
用户访问某方法前我们要对用户执行什么操作   用户访问某方法后我们执行什么操作     程序开始时我们进行什么操作     等等  诸如此类的行为我们
可以灵活的应用这些行为定义去判定一个用户是否登录   或者是用户访问这个页面是否拥有对这个页面的访问权限   或者是对用户的一种记录  即是追踪用户访问了
什么方法执行了什么操作  我们都可以根据用户的行为进行记录   这就是行为所拥有的作用
如何去定义一个行为呢?
如果在公共文件夹之中(Common)文件夹下的conf文件夹下配置的话     那么这个行为定义将应用于所有模块 
如果在模块的conf配置文件下配置的话    那么这个行为只作用于该模块     我推荐的是对所有模块进行记录

定义行为
需在conf文件夹下面  新建一个 tags.php  行为文件    (这个文件thinkphp系统框架会自动载入)
在这个文件之中我们就可以定义行为
<?php
return array(
/*定义了一个行为文件   该行为的作用是在每次用户访问网站内容之前(也就是访问框架上面的方法)调用这个行为   会默认执行改该类下的run方法
如果定义了行为  那么就必须在   行为类下面  定义一个run方法  供系统调用 行为是根据这个run(&param)方法执行的
*/
'action_begin'=>array('Home\\Behaviors\\BeforeBehavior'),
/*这个定义 告诉程序在每次用户访问方法之后将会  调用这个行为    一样的需要在该行为下面定义run(&param)方法*/
'action_end'=>array('Home\\Behaviors\\AfterVehavior'), 
);
?>
定义了我们的tags 行为文件以后我们就需要在  定义的行为文件内容指定的命名空间下面创建我们的行为文件
我这里的命名空间路径为Home模块下面Behaviors文件夹下面的BeforBehavior.class.php  和  AfterBehavior.class.php  
我这里只讲解AfterBehavior
文件名AfterBehavior.class.php
<?php
namespace Home\Behaviors;        //命名空间的定义
class AfterBehavior extends  \Think\Behavior{   //行为类 必须继承Think命名空间下面的Behavior类
public function run(){                //必须定义一个run(&param)方法  这个方法会随着用户访问方法过后自动被调用  行为是通过这个方法执行的

    }
}



create 方法  功能大全详解

在程序的开发有一种至理名言:永远不要相信用户提交的数据,因为你永远不知道用户提交的信息是不是合法的

sql语句过滤  I 方法
那么为了防止这种事情的发生 我们应该怎么办呢
在thinkphp中系统自定义了一些方法供我们调用  
对用户上传的数据进行过滤   用I方法   会对数据上传的信息进行过滤

表单合法性检测  
$insertFields(允许用户上传的数据库字段)    $updateFields(允许用户修改的数据库字段)
这个方法对用户上传的数据进行一种过滤  规定了用户对表中的数据哪些能上传  哪些不能上传

自动完成
protected $_auto=array(
        array('数据表字段','完成规则','完成时间','附加规则');
    );
/*
讲解注释
数据表字段    用户上传的时候对上传的数据进行自动验证   如果定义了字段映射   那么将会在字段映射之后对数据进行上传数据的处理
'数据表字段'  :   数据库中的实际字段
'完成规则'      :    应与'附加规则'配合使用  如果附加规则的值是callback那么'完成规则'字段的值应该在当前的类中定义一个方法   因为callback是回调方法
  他会在当前的类方法中寻找与'完成规则'字段相匹配的函数方法  找到就调用  找到就报错   如果'附加规则'字段的是function   那么首先会在php自带的函数库
  里面去找与之相匹配的函数   找到就调用  没找到  就会到公共函数库里面去找  注意 :公共函数库里面的函数是我们用自己定义的  
  该文件位于:公共文件(Common)下面的Common  或者是模块下面的Common  里面有都一有一个function.php  这两种是常用的方式
 '完成时间'   : 1(新增数据的时候处理  默认方式)
                 2(修改数据的时候处理)
                 3(不管是修改还新增都处理)
*/

自动验证
protected  $_validate=array(
        array('验证字段','验证规则','错误提示','验证条件','附加规则','验证时间'),
/*
讲解注释
'验证字段'  :   实际数据库的表字段
'验证规则'    :    支持函数正则等多样的规则   具体看手册
'错误提示'    :    当验证的字段没有通过验证时所要爆发的错误
'验证条件'    :    0(存在字段就验证  默认)
                1(必须验证  也就是如果字段未定义或者是上传文件时没有找到这个字段与之相配的数据时就会返回错误提示)
                2(值不为空的时候就验证  如果上传数据的时候存在这个数据就验证)
'附加规则'    :    应与验证规则配合使用   其实附加规则就是对验证规则的一个说明 附加规则默认的说明是验证规则是一个正则
如果附加规则是callback  那么代表的意义用自动完成之中callback所代表的意义相同 都是在当前类之中找回调函数   
如果附加规则是unique    那么就会将这个字段的值拿到数据库里面去匹配看表中是否存在相同的值  如果存在就返回一个false  输出错误信息
'验证时间'    :    1(新增数据的时候验证)
                2(修改数据的时候验证)
                3(全部情况下都验证 默认)
               
另外  系统为我们自定义了一些正则验证函数   如email  还有几个搞不清楚了   需要查手册才行

*/

字段映射
protected $_map=arary(
        '表单字段'=>'数据表字段',   //将表单字段的值 映射给数据表单字段值
    );
/*
讲解注释
用过字段我们可以隐藏真正数据表字段的值    在创建数据对象的时候自动映射成数据表的字段值
*/
    );
共5种方法配合使用  使我们数据的安全性能提升
经过上面的讲解  我们已经知道对用户数据的安全处理 I 方法 过滤用户语句  $insertFields(允许用户添加的数据表字段值) $updateFields(允许用户修改的数据表段值)
自动验证  $_validate  自动完成$_auto  字段映射 $_map 通过这几种方法我们就能有效的对数据安全进行管理了
例子: 
先创建一个Mysql数据库
create database tanyong default charset utf8 collate utf8_general_ci;
use tanyong;
create table tbl_user(
uid tinyint(6) primary key,
user varchar(15) unique not null,
pwd char(10) not null,
userRole varchar(30) not null,
id_card char(18)  unique not null,
createTime date
);
现在 我们的数据库创建好了   表的结构也设置好了  现在我们就开始定义
首先我们要让php连接mysql数据库    需在配置文件下面定义     文件地址   在公共文件夹下面(Common)下面的conf文件夹下的conf.php  或者是在模块配置文件(conf)
下面的conf.php
<?php
return array(
        'TMPL_L_DELIM'=>'<{',    //模板变量前识符
        'TMPL_R_DELIM'=>'}>',    //模板变量后识符
        'DB_PREFIX'=>'tbl_',    //表前缀
        'DB_TYPE'=>'mysql',     //要使用数据库类型
        'DB_NAME'=>'tanyong',   //数据库名
        'DB_USER'=>'root',        //数据库用户名
        'DB_PWD'=>'',        //由于我电脑上面的mysql数据库并未设置密码  所以我这里就不写密码 
        'DB_HOST'=>'localhost', //服务器地址
        'DB_PORT'=>3306,        //数据库端口号
    );
   
配置文件我们已经定义好了  下面我就开始定义控制器文件
所有的控制器文件都位于   模块目录下的Controller文件夹下面  当然你也可以自己更改配置   改变其文件夹的名称  这个就去手册中找吧
UserController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class UserController extends Controller{
/*进入用户注册页面*/
public function index(){
        $this->display();
    }

/*用户提交信息获取*/
public function getUser(){
        $data=I('post.');          //接受用户以POST方式传递过来的所有数据
        $user=D("User");           //实例化User表 
        $arr=$user->create($data);       //创建数据对象
        dump($arr);                //查看创建的数据对象
        if($user->add() > 0){      //如果数据表存在一个自动递增的且为主键的字段   那么add()方法会返回这个字段的值  如果没有这个字段  会根据
        //插入成功与否    返回值      成功就是1    失败就是0
        $this->success('添加成功');
        }else{
        $this->error('添加失败');
        }
    }

/*ajax 验证*/
public function userLogin(){
        $data=I('get.');            //接受来自前台的数据
        $new =    D('User');
        $count=$new->where($data)->count();
        if($count>0){
        $this->ajaxReturn(true);
        }else{
        $this->ajaxReturn(false);
        }
    }
}

现在我们开始定义模块文件   该文件位于模块目录下面Model文件夹下面
UserModel.class.php
<?php
namespace Home\Model;
use Think\Model;
class UserModel exntends Model{
/*字段映射*/
$_map=array(
    'username'=>'user',
    'password'=>'pwd',
    'sname'=>'userRole',
);   //映射表单的字段至数据库表的值

/*表单合法性检测*/
protected $insertFields=array('user','pwd','userRole','id_card');   //允许用户添加的字段
protected $updateFields=array('pwd','userRole');          //允许用户修改的字段

/*自动完成*/
protected $_auto=array(
        array('pwd','md5',3,'function'),      //不论是修改还是添加  都将对pwd字段进行Md5函数处理
        array('createTime','getDate',1,'callback'),  //在新增的时候对createTime字段进行回调函数调用  该函数位于 当前类下面定义
    );
/*自动验证*/
protected $_validate=array(
    array('user','','此用户已被注册',1,'unique',1),         //验证用户名是否被注册
    array('id_card','','此身份证号码已被使用',1,'unique',1), //验证用户的身份证号码是否重复
    array('userRole','','此角色名已被使用',1,'unique',1),     //验证用户使用的角色名是否已被使用
);

/*回调函数*/
private function getDate(){
        return date("Y-m-d H:i:s");
    }
}

简易前台注册页面html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" Content="text/html;charset=utf-8">
<titlte>注册页面</title>
<script src="./jquery-1.9.1.js"></script>
<script src="./jquery-1.9.1.min.js"></script>
<script>
$(function(){
            /*用户信息提交验证*/
        $("form").submit(function(){
            var username=$("#username").val();
            var password=$("#password").val();
            var loginpassword=$("#loginpassword").val();
            var userRole=$("#userRole").val();
            if(username=="" || password=="" || loginpassword=="" || userRole==""){
            alert('输入的信息不能为空');
            return false;
            }
            if(password!=loginpassword){
            alert('两次输入的密码不正确请重新输入');
            return false;
            }
        })
       
        /*ajax验证*/
        $("#username").focusout(function(){
        var username=$("#username").val();
        $.ajax({
            url:'__URL__/userLogin',          //异步获取的网页地址
            data:{user:username},              //要向目标页面异步传输的数据  采用的是json格式
            datatype:'text',                  //返回的诗句进行的处理  支持json  html  xml  text 等等的格式
            type:'get',                       //传输的方式
            success:function(data){           //当异步信息交互成功时   调用这个函数   其中data代表去接收异步信息返回过来的数据
                if(data=="true"){
                alert('该用户已被注册');
                }
                   
                }
            error:function(data){             //同上这个是当异步信息交互失败时调用这个函数
                    alert('请联系管理员');
                }
            });
        })
    })
</script>
</head>
<body>
<form action="__URL__/getUser" method="post">
<table cellpadding="0" cellspacing="0" border="1" width="600">
<tr>
<th colspan="2" align="center">用户注册</th>
</tr>
<tr align="center">
<td width="150">角色名:</td>
<td><input type="text" name="sname" id="sname"/></td>
</tr>
<tr align="center">
<td width="150">用户名:</td>
<td><input type="text" name="username" id="username"/></td>
</tr>
<tr align="center">
<td width="150">密码:</td>
<td><input type="password" name="password" id="password"/></td>
</tr>
<tr align="center">
<td width="150">确认密码:</td>
<td><input type="password" name="loginpassword" id="loginpassword"/></td>
</tr>
<tr align="center">
<td width="150">身份证号码</td>
<td><input type="text" name="id_card" id="id_card"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="sub" value="注册" /><input type="reset" value="重置" /></td>
</tr>
</table>
</form>
</body>
</html>

视图模型
在mysql数据库之中我们定义视图的格式是  create view viewTableName as select-----------------------------吧
但是thinkphp 为我们准备了一种更好的视图
视图模型需要继承model 下面的ViewModel类 
我这里定义了一个视图  这个视图的值有user表的 有cate表的  有score的
CreatetblModel.class.php
<?php
namespace Home\Model;
use Think\Model\ViewModel;
class CeratetblModel extends ViewModel{
public $viewFields=array(                     //定义的是这个视图拥有的数据库表的字段
        'User'=>array('uid','userRole','user'),
        'Score'=>array('score','sid','_on'=>'User.uid=Score.uid'), 
        /*讲解注释
        看格式都应该知道了   其中'User'代表的是User表  紧跟着=>代表着User表下面的  array(), uid字段、userRole字段、user字段
        Score  同理     '_on'=>''代表的是两张表的外键关联   这里的外键关联是 User.uid=Score.uid
        User表中的uid字段要与Score表中uid字段匹配
       
        扩展: 视图模型还可以支持别名定义  如我想给userRole定义一个别名   使之在抽取数据的时候使用别名进行数据的读取
        格式 'userRole'=>'userName'    这种用法可以区分两张存在相同的字段值进行区分  假设我要抽取User表中的userRole字段  并且我还有抽取Formation
之中的UserRole字段  那么这时候   就字段就重复了   在读取数据的时候 这个userRole字段  就不知道代表的是哪个表的字段值了  这时候别名为我们解决了
这个尴尬的问题       
        */
       
    );
}


关联模型
什么是关联模型?
要弄清楚这个问题 首先我们要清楚MVC的概念     M就是数据库之中的表映射到类!!!
那么数据库之中可以进行多表查询  如select user.uid,score,user,sid from tbl_user join tbl_score on tbl_user.uid = tbl_score ;
这样我们就将两张表有关系的数据提取了出来    这就叫做关联查询 
关联查询又分许多中
如  一对一(HAS_ONE )  : 一张身份证对应一个人,一张银行卡对应一个主人
    一对多(HAS_MANY)  : 我可以由很多张银行卡,我可以由很多台电脑 但是这么多银行卡只属于我一个人   很多台电脑也只属于我一个人
    多对多(MANY_TO_MANY)  :  我可以选修很多门课程,而课程可以选择很多名学生
只要知道了两张表对应的关系 我们就可以定义他们之间的关联模型了 
如我这里的user表 和 score表    每个用户都会有多个成绩(物理、数学、化学、----等)  那么这个属于上面陈述的那种类型呢
属于 一对多的关系  HAS_MANY  好,现在我们就开始定义关联模型  我们在UserModel里面定义  以User表去关联
UserModel.class.php
<?php
namespace Home\Model;
use Think\Model\RelationModel;               //要使用关联模型 就必须继承Model类下面的RelationModel类
class UserModel exntends RelationModel{
    protected $_link=array(                  //$_link  关联模型定义标识变量
        'Score'=>array(
            'mapping_type'=>self::HAS_MANY,  //关联关系定义 
            'class_name'=>'Score',             //关联的模型类  Score这个模型类可以不用定义   程序会自动定位到数据库之中查找与之相关的
            'foreign_key'=>'uid',             //外键定义  两张表关联的桥梁 (我的理解就是两张表里面两个相同字段)
            'mapping_name'=>'getScore',         //用户获取数据用 relation(getScore)  就会获得这个关联的数据
            'mapping_fields'=>'score,sid',     //要关联查询的字段  设置了这个  就会只抽取自定义的字段值   这里定义的是score,sid字段
        ),
        /*
        ''=>
        ''=>         n多关联模型的定义
        */
    );
}

在Controller 类之中调用关联模型
IndexController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends ControllerP{
public function index(){
        $user=D('User');
        dump($user->relation('getScore')->select());   //只抽取getScore的关联数据
        /*relation 方法详解
         如果传入的参数是true  那么将会抽取出所有的关联数据
         如果传入的参数如示例所示 那么就将只会抽取getScore关联的数据
         那么  我要抽取两个关联的数据  或者是多个关联的数据怎么办呢
        很简单   只要用数组的形式就要    如  relation(array('getScore','mapping_name所设置的值','....')....)这种格式就可以抽取多个关联之中
        定义的数据
        */
    }
}


session驱动支持
在php之中我们开启session的方式是  session_start(); 这个时候我们就可以在session里面添加数据了  并且在以后的php页面中使用要使用session都需要
session_start()一下 并且这个代码必须在所有代码前面
thinkphp是默认开启session支持的也就是说我们可以在控制器、函数、命名空间下定义的类、模型类中直接使用session 支持  这是我探索出来的
要改变session的存储路径  需要在Common公共文件夹下面的配置文件conf文件下面的config.php 
'SESSION_OPTIONS' =>array('path'=>'指定session文件的保存路径');//具体参考手册


路由功能
路由功能能使你的url地址得到简化
如果我要给某一个页面传递很大一串的get参数   那么url地址的长度将会非常的长   用路由的定义可以解决这个问题并且会美化你的url地址
要开路由的支持  需要在模块或者是公共配置文件下面定义
'URL_ROUTER_ON'   => true,    //开启路由支持
另外就是  thinkphp的路由功能是针对于模块设计的所有不能路由模块
剩下的就是路由规则了
'URL_ROUTE_RULES' => array(    //路由规则
        'news/:year/:month/:day'=>array('News/index','username=谭勇'), 
       
        /*讲解注释
        :year  匹配的是$_GET['year']
        :month 匹配的是$_GET['month']
        :day   匹配的是$_GET['day']
        这下 知道怎么扩展了   如果配置的是:name 那么匹配的就是$_GET['name']
        array('News/index','username=谭勇')  其中第一个参数是要路由到的目标地址   第二个参数是要向目标路由地址传入的参数
        */
    )
   
数据查询     (要学习这个要精通连贯方法   这个我就不仔细叙述   看手册)
在进行数据查询的时候 我们D方法查询  M方法查询 都可以催数据库进行操作 我建议的是用D方法进行操作
$user=D('User');     //实例化User模型     根据表映射到类的思想   我们操作这个类 其实就是在操作数据库之中的表
$arr=$user->where($where)->find(); 
/*讲解注释
where里面传入的是查询的条件  $where 就是查询的条件  建议使用数组查询  官网也是这样推荐的  也支持   对象查询 
例子
$where['sid']=130042106;
$where['name']=谭勇;
查询出相满足sid=130042106 and name=谭勇    记录的一行数据(find代表的是只查询满足where条件记录的一行数据)
select  查询满足所有的查询提交的记录数
field   查询field  定义的字段名的值 如:$user->where($where)->field('sid,name,age,userRole')->select();
查询满足条件$where记录数之中 field定义的字段数据  将之全部抽取出来    而不是抽取一行

limit 查询规定的记录数   如 limit 2,6   意为  从第2行开始向后抽取6行数据   如  limit 6,20  意为 从第6行开始向后抽取20行数据
好 那么我们就可以写了
$user->where($where)->limit(2,6)->select();   //查询出满足$where条件的从第二行开始向后抽取6行

page  分页   参数  ($count,$page)  $count:表总记录数    $page:每页显示的记录数
*/


thinkphp 防止xxs攻击
在接受用户传递过来的信息的时候 我们可以使用I函数去接收用户传递过来的数据 对数据进行初步的过滤  而且thinkphp自定义了对xxs攻击的一些操作
且我们可以清空所有的javascript脚本      用户通过的xxs攻击实际上是跳过javascript的验证   直接向服务器提交数据


判断用户是否在线这个功能的实现
首先我们需要在Mysql数据库之中建立一张表(userTopxian)   这一张表所代表的内容是:
用户登录过后    会在这张表上添加一行数据(userTopxian)并且 在用户所在那一行中修改他的登录状态   由0转为1    表示该用户已上线
并且在userTopxian 表之中插入的数据是用户的uid  生成的session文件的session_id  还有就是他的上线时间 
然后我们就可以去操作了   我们预先在服务器端  将所有的session文件存储我们规定的一个文件夹之中   且我们还需要将php的session自动回收机制给关闭了
  改为我们手动回收    
  然后我们需要在前台页面这一方面 写一jquery代码用户判定用户是否关闭了网页   当用户关闭了网页 或者是 进入了我们网站之外的url连接地址
  那么就会触发一个事件   这个事件是一个ajax请求    请求不要求有任何返回值  只要求有请求就Ok了     求情的目标地址之中  我们可以去获得当前
  用户的session_id   然后找到这个session_id所对应的文件    将session文件里面的内容    存入用户的文件夹下面的user.text  这个功能已经实现
  且将用户对应的数据表字段之中的状态重新设置为0   成为未登录状态
  并且 我们可以在mysql  添加一个触发事件
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值