2021-2-15-thinkphp6.0

composer、规范、url访问方式、控制器、连接数据库、数据操作、模型、路由

composer

php5.3以上的一个依赖管理工具,但不是包管理器。windows上下载exe文件后,点击下一步直至完成安装。

1)使用阿里云镜像

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

2)创建thinkPhp6.0项目

composer create-project topthink/think tp

3)启动项目

(1)进入目录

cd tp

(2)启动

php think run

规范

1)目录和文件

(1)目录名,小写+下划线

(2)类库和函数文件统一以.php为后缀

(3)类的文件名军以命名空间定义,且命名空间的路径和类库文件所在路径一直

(4)类文件采用驼峰命名,其他采用小写加下划线命名

(5)类名和文件名保持一致

2)函数、类、属性

(1)类名使用大驼峰

(2)函数名使用小写加下划线

(3)方法和属性使用小驼峰

3)常量与配置

常量和环境变量,以大写字母和下划线命名

配置参数以小写字母和下划线命名

4)数据表和字段

均使用小写加下划线方式命名


url访问方式

1)多APP

IP:prot/appName/className/methodName/argName/argValue

方法名是index可省略方法名

2)单APP

IP:prot/className/methodName/argName/argValue

方法名是index可省略方法名

3)index.php省略

appache的httpd.conf中打开mod_rewrite.so模块,将AllowOverride的None改为All


控制器

1定义

<?php
namespace app\controller;

use app\BaseController;

class HelloWorld extends BaseController
{
    public function hello()
    {
        return "方法名:".$this->request->action()."路径:".$this->app->getBasePath();
    }
}

2控制器目录

控制器目录可自定义,在文件app/config/routee.php中

return[
    'controller_layer'      => 'controller',
]

3多级控制器

在控制器目录下创建文件夹,将控制器放到文件夹内。如创建目录group,目录下放一个名为HelloWorld的控制器,里面有个hello的方法,此时访问路径为url:port/group.HelloWorld/hello

4渲染输出

1)使用return

2)使用json函数

3)中断执行使用halt函数

5自定义错误页面

在控制器目录下,建一个名为Error的文件和类,定义好index方法。当请求未找到控制器后,会使用该控制器,如果控制器中没有对应的方法,会报错。

<?php
namespace app\controller;

use app\BaseController;

class Error extends BaseController
{
    public function index()
    {
        return "访问路径不存在";
    }
}

连接数据库

1)配置

配置文件database.php中进行配置

2)调用数据库

<?php
namespace app\controller;

use app\BaseController;
use think\facade\Db;

class Test extends BaseController
{
    public function index()
    {
        $users = Db::table("tb_user")->select();
        return json($users);
    }
}

3)配置多数据库

(1)database.php文件

<?php
use think\facade\Env;

return [
    // 默认使用的数据库连接配置
    'default'         => Env::get('database.driver', 'mysql'),

    // 自定义时间查询规则
    'time_query_rule' => [],

    // 自动写入时间戳字段
    // true为自动识别类型 false关闭
    // 字符串则明确指定时间字段类型 支持 int timestamp datetime date
    'auto_timestamp'  => true,

    // 时间字段取出后的默认时间格式
    'datetime_format' => 'Y-m-d H:i:s',

    // 数据库连接配置信息
    'connections'     => [
        'mysql' => [
            // 数据库类型
            'type'              => Env::get('database.type', 'mysql'),
            // 服务器地址
            'hostname'          => Env::get('database.hostname', '127.0.0.1'),
            // 数据库名
            'database'          => Env::get('database.database', 'test'),
            // 用户名
            'username'          => Env::get('database.username', 'root'),
            // 密码
            'password'          => Env::get('database.password', ''),
            // 端口
            'hostport'          => Env::get('database.hostport', '3306'),
            // 数据库连接参数
            'params'            => [],
            // 数据库编码默认采用utf8
            'charset'           => Env::get('database.charset', 'utf8'),
            // 数据库表前缀
            'prefix'            => Env::get('database.prefix', ''),
            // 数据库调试模式
            'debug'             => Env::get('database.debug', true),
            // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
            'deploy'            => 0,
            // 数据库读写是否分离 主从式有效
            'rw_separate'       => false,
            // 读写分离后 主服务器数量
            'master_num'        => 1,
            // 指定从服务器序号
            'slave_no'          => '',
            // 是否严格检查字段是否存在
            'fields_strict'     => true,
            // 是否需要断线重连
            'break_reconnect'   => false,
            // 字段缓存路径
            'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
        ],
        'mysql_deepin' => [//新增的配置
            // 数据库类型
            'type'              => Env::get('database.type', 'mysql'),
            // 服务器地址
            'hostname'          => Env::get('database.hostname', '192.168.50.33'),
            // 数据库名
            'database'          => Env::get('database.database', 'test'),
            // 用户名
            'username'          => Env::get('database.username', 'root'),
            // 密码
            'password'          => Env::get('database.password', '123456'),
            // 端口
            'hostport'          => Env::get('database.hostport', '3306'),
            // 数据库连接参数
            'params'            => [],
            // 数据库编码默认采用utf8
            'charset'           => Env::get('database.charset', 'utf8'),
            // 数据库表前缀
            'prefix'            => Env::get('database.prefix', ''),
            // 数据库调试模式
            'debug'             => Env::get('database.debug', true),
            // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
            'deploy'            => 0,
            // 数据库读写是否分离 主从式有效
            'rw_separate'       => false,
            // 读写分离后 主服务器数量
            'master_num'        => 1,
            // 指定从服务器序号
            'slave_no'          => '',
            // 是否严格检查字段是否存在
            'fields_strict'     => true,
            // 是否需要断线重连
            'break_reconnect'   => false,
            // 字段缓存路径
            'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
        ],

        // 更多的数据库配置信息
    ],
];

(2)控制器中

<?php
namespace app\controller;

use app\BaseController;
use think\facade\Db;

class Test extends BaseController
{
    public function multyDb()
    {
        $orgs = Db::connect("mysql_deepin")->table("tb_org")->select();
        return json($orgs);
    }
}

访问http://127.0.0.1/Test/multyDb即可看到返回的数据

4)使用Model

(1)定义model类

需创建好一个与controller同父级的目录model,里面防止model的类

<?php

namespace app\model;

use think\Model;

class User extends Model{
    protected $connection="mysql";//设置数据源,省略后会连接默认数据源
}

注意:使用model的时候,会通过类名取关联数据库中的表,该类名为USER,关联的是user表,如果数据库中的表名为tb_user,需要取配置文件中设置表的前缀为“tb_”

(2)使用

<?php
namespace app\controller;

use app\BaseController;
use app\model\User;

class Test extends BaseController
{
    public function testModel()
    {
        $users = User::select();
        return json($users);
    }
}

数据操作

1查询(Array对象)

1)单条数据查询

//省略其他代码
Db::table("tb_user")->where('id',1)->find();//没查到数据时,返回null
Db::getLastSql();//得到最近一条SQL查询的原生语句
//省略其他代码
Db::table("tb_user")->where('id',1)->findOrFail();//没查到数据时抛出一个异常
//省略其他代码
Db::table("tb_user")->where('id',1)->findOrEmpty();//没查到数据时返回一个空数据

2)数据集查询(Collection对象)

//省略其他代码
Db::table("tb_user")->select();//获取到的时多行数据
//省略其他代码
Db::table("tb_user")->where('id',1)->selectOrFail();//没查到数据时抛出一个异常
//省略其他代码
$users = Db::table("tb_user")->select()->toArray();//转换成数据
dump($users);//查询详细

3)忽略前缀

//省略其他代码
$users = Db::name("user")->select();//表名为tb_user,但需确保配置文件中配置好前缀

4)获取单列值

//省略其他代码
Db::table("tb_user")->where('id',1)->value('user_name');//返回满足where条件这一行的列明为user_name的数据

5)获取多列值

//省略其他代码
Db::table("tb_user")->where('id',1)->column('user_name');

6)分批处理

数据量过大时导致内存开销过大,使用分批处理

Db:table("tb_user")->chunk(3,function($users){
	foreach($users as $user){
        dump($user);
    }
});

7)游标查询

$cursor = Db::table("tb_user")->cursor();
foreach($cursor as $user){
    dump($user);
};

8)链式查询

使用where、order等,会得到一个查询对象(Query),最后使用select或find会得到一个最终的数据对象(Array或Collection),在对一个查询对象多次操作时,可将其保存到一个变量中,反复调用,但上一次的where或order会保存在对象中,使用removeOption('where')可清楚掉上一次的操作

2新增

1)普通新增

//省略其他代码
$user=[
    'user_id' => '3',
    'user_name' =>"zhang"
];
Db::name("user")->insert($user);//成功后会返回1,表示插入1条数据成功

2)强制新增

//省略其他代码
$user=[
    'user_id' => '4',
    'user_name' =>"zhang11",
    "aaaa"=>"asdsdsd" //不存在的列
];
Db::name("user")->strict(false)->insert($user);//不会报错

3)替换新增

普通情况下插入两条主键相同的数据,会报错。使用replaceh后,插入数据,如果存在则替换,不存在就直接插入

//省略其他代码
$user=[
    'user_id' => '3',
    'user_name' =>"zhang11",
];
Db::name("user")->replace()->insert($user);//返回2

4)插入数据后返回当前数据id

//省略其他代码
$user=[
    'user_id' => '3',
    'user_name' =>"zhang11",
];
Db::name("user")->insertGetId($user);//返回id

5)批量插入

//省略其他代码
$users=[
    ['user_name' =>"zhang123"],
    ['user_name' =>"zhang1234"]
];
return Db::name("user")->insertAll($users);

6)save方法

//省略其他代码
$user=[
    'user_name' =>"zhang"
];
Db::name("user")->save($user);//有主键会进行更新,没有会插入一条新纪录

3修改

1基本操作

//省略其他代码
$user=[
    'user_name' =>"zhangh"
];
Db::name("user")->where('user_id',3)->update($user);
//修改后返回1,未进行修改返回0

2省略where

//省略其他代码
$user=[
    'user_id'=>'3',
    'user_name' =>"zhang"
];
Db::name("user")->update($user);//如果数据中包含主键可省略掉where

3exp()方法

//省略其他代码
Db::name("user")->where('user_id',3)->exp('user_name','UPPER(user_name)')->update();

4自增、减

//省略其他代码
Db::name("user")->where('user_id',3)->inc('age')->dec('weight',2)->update();

5raw()方法

//省略其他代码
Db::name("user")->where('user_id',3)->update([
    'user_name'=>Db::row('age+1')
]);

4删除

1)根据主键删除

//省略其他代码
Db::name("user")->delete(2);

2)根据主键批量删除

//省略其他代码
Db::name("user")->delete([1,2,3]);

3)通过where方法删除

//省略其他代码
Db::name("user")->where('user_id',2)->delete();

4)删除所有数据

//省略其他代码
Db::name("user")->delete(true);

5查询方式

1)比较查询

//省略其他代码
Db::name("user")->where('user_id','=',76)->find();
Db::name("user")->where('user_id',76)->find();
Db::name("user")->where('user_id','<>',76)->select();
Db::name("user")->where('user_name','like',['zh','huan','or'])->select();

2)模糊查询

//省略其他代码
Db::name("user")->whereLike('user_name',['zh','huan','or'])->select();
Db::name("user")->whereNotLike('user_name',['zh','huan','or'])->select();

3)区间查询

(1)between

//省略其他代码
Db::name("user")->where('user_id','between','19,25')->select();
Db::name("user")->where('user_id','between',[19,25])->select();
Db::name("user")->whereBetween('user_id','19,25')->select();
Db::name("user")->whereNotBetween('user_id','19,25')->select();

(2)in

//省略其他代码
Db::name("user")->where('user_id','in','19,25')->select();
Db::name("user")->whereIn('user_id','19,25')->select();
Db::name("user")->whereNotIn('user_id','19,25')->select();

(3)null

//省略其他代码
Db::name("user")->where('email','null')->select();
Db::name("user")->where('email','not null')->select();
Db::name("user")->whereNull('email')->select();
Db::name("user")->whereNotNull('email')->select();

4)EXP查询

//省略其他代码
Db::name("user")->where('user_id','exp','IN (19,25)')->select();
Db::name("user")->whereExp('user_id','IN (19,25)')->select();
//自定义字段后的SQL语句

6时间查询

//省略其他代码
Db::name("user")->where('create_time','>','2019-1-1')->select();
Db::name("user")->where('create_time','not between',['2019-1-1','2019-11-11'])->select();
Db::name("user")->whereBetween('create_time',['2019-1-1','2019-11-11'])->select();
//省略其他代码
Db::name("user")->whereTime('create_time','>','2019-1-1')->select();
Db::name("user")->whereBetweenTime('create_time','2019-1-1','2019-11-11')->select();

1)获取当年

//省略其他代码
Db::name("user")->whereYear('create_time')->select();

2)获取上一年

//省略其他代码
Db::name("user")->whereYear('create_time','last year')->select();

3)获取某一年

//省略其他代码
Db::name("user")->whereYear('create_time','2020')->select();

4)查询两小时内

//省略其他代码
Db::name("user")->whereTime('create_time','-2 hours')->select();

7聚合查询

//省略其他代码
Db::name("user")->count();
Db::name("user")->max('age');
Db::name("user")->min('age');
Db::name("user")->avg('age');
Db::name("user")->sum('age');

8子查询

1)buildSql

//省略其他代码
$subQuery = Db::name('sex')->field('id')->where('name','男')-buildSql(true);
$result = Db::name('user')->where('id','exp','IN'.$subQuery)->select();

2)函数方式

//省略其他代码
$result = Db::name('user')->where('id','in',function($query){
    $query->name('sex')->field('id')->where('name','男');
})->select();

9原生查询

//省略其他代码
$result1 = Db::query('select * from tb_user');
$result2 = Db::execute('UPDATE tb_user SET user_name="aaaa" WHERE user_id = 1');

10链式查询

1)where查询

Db::name('user')->where('user_id','>','1')->select();
Db::name('user')->where([
    'user_id'=>1
])->select();
Db::name('user')->where([
    ['user_id','>',1],
    ['age','>',11]
])->select();

$map[] = ['user_id','>',1];
$map[] = ['age','>',11];
Db::name('user')->where($map)->select();

2)whereRaw查询

Db::name('user')->whereRaw('user_id IN (7,8,9)')->select();

//预处理
Db::name('user')->whereRaw('user_id=:id',['id'=>1])->select();

3)field()

Db::name('user')->field('user_id,user_name')->select();
Db::name('user')->field(['user_id','user_name'])->select();

Db::name('user')->field('user_id,user_name as name')->select();
Db::name('user')->field(['user_id','user_name as name'])->select();

//聚合
Db::name('user')->field('user_id,SUM(age)')->select();

//显示查询所有字段,而不是*
Db::name('user')->field(true)->select();

//排除某一字段
Db::name('user')->withoutField('name')->select();

4)alias

//给数据库起一个别名
Db::name('user')->alias('a')->select();

5)limit

Db::name('user')->limit(0,1)->select();//从0开始

6)page

Db::name('user')->page(1,1)->select();//从1开始

7)order

(1)单字段

Db::name('user')->limit(0,11)->order('id','asc')->select();

(2)多字段

Db::name('user')->limit(0,11)->order(['age'=>'desc','weight'=>'asc'])->select();

(3)orderRaw

Db::name('user')->limit(0,11)->orderRaw('FIELD(user_name,"zhang") DESC')->select();
//SELECT * FROM `tb_user` ORDER BY FIELD(user_name,"zhang") DESC LIMIT 0,11

8)group

Db::name('user')->fieldRaw('user_id,AVG(age)')->group('type')->select();

9)having

Db::name('user')->fieldRaw('user_id,AVG(age)')->having('AVG(age)>0')->group('type')->select();

8)高级查询

(1)普通

Db::name('user')->where('user_name|email','like','%zhang%')
    ->where('age&weight','>',0)
    ->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zhang%' OR `email` LIKE '%zhang%' ) AND ( `age` > 0 AND `weight` > 0 )
//连个where间是and连接

(2)where和whereOr

$map1 = [
    ['user_name','like','%zh%'],
    ['email','like','%zh%']
];
$map2 = [
    ['user_name','like','%huan%'],
    ['email','like','%c%']
];
$result1 = Db::name('user')->where([$map1,$map2])->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zh%' AND `email` LIKE '%zh%' ) AND ( `user_name` LIKE '%huan%' AND `email` LIKE '%c%' )

$result1 = Db::name('user')->whereOr([$map1,$map2])->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zh%' AND `email` LIKE '%zh%' ) OR ( `user_name` LIKE '%huan%' AND `email` LIKE '%c%' )

9)事务

Db::Transaction(function(){
    Db::name('user')->where('user_id',1)->save(['money'=>Db::raw('money+3')]);
    Db::name('user')->where('user_id',2)->save(['money'=>Db::raw('money-3')]);
});
Db::startTrans();
try{
  Db::name('user')->where('user_id',1)->save(['money'=>Db::raw('money+3')]);
  Db::name('user')->where('user_id',2)->save(['money'=>Db::raw('money-3')]);
  Db::commit();
}catch(Exception $e){
    Db::rollback();
}

10)获取器

//对查询结果进行处理
Db::name('user')->withAttr('email',function($value,$data){
    return strtoupper($value);
})->select();

11)数据集

(1)获取数据集

$user = Db::name('user')->select();

(2)转换成数组

$user->toArray();

(3)随机打乱

$user->shuffle();

(4)删除最后一个元素

$user->pop();//返回被删除的数据

模型

1定义

<?php

namespace app\model;

use think\Model;

class Org extends Model{
    protected $connection = "mysql_deepin";//指定数据源
    protected $name = 'org';//指定模型的后缀,表名=前缀+后缀
    protected $pk = 'org_id';//指定主键
    protected $table = 'tb_org';//指定表名
}

2查询

//省略部分代码
//查询
Org::select();
Org::find(1);

Org:where('org_id','>',1)->limit(5)->order('id','desc')->select();

Org:whereIn('org_id',[6,7,8]);

Org::max('id');

3新增

//省略部分代码

//新增
Org::insert([
    'org_id'=>2,
    'org_name'=>'机构2'
]);

//模型对象的save方法
$org = new Org();
$org->save(['org_name'=>'机构']);//会自动填充create_time和update_time

$org = new Org();
$org->org_name = '机构a';
$org->save();

//批量新增
$orgs = [
    ['org_name'=>'机构aaa'],
    ['org_name'=>'机构bbb']
];
$org = new Org();
$org->saveAll($orgs);//返回新增的两个对象

//静态方法
Org::create([
    'org_name'=>'静态机构'
],['org_name'],false);
//参数1是新增的数组,必选
//参数2是允许写入的字段,可选
//参数3为是否replace写入,默认为false
//返回值是新增的数据对象

4删除

$org = Org::find(1);
$org->delete();

//批量删除
Org::destroy([2,3]);

//条件删除
Org::where('id','=',3).delete();//返回boolean

//闭包方式
Org::destroy(function($query){
   $query->where('id'.'>',5); 
});
    
   

5修改

$org = Org::find(1);
$org->org_name = '机构a';
$org->save();

//批量修改
$list=[
    [
        'org_id'=>1,
        'org_name'=>'机构3'
    ],
    [
        'org_id'=>2,
        'org_name'=>'机构4'
    ]
];
$org = new Org();
$org->saveAll($list);

//静态修改
Org::update([
    'org_id'=>1,
    'org_name'=>'降级'
]);

Org::update([
    'org_name'=>'降级'
],['org_id'=>1]);//主键放到后面的数组

Org::update([
    'org_name'=>'降级'
],['org_id'=>1],['org_name']);//第三个参数限制可更新字段为org_name

6字段缓存问题

每次操作时,都会去查找字段类型,需要将字段信息缓存起来。在config/database.php中开启字段缓存。'field_cache'=>true

7动态获取器

User::withAttr("email",function($value){
    return strtoupper($value);
})->find(4);

8强制全局范围查询

(1)定义模型

<?php

namespace app\model;

use think\Model;

class User extends Model{
    protected $globalScope=['status'];
    public function scopeStatus($query){
        $query->where('status','>=',0);
    }
}

(2)调用

User::withAttr("email",function($value){
    return strtoupper($value);
})->find(4);
//SELECT * FROM `tb_user` WHERE `status` >= 0 AND `user_id` = 4 LIMIT 1

//去掉强制
User::withoutGlobalScope()->select();

9隐藏字段

User::select()->hidden(['money']);

10仅显示部分字段

User::select()->visible(['money']);

11自动填充时间

确保database.php中'auto_timestamp' => true

有时需要关闭某个模型中的自动填充功能,在该模型中新增属性protected $autoWriteTimestamp=false

12设置只读字段(只支持模型)

(1)静态

在模型中新增属性protected $readonly=['username','email']

(2)动态

$user = User::find(4);
$user->email = 'aaa@qq.com';
$user->age = 55;
$user->readonly(['email'])->save();

13类型转换

在模型中新增属性protecte $type=['user_id'=>'int']

14废弃字段

在模型中新增属性protected $disuse=['status']

15存放json

(1)Db操作

//存
$org = [
    'org_name'=>"机构谔谔谔",
    "list"=>["name"=>"zhang"]
]
Db::name('org')->json(['list'])->save($org);

//取
Db::name('org')->json(['list'])->select();

//根据json属性取数据
Db::name('org')->json(['list'])->where('list->name',"wewqweq")->find();

//修改
$org = Db::name('org')->json(['list'])->find(13);
$org['list'] = ['name'=>'zaaaa'];
Db::name('org')->json(['list'])->save($org);

//修改json中某一个数据
$org = Db::name('org')->json(['list'])->find(13);
$org['list']['name'] = "aaasdsd";
Db::name('org')->json(['list'])->save($org);

(2)模型操作

在模型中定义属性protected %json=['list'];,就会指定list为存放json的字段

16软删除

(1)新增字段

表中新增delete_time的字段

(2)模型中开启软删除

新增代码use SoftDelete;protected $deleteTime = 'delete_time'

<?php
namespace app\model;

use think\Model;
use think\model\concern\SoftDelete;

class User extends Model
{
    use SoftDelete;
    protected $deleteTime = 'delete_time';
}

(3)调用

// 软删除
User::destroy(1);
// 真实删除
User::destroy(1,true);

$user = User::find(1);
// 软删除
$user->delete();
// 真实删除
$user->force()->delete();
//注意:已经软删除的数据,需要先还原,再进行真实删除

(4)报错问题

日期字段如果不是int类型会报错,这里需要在模型中放入以下属性

protected $autoWriteTimestamp = 'datetime';

(5)查询软删除数据

User::withTranshed()->select();
User::onlyTranshed()->select();

(6)还原软删除数据

$user = User::onlyTranshed()->find(10);
$user->restore();

17模型事件

事件 描述 事件方法名
after_read 查询后 onAfterRead
before_insert 新增前 onBeforeInsert
after_insert 新增后 onAfterInsert
before_update 更新前 onBeforeUpdate
after_update 更新后 onAfterUpdate
before_write 写入前 onBeforeWrite
after_write 写入后 onAfterWrite
before_delete 删除前 onBeforeDelete
after_delete 删除后 onAfterDelete
before_restore 恢复前 onBeforeRestore
after_restore 恢复后 onAfterRestore

在模型类里面定义静态方法来定义模型的相关事件响应

<?php
namespace app\model;

use think\Model;
use app\model\Profile;

class User extends Model
{
    public static function onBeforeUpdate($user)
    {
    	if ('thinkphp' == $user->name) {
        	return false;
        }
    }
    
    public static function onAfterDelete($user)
    {
		Profile::destroy($user->id);
    }
}

18关联

1)一对一

(1)模型中新增方法

<?php

namespace app\model;

use think\Model;
use think\model\concern\SoftDelete;

class User extends Model{
    protected $pk = 'user_id';

    public function detail(){
        return $this->hasOne(Detail::class, 'user_id');//指向目标模型,第二个参数是外键
    }

}

(2)调用

//取出关联表的字段内容
$user = User::find(1);
echo $user->detail->phone;

//取出一条数据包含detail
$user = User::with('detail')->find(1);
echo $user;

//修改关联表
$user = User::with('detail')->find(1);//with是预加载
$user->detail->save(['phone'=>'18608086840']);

//从user表中查出其关联表detail关联id=1的数据
$user = User::hasWhere('detail',['id'=>1])->find();

//查出其关联表中关联该表的数据记录条数>=2的数据
User::has('detail',">=",2)->select();

//向关联表中新增数据
$user = User::find(1);
$user->detail()->save(['phone'=>122222222]);

//关联删除
$user = User::with('detail')->find(1);
$user->together(['detail'])->delete();

//延时加载
$user = User::find(1);
$user->load();
echo $user->detail->phone;

(3)关联表数据统计

//查出数据包含关联表记录条数
User::withCount(['detail'])->select();

//计算关联表某一字段总和,值赋给totalMoney
User::withSum(['detail'=>'totalMoney'],'money')->select();

2)一对多

(1)定义中间表模型

<?php


namespace app\model;

use think\model\Pivot;

class Access extends Pivot
{

}

(2)定义其中一张主表

<?php

namespace app\model;

use think\Model;

class User extends Model{

    public function roles(){
        return $this->belongsToMany(Role::class,Access::class,'role_id','user_id');
    }

}

(3)调用

//查询
$user = User::find(1);
$roles = $user->roles;

//向关联表插入数据
User::find(1)->roles()->save(['name'=>'测试管理员']);

//向第三张表中插入关联关系
User::find(1)->roles()->save(1);
User::find(1)->roles()->save(Role::find(1));//等同
User::find(1)->roles()->attach(1);//等同

//删除第三张表的关联关系
User::find(1)->roles()->detach(3);

路由

1路由相关的文件

1)配置文件

配置路由功能的文件,位于config/route.php

2)定义文件

定义路由的文件,位于route/route.php

2定义路由

(1)普通

Route::rule('user/:id','UserController/getUserById','GET')->pattern(['id'=>'\d+']);//id为参数

(2)全局规则

Route::pattern(['id'=>'\d+'])

(3)多级控制器

Route::rule('detail/:id','goup.Blog/detail');

(4)完整路径控制器

Route::rule('detail/:id','\app\controller\goup.Blog@detail');//用@访问方法

(5)重定向

Route::redirect('ds/:id','http://localhost',302);

3路由参数检测

1)强制后缀

//强制使用该后缀
Route::rule('detail/:id','goup.Blog/detail')->ext('html');
//禁止使用该后缀
Route::rule('detail/:id','goup.Blog/detail')->denyExt('jpg');

2)强制https

Route::rule('detail/:id','goup.Blog/detail')->https();

3)跨域

Route::rule('detail/:id','goup.Blog/detail')->allowCrossDomain();
Route::rule('detail/:id','goup.Blog/detail')->allowCrossDomain([
    'Access-Control-Allow-Origin'=>'http://abc.com'
]);

4路由分组

Route::group('adress',function(){
    Route::rule(':id','Address/details');
    Route::rule(':name','Address/read');
})->parttern(['id'=>'\d+','name'=>'\w+']);//省略路由字符串

Route::group('adress',function(){
    Route::rule(':id','details');
    Route::rule(':name','read');
})->prefix('Address')
    ->parttern(['id'=>'\d+','name'=>'\w+']);//省略类字符串

5错误页面

Route::miss('public/miss');//调用Error控制器的miss方法

可全局生效和局部生效,由该段代码的位置决定


获取请求对象

1)注入方式

<?php
namespace app\controller;

use app\BaseController;
use app\Request;//注意

class Index extends BaseController
{
    protected $request;

    public function __construct(Request  $request)
    {
        $this->request = $request;
    }

    public function index()
    {
        dump($this->request);
    }

}

2)静态方式

<?php
namespace app\controller;

use app\BaseController;
use think\facade\Request;//注意,调用的是门面里的request

class Index extends BaseController
{

    public function index()
    {
        dump(Request::param('id'));
    }

}

3)助手函数

<?php
namespace app\controller;

use app\BaseController;

class Index extends BaseController
{

    public function index()
    {
        dump(\request()->param('id'));
    }

}

助手函数input

input('?get.id');//判断get下id是否存在
input('?post.id');//判断get下id是否存在
input('param.id');//获取param下id
input('param.id','默认值');//获取,并设置默认值
input('param.id','','htmlspecialchars');//过滤器

中间件

在php中没有AOP,所以对于权限等的控制依赖于中间件。所有的请求都会经过中间件,可对请求进行控制,如权限、日志记录等,相当于过滤器

1全局中间件

1)定义过滤器

在app目录下创建middleware目录,并在里面放入如下代码

<?php

namespace app\middleware;

class Check
{
    public function handle($request, \Closure $next)
    {
        //前置逻辑
        echo $request->url();
        $res = $next($request);

        //后置逻辑

        return $res;
    }
    public function end(){
        echo "结束";
    }
}

2)为过滤器定义别名

在config目录下的middleware.php文件中定义

<?php
// 中间件配置
return [
    // 别名或分组
    'alias'    => [
        'check' =>[\app\middleware\Check::class]
    ],
    // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
    'priority' => [],
];

3)注册

在app目录下创建middleware.php文件,写入如下代码

<?php
return [
    'check',//通过别名注册过滤器,也可以直接写\app\middleware\Check::class
];

2路由中间件

定义过滤器、起别名和全局中间件一样,注册只需直接注册到路由上,以下是路由文件,即Route/app.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Route;

Route::group('article',function(){
    Route::rule('','ArticleController/getArticle','GET')->middleware(['check']);//注册中间件
    Route::rule('','ArticleController/addArticle','POST');
    Route::rule('','ArticleController/updateArticle','PUT');
    Route::rule('/list','ArticleController/getArticleList','GET');
    Route::rule('/:id','ArticleController/deleteArticle','DELETE');
});

3控制器中间件

定义过滤器、起别名和全局中间件一样,注册只需将以下属性放到控制器里

protected $middleware = ['check'];

thinkphp访问数据库报错

#0 [0]PDOException in PDOConnection.php line 554 
could not find driver

错误原因是php的pdo模块未打开,需要在php.ini文件中找到

;extension=pdo_mysql

去掉左边的';',表示打开注释,开发pdo模块。如果php目录小没有php.ini文件,则需要将php.ini-development另存为php.ini,并进行以上操作,完成后重启项目即可。

posted @ 2024-03-22 17:14  SylvesterZhang  阅读(33)  评论(0)    收藏  举报