thinkphp

MODULE_NAME
CONTROLLER_NAME
ACTION_NAME

tp3开发规范:

目录名: 
    全部小写+下划线
文件名: 
    类文件采用首字母大写的驼峰命名法定义
    其他文件为小写+下划线命名

类名:
    和类文件名保持一致(采用首字母大写驼峰命名法)
    5之前有UserController这样的Controller、model等后缀 

函数名、属性:
    首字母小写的驼峰命名法
常量:
    大写和下划线
配置名:
    小写+下划线

数据库 表和字段命名:
     必须小写+下划线

类库函数文件以.php结尾而5之前是.class.php

类的文件名以命名空间定义。且命名空间和类文件所在的路径一致

 

tp5开发规范:

需要大写的
类文件名:类文件采用驼峰法命名(首字母大写)
类名:类名和类文件名保持一致,统一采用驼峰法命名(首字母大写)
类方法:命名使用驼峰法(首字母小写),例如 getUserName;
类属性:命名使用驼峰法(首字母小写),例如 tableName
常量:以大写字母和下划线命名,例如 APP_PATH

函数:小写+下划线
目录:目录使用小写+下划线
文件:除类文件其他均以小写+下划线

 

模板提替换

tp5.0-:(包含5.0)

    'view_replace_str'       => [
        '__PUBLIC__'=>'xxx',
    ],

注意:5.0.24可直接使用如下模板替换变量:只针对根目录为public时没有问题(__STATIC__ 的值为 /static ,如果更目录改成与tp3默认的一样的话就少一个public了)

__ROOT__ :项目目录

__STATIC__ :项目目录下的static目录

__JS__ :项目目录下的static/js目录

__CSS__:项目目录下的static/css目录

tp5.1+(5.1及以上)

'tpl_replace_string'      => [
        '__PUBLIC__'     => 'xxx',
    ],

 

 

 

安全

异常封装

日志记录

开发单独开启sql日志

 

在index.php定义:
\think\Log::init([ 'type'=>'File', 'path'=>APP_PATH.'/sql_log', 'level'=>['sql'] ]);

 

 

 

tp5数据库操作:

mode lORM

原生:

use think\Db;
Db:query('select * from user where id=?',[$id])

构造器:前面的方法是不会真正的执行sql的只有select或者find之后才能调用

除了find、select之外还有update(更新)、delete(删除)、insert(删除)

还有聚合查询(count、max、min、avg、sum),。。。等等

 

use think\Db;

$result=Db::table('banner_item')->where('banner_id','=',$id)->select();

除了上面的执行语句的方法还有许多辅助的方法、他们也被成为链式操作方法

table、where、alias、field、strict、limit、page、order、group、having、join、union、distinct、lock、cache、comment、fethSql、force、partition、failException、sequence

带*表示可以多次调用

连贯操作作用支持的参数类型
where*用于AND查询字符串、数组和对象
whereOr*用于OR查询字符串、数组和对象
wheretime*用于时间日期的快捷查询字符串
table用于定义要操作的数据表名称字符串和数组
alias用于给当前数据表定义别名字符串
field*用于定义要查询的字段(支持字段排除)字符串和数组
order*用于对结果排序字符串和数组
limit用于限制查询结果数量字符串和数字
page用于查询分页(内部会转换成limit)字符串和数字
group用于对查询的group支持字符串
having用于对查询的having支持字符串
join*用于对查询的join支持字符串和数组
union*用于对查询的union支持字符串、数组和对象
view*用于视图查询字符串、数组
distinct用于查询的distinct支持布尔值
lock用于数据库的锁机制布尔值
cache用于查询缓存支持多个参数
relation*用于关联查询字符串
with*用于关联预载入字符串、数组
bind*用于数据绑定操作数组或多个参数
comment用于SQL注释字符串
force用于数据集的强制索引字符串
master用于设置主服务器读取数据布尔值
strict用于设置是否严格检测字段名是否存在布尔值
sequence用于设置Pgsql的自增序列名字符串
failException用于设置没有查询到数据是否抛出异常布尔值
partition用于设置分表信息数组 字符串

 

 

import()方法

import 语法:

boolen import(class, baseUrl, ext) 

 

参数说明:
参数说明
class必须,表示要导入的类库,采用命名空间的方式。
baseUrl可选,表示导入的基础路径,省略的话系统采用默认的规则,具体见下文。
ext可选,表示导入的类库后缀,默认是 .class.php 。

 

这个方法默认会以ThinkPHP\Library为相对起始目录  (这个目录包含了'Think','Org','Behavior','Com','Vendor'系统基类)
import("ORG.Util.Page");   // 导入 ThinkPHP系统目录/Lib/ORG/Util/Page.class.php 文件
如果是当前项目(),可以简化为:import("@.Action.UserAction");

逻辑:如果import截取第一个参数以@开头代表是当前项目那么他的起始目录为 APP_PATH.MODULE_NAME.'/' 即application/Home/
如果截取的第一个参数是'Think','Org','Behavior','Com','Vendor'中的其中一个那么他的起始目录为ThinkPHP/Library
如果以上两个都不是那么它的起始目录为APP_PATH 即 application/
所以:import('Home.Test.Alipay');和import('@.Test.Alipay');都能定位到aplication/Home/Test/Alipay.class.php
要想放在
ThinkPHP/Library 那么Test文件夹必须放到library下的'Think','Org','Behavior','Com','Vendor’这几个目录里我们用import调用时可以
import("ORG.Test.Alipay");import("Behavior.Test.Alipay");等等


非Composer安装的第三方库一般在extends目录 需要定义命名空间,否则不会自动加载
//该文件那么实际的类文件位置应该是: 1.extend/first/second/Foo.php
namespace first\second;
class Foo {

}


//使用first.second.Foo类的时候,直接实例化即可使用,例如:
$foo = new \first\second\Foo();
//或者:
use first\second\Foo;
$foo = new Foo();

//无命名空间则用:
Loader::import('first.second.Foo');
$foo = new \Foo();

 



vendor()导入第三方类库 第一个参数中的.会解析成/ #会解析成.

vendor('alipaycustom.AopEncrypt');                                                //vendor/alipaycustom/AopEncrypt.php
vendor('alipaycustom.alipaycustom#function');                               //vendor/alipaycustom/alipaycustom.function.php

 

 

配置:

改变配置文件的放置目录

publuc/index.php文件定义 define("CONF_PATH",__DIR__."/../conf/");   配置文件就从默认的 application/config.php 变成了 application/conf/config.php

 扩展配置

将配置文件放入extra目录:如aplipay.php       

获取:config(文件名.配置的键名)  如 config("aplipay.public_key")

场景配置:  比如 家里和公司

在公司环境中,我们在应用配置文件中配置:  'app_status'=>'office' 那么就会自动加载该状态对应的配置文件(默认位于application/office.php

场景配置文件和应用配置文件config.php是一样的定义。

如果我们回家后,我们修改定义为:'app_status'=>'home' 那么就会自动加载该状态对应的配置文件(位于application/home.php)。

 

thinkphp 架构URL访问中有这么一句    RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]  是将所有请求XXOO都转到 index.php/XXOO    $1就是^(.*)$ 

url生成

thinkphp5-    U()

thinkphp5+     url('模块/控制器/方法','参数')

注意多级控制器的情况下url的写法

application/admin/Controller/user/AdminUser.php  controller下多了一个目录
正确的写法  
 <a href="{:url('admin/user.adminuser/getuser')}">aaaaaaaaaa</a>
错误的写法
   <a href="{:url('admin/user/adminuser/getuser')}">bbbbb</a>

 同理:路由也是按上面的方式获取:Route::("hello/:id","admin/user.adminuser/getuser");

 

路由:

参数配置:

// 是否开启路由
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 路由使用完整匹配
'route_complete_match' => false,
// 是否强制使用路由    为true的话必须要为每个url配置路由才能访问哦 所以才开发阶段可以false 这样原url和路由url都可以访问到
'url_route_must' => false,

路由配置:

application/route.php

return [
    //'news/:id' => '控制器/模块/方法'  
    'news/:id' => 'index/index/info',
];
//配置以后访问localhost/index.php/index/index/info/id/5.html就访问不到了
//必须访问localhost/index.php/news/5.html

//怎么获取路由后的url呢?
//thinkphp5 的url函数现在可以自动生成路由的路径啦!
//但是之前的版本必须自己写代码实现

 

 

获取php全局变量

thinkphp5- :

 I()

thinkphp5+ :

input()
获取所有:input("param.");
获取所有post:input("post.");
获取get:input("get.");

 

 

模板输出:

thinkphp5-:

$this->display()

thinkphp5+:

return $this->fetch()

模板使用函数

{$data.name|md5} 

<?php echo (md5($data['name'])); ?>

{$name|md5|strtoupper|substr=0,3}
{:substr(strtoupper(md5($name)),0,3)}

<?php echo (substr(strtoupper(md5($name)),0,3)); ?>

多个参数:
{$create_time|date="y-m-d",###}

<?php echo (date("y-m-d",$create_time)); ?>


{$data.name|substr=0,3}
{$data.name|substr=###,0,3}

<?php echo (substr($data['name'],0,3)); ?>

 

 tp表达式查询

 自动验证

thinkphp5-: 

格式:

 

array(
①验证字段1,
② 验证规则,
③错误提示,
④验证条件(0:存在字段就验证(默认);1:必须验证;2:值不为空就验证),
⑤附加规则,
⑥验证时间(1:新增 2:更新 3:新增和更新(默认)),
⑦额外参数 数组形式 这个数组的每个值都是函数的一个参数(为callbck和function的时候)
),
额外参数试例
$create_data['identifier']=$identifier;
$extraArr=array(
    'ext'=>array('1','2','3','4'),
    'size'=>array(100,200,300),
    88
)
$rules=array( 
    array('identifier','checkedIdentifier','格式不正确',1,'function',3,),$extraArr),
); 

function checkedIdentifier($param,$val1,$val2,$val3){ 
    dump($param);//$create_data['identifier']的值 
    dump($val1);//第七个参数数组的第一个键值ext'=>array('1','2','3','4') 
    dump($val2);//'size'=>array(100,200,300) 
    dump($val3);//88 
}

 

静态验证:在model里定义$_validate属性;定义好验证规则后,就可以在使用create方法创建数据对象的时候自动调用:

namespace Home\Model;
use Think\Model;
class UserModel extends Model{
   protected $_validate = array(
     array('verify','require','验证码必须!'), //默认情况下用正则进行验证
     array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一
     array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内
     array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致
     array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
     array('password','md5','密码格式不正确',0,'function'), // 自定义函数验证密码格式
     array('img','checkImg','图片格式不正确',1,'callback',3,array('ext'=>array('jpg','jpeg','png','gif'))),


   );

  /**
   * 自定义图片后缀验证
  */
  public function checkImg($param,$value){
      $exts='';
      foreach($value as $val){
          $exts.="[".$val."]{1}|";
      }
      $exts=substr($exts,0,-1);;
      $str=$param;
      $preg="/^[\S]+[.]?(".$exts.")$/";
      if( preg_match($preg ,$str)){
          return true;
      }else{
          return false;
      }
  }
}

 

动态验证:动态验证不依赖模型类的定义,所以通常用M函数实例化模型就可以

$rules = array(
     array('verify','require','验证码必须!'), //默认情况下用正则进行验证
     array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一
     array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内
     array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致
     array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
    array('tel','/^1[34578]\d{9}$/','手机号码不对..1!',0,'regex',3),// 必填

); $User = M("User"); // 实例化User对象 if (!$User->validate($rules)->create()){ // 如果创建失败 表示验证没有通过 输出错误提示信息 exit($User->getError()); }else{ // 验证通过 可以进行其他数据操作 }

 tp3验证规则:系统内置或自定义的规则

//内置验证require不能为空
array('require','require','数据不能为空!',1),
//内置验证email,验证邮箱格式
array('email','email','邮箱格式不正确',1),
//内置验证url,验证网址
array('url','url','URL地址不正确',1),
//内置验证currency,验证货币
array('currency','currency','货币格式不正确',1),
//内置验证zip,验证邮编
array('zip','zip','邮政编码不正确',1),
//内置验证number,验证是不是正整数
array('number','number','不是正整数',1),
//内置验证integer,验证是不是整数
array('integer','integer','不是整数',1),
//内置验证double,验证是不是浮点数,正负均可
array('double','double','不是浮点数',1),
//内置验证english,验证是不是纯英文
array('english','english','不是纯英文',1),

 

tp3附加规则:配合验证规则使用

规则说明
regex

正则验证,定义的验证规则是一个正则表达式(默认)       

array('tel','/^1[34578]\d{9}$/','手机号码不对!',0,'regex',3),// 必填
array('name','/^[A-Za-z0-9\x{4e00}-\x{9fa5}]{2,20}$/u','不是汉字字母数字组成',1,'regex',3),
function

函数验证,定义的验证规则是一个函数名

array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
callback

方法验证,定义的验证规则是当前模型类的一个方法

array('user', 'checkLength', '用户名必须在 3-5 位', 0, 'callback', 3,array(3,5)),
confirm

验证表单中的两个字段是否相同,定义的验证规则是一个字段名

array('user', 'name', '两个用户名对比不同!',0,'confirm'),
equal

验证是否等于某个值,该值由前面的验证规则定义

array('user', '李炎恢', '值不对等', 0, 'equal'),
notequal

验证是否不等于某个值,该值由前面的验证规则定义(3.1.2版本新增)

array('user', '李炎恢', '值不能相等', 0, 'notequal'),
in

验证是否在某个范围内,定义的验证规则可以是一个数组或者逗号分割的字符串

array('user',  array(1,2,3), '不在指定范围', 0, 'in'),
notin

验证是否不在某个范围内,定义的验证规则可以是一个数组或者逗号分割的字符串(3.1.2版本新增)

array('user',  array(1,2,3), '不得在指定范围', 0, 'notin'),
length

验证长度,定义的验证规则可以是一个数字(表示固定长度)或者数字范围(例如3,12 表示长度从3到12的范围)

array('user', '3,5', '不得小于 3 位,不得大于 5 位', 0, 'length'),
between

验证范围,定义的验证规则表示范围,可以使用字符串或者数组,例如1,31或者array(1,31)

array('user',  array(3,5), '必须是 3-5 之间的数字', 0, 'between'),
array('user', '3,5', '必须是 3-5 之间的数字', 0, 'between'),
notbetween

验证不在某个范围,定义的验证规则表示范围,可以使用字符串或者数组(3.1.2版本新增)

array('user',  array(3,5), '必须不是 3-5 之间的数字', 0, 'notbetween'),
array('user', '3,5', '必须不是 3-5 之间的数字', 0, 'notbetween'),
expire验证是否在有效期,定义的验证规则表示时间范围,可以到时间,例如可以使用 2012-1-15,2013-1-15 表示当前提交有效期在2012-1-15到2013-1-15之间,也可以使用时间戳定义
array('user', '2014-1-10,2015-10-10', '时间已过期', 0, 'expire'),
ip_allow

验证IP是否允许,定义的验证规则表示允许的IP地址列表,用逗号分隔,例如201.12.2.5,201.12.2.6

array('user', '127.0.0.1', '当前 IP 没有被允许', 0, 'ip_allow'),
ip_deny

验证IP是否禁止,定义的验证规则表示禁止的ip地址列表,用逗号分隔,例如201.12.2.5,201.12.2.6

array('user', '127.0.0.1', '当前 IP 被禁止', 0, 'ip_deny'),
unique验证是否唯一,系统会根据字段目前的值查询数据库来判断是否存在相同的值,当表单数据中包含主键字段时unique不可用于判断主键字段本身
array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一

 

thinkphp5+: 

对某个字段多次验证

namespace app\index\validate;
use think\Validate;
class Comments extends Validate
{
    protected $regex = [ 'zip' => '/^1[3|4|5|8][0-9]{9}$/'];
    protected $rule = [
        'name' => 'require',
        'phone'   => "require|regex:zip",
        'phone_time'   => 'require',
    ];
   
    protected $message = [
        'name.require' => '姓名不能为空',
        'phone.require' => '联系方式不能为空',
        'phone.regex' => '联系方式格式不正确',
        'phone_time.require' => '接听时段不能为空',
    ];
}

 

验证进阶

 

 

 

 

自动完成

 

    protected $_auto=array(
        array('create_time','time',self::MODEL_INSERT,'function'), // 对create_time字段在新增的时候写入当前时间戳
        array('update_time','time',self::MODEL_UPDATE,'function'), // 对update_time字段在更新的时候写入当前时间戳
        array('pwd','md5',3,'function') , // 对password字段在新增和编辑的时候使md5函数处理
    );

 

字段映射

 

    /**
     * 字段映射
     * @var array
     */
    protected $_map=array(
        'member'=>'name',
        'password'=>'pwd',
    );

 

 

 

 

 

 参数绑定

手动绑定:

$Model = M('User');
$where['id']    =    ':id';
$where['name']  =    ':name';
$bind[':id']    =    array(I('id'),\PDO::PARAM_INT);
$bind[':name']  =    array(I('name'),\PDO::PARAM_STR);
$list = $Model->where($where)->bind($bind)->select();

自动绑定:

自动绑定不支持参数类型等额外设置,如果有必要请使用上面的手动绑定方式。

'DB_BIND_PARAM'    =>    true  //需要开启这个配置
然后 如下:
$Model = M('User');
$Model->name = 'thinkphp';
$Model->email = 'thinkphp@qq.com';
$Model->add();
等效于:
$Model = M('User');
$Model->name = ':name';
$Model->email = ':email';
$bind[':name']    = 'thinkphp';
$bind[':email']   = 'thinkphp@qq.com';
$Model->bind($bind)->add();

 

 关联模型

ThinkPHP 3.2.3 关联模型的使用

HSA_ONE:一对一,一个员工只有一个档案表(BELONGS_TO 也可用作一对一 可以理解他是son  BELONGS_TO它的parent)

支持:

属性描述
class_name要关联的模型类名
mapping_name关联的映射名称,用于获取数据用 该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。
foreign_key关联的外键名称
mapping_fields关联要查询的字段
condition关联条件
as_fields直接把关联的字段值映射成数据对象中的某个字段
mapping_type 关联类型

BELONGS_TO:多对一,一个员工只属于一个部门,但是部门里有多个员工

属性描述
class_name要关联的模型类名
mapping_name关联的映射名称,用于获取数据用 该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。
foreign_key关联的外键名称
mapping_fields关联要查询的字段
condition关联条件
parent_key自引用关联的关联字段 默认为parent_id 自引用关联是一种比较特殊的关联,也就是关联表就是当前表。
as_fields直接把关联的字段值映射成数据对象中的某个字段
mapping_type 关联类型

HAS_MANY:一对多,一个员工有多张银行卡,但是一张银行卡只属于一个员工

属性描述
class_name要关联的模型类名
mapping_name关联的映射名称,用于获取数据用 该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。
foreign_key关联的外键名称
parent_key自引用关联的关联字段 默认为parent_id
condition关联条件 关联查询的时候会自动带上外键的值,如果有额外的查询条件,可以通过定义关联的condition属性。
mapping_fields关联要查询的字段 默认情况下,关联查询的关联数据是关联表的全部字段,如果只是需要查询个别字段,可以定义关联的mapping_fields属性。
mapping_limit关联要返回的记录数目
mapping_order关联查询的排序

MANY_TO_MANY:多对多,一个员工可以属于多个组,每个组可以有多个员工

 

属性描述
class_name要关联的模型类名
mapping_name关联的映射名称,用于获取数据用 该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。
foreign_key关联的外键名称 外键的默认规则是当前数据对象名称_id
relation_foreign_key关联表的外键名称 默认的关联表的外键名称是表名_id
mapping_limit关联要返回的记录数目
mapping_order关联查询的排序
relation_table多对多的中间关联表名称

 

thinkphp5+

查询:

//原生
        $result=Db::query('select * from banner_item where img_id=?',[3]);
        //var_dump($result);
        $result=Db::table('banner_item')->where('banner_id','=',$id)->select();

 一对一:

hasOne('关联模型名','外键名','主键名',['模型别名定义'],'join类型');

belongsTo('关联主表模型名','从表外键名','关联表主表键名',['模型别名定义'],'join类型');

一对多:

hasMany('关联模型名','外键名','主键名',['模型别名定义']);

多对多:

belongsToMany('关联模型名','中间表名','外键名','当前模型关联键名',['模型别名定义']);

 

 

 

banner(记录有个项目有多少个轮播)                      banner_item(每个轮播的轮换个数)                   image(图片)

id                                                                              id    banner_id        img_id                                             id

                                                                                 1       1                   4                                                      4

                                                                                 2       1                   5                                                      5

                                                                                 3       1                   6                                                     6

banner:banneritem  一对多   (hasMany)

banner_item:img   一对一      (belongsTo,它也是多对一)    这里用hasOne会报错 因为外键在banner_item                                

注意:

一对一关系,存在主从关系(主表和从表 ),主表不包含外键从表包含外键

hasOne 和 belongsTo 都是一对一关系,区别:

在主表(不包含外键)的模型中建立关联关系,用 hasOne 

在从表(包含外键)模型中建立关联关系,用 belongsTo

 model/Banner.php

namespace app\api\model;
use think\Model;
use think\Db;
class Banner extends Model{

    public function items(){
               //banner关联 Banner_item表    
        return $this->hasMany('BannerItem','banner_id','id');
    } 
    
}

model/BannerItem.php

<?php

namespace app\api\model;
use think\Model;
class BannerItem extends Model{ 
    public function img(){
        //bannner_item 关联image表
        //return $this->belongsTo('Image','img_id','id');
        return $this->hasOne('Image','img_id','id');
    }
}

model/Image.php

<?php
namespace app\api\model;
use think\Model;
class Image extends Model{

}

在控制器方法中调用:

需引入  use app\api\Model\Banner as BannerModel;//这里的Banner和Model的Banner重名

//$banner=BannerModel::with('items')->find($id);//单表关联
$banner=BannerModel::with(['items','items.img'])->find($id);//多表关联(参数是定义的方法名 )
参数表明Banner类里有一个封装关联关系items方法 items.img 表示items方法里关联的表模型又关联了一个封装关联关系的img方法

 模型之with()关联预载入

 

 

 

 

改造:将关联查询封装到Banner.php中

model/Banner.php

<?php

namespace app\api\model;
use think\Model;
use think\Db;
class Banner extends Model{

    public function items(){
        return $this->hasMany('BannerItem','banner_id','id');
    } 
    
    public static function getBannerById($id){
        //TODO:根据bannerid号获取banner信息
        $result=self::with(['items','items.img'])->find($id);
        return $result;

    } 
}

控制器方法里这么调用:

<?php
namespace app\api\controller\v1;
use think\Controller;
use app\api\Model\Banner as BannerModel;//这里的Banner和Model的Banner重名


class Banner extends controller{


    public function  getBanner($id){
                
        $banner=BannerModel::getBannerById($id);
        //$banner->toArray();//拿到$data查出来的对象转数组 还有toJson()  
        //unsetc($data['delete_time']);//隐藏数据中的delete_time,不推荐
     $banner->hidden(['delete_time','update_time']);//隐藏数据中的某些数据
        $banner->visiable(['id','name']);//只显示数据中的某些值

    return $banner;
    return json($banner);
} }

 

 

 

 

图片路径不全,我们怎么和查询出来的数据进行拼接

tp5可以用读取器(获取器)来解决

如image表的url字段有个数据为/woman.jpg  并且我们将图片存到public/images目录下的

application/setting.php 定义

return [
'img_prefix'=>'http://www.tp5.lichihua.com/images'
];

获取可以

$img_prefix=config('setting.img_prefix');

组装:我么可以在model/Image.php中定义一个读取器的方法格式为 get+当前模型的某个字段名+Attr

 

<?php
namespace app\api\model;
use think\Model;
class Image extends Model{
    protected $hidden=['id','from','delete_time','update_time'];

    /**
     * url读取器   组装之后用model查询出来的url就是完整的路径了
     * from字段为1表示本站图片 2为网络资源即带有http:完整url路径
     * @param  max $value 自动获取的image表中url字段的值
     * @param  max $data  image的所有字段数据
     * @return string        返回组装好图片的url地址
     */
    public function getUrlAttr($value,$data){
        $finalUrl=$value;
        if ($data['from']==1) {
             $finalUrl = config('setting.img_prefix').$value;
        }
        return $finalUrl;
        
    }

}

 读取器触发的方式,模型调用字段属性的时候自动调用

如下面的代码也能调用getUrlAttr读取器方法:上面的getBannerById方法在 return $banner;时由于关联模型会关联到Image框架会自动的调用Image模型的每一个模型属性没有显示的调用!

$img=new Image();

$img->url;

但是其他的模型字段也有类似的需求呢?我们就需要新建一个基类集成mode然后其他的model集成这个基类然后将读取器放到基类里,

但是有个弊端当继承基类的模型可能隐式的调用有夺取器的字段时,他会自动调用读取器的,这不是我们所期望的,所以我们需要改造一下!

<?php
namespace app\api\model;
use think\Model;
class BaseModel extends Model
{

    public function prefixImgUrl($value,$data){
        $finalUrl=$value;
        if ($data['from']==1) {
             $finalUrl = config('setting.img_prefix').$value;
        }
        return $finalUrl;
        
    }            
}



<?php
namespace app\api\model;
use app\api\model\BaseModel;
class Image extends BaseModel{
    protected $hidden=['id','from','delete_time','update_time'];

    public function getUrlAttr($value,$data){
        return $this->prefixImgUrl($value,$data);
        
    }
}

  

 

 

 

 

 

 

 

 版本控制:

可以在route.php中这样定义:

 Route::get("api/:version/banner/:id","api/:version.Banner/getBanner");

然后:

http://www.tp5.lichihua.com/index.php/api/v2/Banner/1

http://www.tp5.lichihua.com/index.php/api/v1/Banner/1  

 

 

 

 

session、cookie 

    /* SESSION设置 */
    'SESSION_AUTO_START'    =>  true,    // 是否自动开启Session
    'SESSION_OPTIONS'       =>  array(), // session 配置数组 支持type name id path expire domain 等参数
    'SESSION_TYPE'          =>  '', // session hander类型 默认无需设置 除非扩展了session hander驱动
    'SESSION_PREFIX'        =>  '', // session 前缀
    //'VAR_SESSION_ID'      =>  'session_id',     //sessionID的提交变量

 

/**
 * session管理函数
 * @param string|array $name session名称 如果为数组则表示进行session设置
 * @param mixed $value session值
 * @return mixed
 */
function session($name='',$value='') {

    $prefix   =  C('SESSION_PREFIX');//配置文件的session前缀

    if(is_array($name)) { // session初始化 在session_start 之前调用
      
     // 第一个参数维数组且存在prefix键 则将此值赋值给配置的SESION_PREFIX if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
//如果配置文件重新定义的session_id 且$_COOKIE、$_POST、$_GET存在该值 则设置sessionid 如果传入的数组存在id则设置sesionid(类似秘钥)
if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){ session_id($_REQUEST[C('VAR_SESSION_ID')]); }elseif(isset($name['id'])) { session_id($name['id']); } if('common' == APP_MODE){ // 其它模式可能不支持 ini_set('session.auto_start', 0); } if(isset($name['name'])) session_name($name['name']); if(isset($name['path'])) session_save_path($name['path']); if(isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']); if(isset($name['expire'])) { ini_set('session.gc_maxlifetime', $name['expire']); ini_set('session.cookie_lifetime', $name['expire']); } if(isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0); if(isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies']?1:0); if(isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']); if(isset($name['cache_expire'])) session_cache_expire($name['cache_expire']); if(isset($name['type'])) C('SESSION_TYPE',$name['type']); if(C('SESSION_TYPE')) { // 读取session驱动 $type = C('SESSION_TYPE'); $class = strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type)); $hander = new $class(); session_set_save_handler( array(&$hander,"open"), array(&$hander,"close"), array(&$hander,"read"), array(&$hander,"write"), array(&$hander,"destroy"), array(&$hander,"gc")); } // 启动session if(C('SESSION_AUTO_START')) session_start(); }elseif('' === $value){ if(''===$name){ // 获取全部的session return $prefix ? $_SESSION[$prefix] : $_SESSION; }elseif(0===strpos($name,'[')) { // session 操作 if('[pause]'==$name){ // 暂停session session_write_close(); }elseif('[start]'==$name){ // 启动session session_start(); }elseif('[destroy]'==$name){ // 销毁session $_SESSION = array(); session_unset(); session_destroy(); }elseif('[regenerate]'==$name){ // 重新生成id session_regenerate_id(); } }elseif(0===strpos($name,'?')){ // 检查session $name = substr($name,1); if(strpos($name,'.')){ // 支持数组 list($name1,$name2) = explode('.',$name); return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]); }else{ return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]); } }elseif(is_null($name)){ // 清空session if($prefix) { unset($_SESSION[$prefix]); }else{ $_SESSION = array(); } }elseif($prefix){ // 获取session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null; }else{ return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null; } }else{ if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null; }else{ return isset($_SESSION[$name])?$_SESSION[$name]:null; } } }elseif(is_null($value)){ // 删除session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); if($prefix){ unset($_SESSION[$prefix][$name1][$name2]); }else{ unset($_SESSION[$name1][$name2]); } }else{ if($prefix){ unset($_SESSION[$prefix][$name]); }else{ unset($_SESSION[$name]); } } }else{ // 设置session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); if($prefix){ $_SESSION[$prefix][$name1][$name2] = $value; }else{ $_SESSION[$name1][$name2] = $value; } }else{ if($prefix){ $_SESSION[$prefix][$name] = $value; }else{ $_SESSION[$name] = $value; } } } return null; }

sesion初始化及设置

//初始化

sesion(array('name'=>'replacePHPSESSID'),'expire'=>3600,'id'=>'9h1bano5p1lvt6tac5nvbboac7');

//设置session

session('loginSign',1)

 

 

ThinkPHP 事务处理 (事务回滚) 、异常处理

         //进行付款处理   事务实现付款
         
         $user=M('User');
         $user->startTrans();
        // $new_user_money=$user_money-$order_total_money;
           //用户的积分增加
         $user_score= $user_info[0]['user_score']+$order_total_money;
         $user_status=$user->where(array('user_id'=>$user_id))->save(array('user_score'=>$user_score));
        // $order_status=M("Order")->where(array('order_id'=>$order_id))->save(array('order_state'=>'已付款'));
            //判断两个是否都执行成功
         if($order_status&&$user_status){
              $user->commit();
              //付款成功就显示到页面上
              //把信息写到用户消费表
              $user_payment['user_payment_money']="-".$order_total_money;
              $user_payment['user_payment_why']="在线购买";
              $user_payment['user_payment_time']=time();
              $user_payment['user_id']=$user_id;
              M('UserPayment')->add($user_payment);
                //删除session中保存的order_id信息
                session(C("USER_ORDER_ID"),null);
              //显示信息到前台去
              
              $this->order_no=$order_info[0]['order_no'];
              $this->order_total_money=$order_info[0]['order_total_money'];
 
         
         }else{
              //执行失败就回滚
             $user->rollback();
             $this->error('付款失败');
             exit;
         
         }

 多表的回滚:

$m=D('YourModel');//或者是M();
$m2=D('YouModel2');
$m->startTrans();//在第一个模型里启用就可以了,或者第二个也行
$result=$m->where('删除条件')->delete();
$result2=m2->where('删除条件')->delete();
if($result && $result2){
$m->commit();//成功则提交
}else{
$m->rollback();//不成功,则回滚
}

 

 

common 无法通过   域名/common/index/index 这种方式访问

我们需要在某个模块下定义一个commom方法 然后实例化并调用他 如:aplication/index/controller/index.php

//application/index/controller/Index.php
<?php
namespace app\index\controller;

use app\common\controller\Index as commonIndex;

class Index{
   public function index(){}

   public function common(){
       $common = new commomIndex();
       return $common->index(); 

   }

}
//aplication/common/controller/Index.php
<?php
namespace app\common\controller;
class Index
{
    public function index(){
    }
}

//application/index/controller/User.php
<?php
namespace app\index\controller;
use app\common\controller\User as commonUser;

class User extends commonUser{

   public function demo(){
       return $this->showName('zhangsan'); 
   }

}
//aplication/common/controller/User.php
<?php
namespace app\common\controller;
class User
{
    public function showName($name=' '){
        return "my name is {$name}";
    }
}
 
 

 

 Controller:

属性:

$view  :  \think\View 视图类实例 赋值__construct
$request  : \think\Request Request 实例  赋值__construct
$failException:  bool 验证失败是否抛出异常
$batchValidate:bool 是否批量验证
$beforeActionListarray 前置操作方法列表
方法:
_initialize:初始化操作
beforeAction($method, $options = []):前置操作
fetch($template = '', $vars = [], $replace = [], $config = []):加载模板输出
display($content = '', $vars = [], $replace = [], $config = []):渲染内容输出
assign($name, $value = ''):模板变量赋值
engine($engine):初始化模板引擎
validateFailException($fail = true):设置验证失败后是否抛出异常
validate($data, $validate, $message = [], $batch = false, $callback = null):验证数据

 

model:

 

 
 


 

转载于:https://www.cnblogs.com/lichihua/p/9477845.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值