ThinkPHP V5.0 入门学习


ThinkPHP V5.0 入门学习


正文

大致先翻一遍文档,对框架有个印象。先确定用哪个版本,再查看相应文档,如 ThinkPHP5.0 https://www.kancloud.cn/manual/thinkphp5

然后看一下视频,找找感觉: 《ThinkPhP5基础视频教程》

再就是项目实战,慢慢上手。

视频整体分为四部分:

  1. Thinkphp5基础视频教程
  2. Thinkphp项目开发实战视频教程
  3. Thinkphp项目服务器架构视频教程
  4. 第三方接口视频教程

《TP5 视频教程课程内容》
    
第一、ThinkPHP5
    TP5 官网基础教程, 官网手册作为参考,讲解TP5的使用方法.理解TP的用途

第二、TP5大型项目实战及底层源码分析
    用TP5 做大型电商项目. 内容全面 涵盖知识面广 
    ThinkPHP底层源码分析 Thinkphp shop 简称 TPshop 底层源码分析

第三、服务器集群 
    TPshop  memcache  redis  sphinx  keepalived  lvs  MongoDB  mysql 主从 读写分离
分表分库 集群服务器,消息队列 负载均衡 高并发 大数据设计 数据库优化 
多台服务器 节点数据同步类,thinkphp底层代码断点调试逐行追踪,php防注入防木马防黑客入侵 seo 基础

第四、Thinkphp框架底层源码分析 
    TPshop手机端 APP Android IOS api对接

第五、微信开发部分 
    TPshop项目整合到 微信商城 微信开发模块 微信公众号服务号 ,微信各个接口开发

第六、
    TPshop项目测试 php代码断点调试逐行追踪

第七、第三方接口集成部分
    TPshop用户 注册登录(接口 QQ 微信 微博 支付宝 登录接口) 选购 下单 
结款(支付各种 支付宝,财富通,微信,银联等支付) 
完成(物流各大物流查询接口, 百度地图接口)

ThinkPhP5基础视频教程

《ThinkPhP5基础视频教程》, 这个视频用的文档是 《ThinkPHP5快速入门》 , 应该是这个文档的作者自己出的视频。

《ThinkPHP5快速入门》的文档目录:

零、序言

一、基础

(1)简介
(2)安装
(3)目录结构
(4)运行环境
(5)入口文件
(6)资源访问
(7)调试模式
(8)控制器
(9)视图
(10)读取数据
(11)总结

二、URL和路由

(1)URL访问
(2)参数传入
(3)隐藏入口
(4)定义路由
(5)URL生成
(6)总结

三、请求和响应

(1)请求对象
(2)请求信息
(3)响应对象
(4)总结

四、数据库

(1)准备
(2)数据库配置
(3)原生查询
(4)查询构造器
(5)链式操作
(6)事务支持

五、查询语言

(1)查询表达式
(2)批量查询
(3)快捷查询
(4)视图查询
(5)闭包查询
(6)获取值和列
(7)聚合查询
(8)时间查询
(9)字符串查询
(10)分块查询

六、模型和关联

(1)模型定义
(2)基础操作
(3)读取器和修改器
(4)类型转换和自动完成
(5)查询范围
(6)输入和验证
(7)关联
(8)模型输出

七、视图和模板

(1)模板输出
(2)分页输出
(3)公共模板
(4)模板定位
(5)布局模板
(6)标签定制
(7)输出替换
(8)渲染内容
(9)助手函数

八、调试和日志

(1)第一式:未雨绸缪——页面Trace
(2)第二式:初见端倪——异常页面
(3)第三式:拨云见日——断点调试
(4)第四式:欲穷千里——日志分析
(5)第五式:运筹帷幄——远程调试

九、API开发

(1)API版本
(2)异常处理
(3)RESTFul
(4)REST调试
(5)API调试
(6)安全建议

十、命令行工具

(1)查看指令
(2)模块生成
(3)控制器生成
(4)生成类库映射文件
(5)生成路由缓存
(6)生成字段缓存
(7)指令扩展
(8)命令行调试
(9)命令行颜色支持
(10)命令调用

十一、扩展

(1)函数扩展
(2)类库扩展
(3)驱动扩展
(4)Composer扩展

十二、杂项

    Session
    Cookie
    验证码
    文件上传
    图像处理
    单元测试

番外篇:学习ThinkPHP5的正确姿势
概念篇:ThinkPHP5名词解释
附录A、常见问题集
附录B、3.2和5.0区别
附录C、助手函数
附录D、5.1你必须努力避免的一些问

《ThinkPhP5基础视频教程》的视频列表:

P11.ThinkPhP5 视频教程课程内容(一):课程大纲     12:51
P22.1ThinkPhP5 视频教程(二)上:入门与安装       28:46
P32.2ThinkPhP5 视频教程(二)下:入门与安装       20:01
P43.ThinkPhP5 视频教程(三):URL和路由 - 路由       20:42
P54.ThinkPhP5 视频教程(四):URL和路由 - URL      32:44
P65.ThinkPhP5 视频教程(五):请求和响应 - 请求        24:18
P76.ThinkPhP5 视频教程(六):请求和响应 - 响应        14:28
P87.ThinkPhP5 视频教程(七):SQL追踪器        21:10
P98.ThinkPhP5 视频教程(八):数据库-基本操作      24:59
P109.ThinkPhP5 视频教程(九):数据库-事务、链式操作      19:39
P1110.ThinkPhP5 视频教程(十):查询语言-上      21:25
P1211.ThinkPhP5 视频教程(十一):查询语言下      22:30
P1312.ThinkPhP5 视频教程(十二讲):模型和关联-上       21:57
P1413.ThinkPhP5 视频教程(十三讲):模型和关联-下       30:57
P1514.ThinkPhP5 视频教程(十四讲):读取器与修改器       20:43
P1615.ThinkPhP5 视频教程(十五讲):转换与自动完成       29:27
P1716.ThinkPhP5 视频教程(十六讲):查询范围      16:07
P1817.ThinkPhP5 视频教程(十七讲):输入和验证-上       22:48
P1918.ThinkPhP5 视频教程(十八讲):输入和验证-下       12:50
P2019.ThinkPhP5 视频教程(十九讲):关联-一(一对多)     23:47
P2120.ThinkPhP5 视频教程(二十讲):关联-二(一对多)     16:58
P2221.ThinkPhP5 视频教程(二十一讲):关联-三(一对一)        20:56
P2322.ThinkPhP5 视频教程(二十二讲):关联-四(多对多)        24:52
P2423.ThinkPhP5 视频教程(二十三讲):关联-五(多对多)        23:23
P2524.ThinkPhP5 视频教程(二十四讲):模型输出     08:50
P2625.ThinkPhP5 视频教程(二十五讲):视图和模板-一      22:40
P2726.ThinkPhP5 视频教程(二十六讲):视图和模板-二      22:39
P2827.ThinkPhP5 视频教程(二十七讲):调试和日志        24:13
P2928.ThinkPhP5 视频教程(二十八讲):API调试        17:25
P3029.ThinkPhP5 视频教程(二十九讲):扩展       27:22
P3130.ThinkPhP5 视频教程(三十讲):浅析session、cookie机制        21:14
P3231.ThinkPhP5 视频教程(三十一讲):session的使用       23:11
P3332.ThinkPhP5 视频教程(三十二讲):cookie的使用        12:40
P3433.ThinkPhP5 视频教程(三十三讲):验证码      19:33
P3534.ThinkPhP5 视频教程(三十四讲):文件上传     25:13
P3635.ThinkPhP5 视频教程(三十五讲):图像处理     22:48
P3736.ThinkPhP5 视频教程(三十六讲):版本3.2和5的差别_Output        12:14
P3837.ThinkPhP5 视频教程(三十七讲):学习心得与总结      15:33

入门与安装部分

  1. 讲了安装配置
  2. 模块控制器介绍
  3. request处理请求类
  4. apache伪静态文件
  5. 数据库查询
  6. 模板解释机制

URL和路由

  1. 讲了参数绑定
  2. url大小写的注意
  3. 当不支持pathinfo怎么处理
  4. apache伪静态 或nginx隐藏index.php
  5. 定义路由规则 复杂路由
  6. url参数分隔符
  7. 生成URL地址
  8. 路径访问原理

请求和响应

SQL追踪器

介绍了作者自己写的一个SQL辅助工具,可以快速查看SQL执行log

数据库

基本操作、数据库-事务、链式操作

  1. 数据库配置
  2. query execute 原生态 sql 语句 增删改查
  3. 参数绑定 命名 占位符绑定
  4. 多个数据库切换查询操作
  5. 查询构造器
  6. DB链式操作
  7. 事务支持

查询语言

  1. 查询表达式
  2. 批量查询
  3. 快捷查询
  4. 视图查询
  5. 使用Query对象
  6. 获取数值
  7. 获取列数据
  8. 聚合查询
  9. 字符串查询
  10. 日期查询
  11. 分块查询

模型和关联

读取器与修改器

转换与自动完成

查询范围:

scope + 范围名称

全局查询范围 base()

输入和验证

关联

模型输出

问题小结

模型关联条件查询

如果要根据关联表的查询条件查询当前模型的数据,可以使用hasWhere方法,文档中举例:

$user = User::hasWhere('profile',['email'=>'thinkphp@qq.com'])->find();
echo $user->name;

在实际列表查询中,使用时写了:

list($where, $sort, $order, $offset, $limit) = $this->buildparams();

$list = $this->model
    ->where($where)
    ->with(["product"])->hasWhere("product", ["enterprise_id" => $this->enterprise_id])
    ->order($sort, $order)
    ->paginate($limit);

$total = $list->total();
$rows = $list->items();

$result = array("total" => $total, "rows" => $rows);

但报错了:

[0] Exception in Query.php line 103
method not exist:think\db\Query->hasWhere

说在 think\db\Query 中 不存在 hasWhere 方法,搜索查询解决方案的写法:

list($where, $sort, $order, $offset, $limit) = $this->buildparams();

$list = $this->model->hasWhere("product", ["enterprise_id" => $this->enterprise_id])
    ->where($where)
    ->with(["product"])
    ->order($sort, $order)
    ->paginate($limit);

$total = $list->total();
$rows = $list->items();

$result = array("total" => $total, "rows" => $rows);

原因是 hasWherethink\Model 中的方法:

<?php
namespace think;

use BadMethodCallException;
use InvalidArgumentException;
use think\db\Query;
use think\exception\ValidateException;
use think\model\Collection as ModelCollection;
use think\model\Relation;
use think\model\relation\BelongsTo;
use think\model\relation\BelongsToMany;
use think\model\relation\HasMany;
use think\model\relation\HasManyThrough;
use think\model\relation\HasOne;
use think\model\relation\MorphMany;
use think\model\relation\MorphOne;
use think\model\relation\MorphTo;

abstract class Model implements \JsonSerializable, \ArrayAccess
{
    /*...省略若干...*/
    
    /**
     * 根据关联条件查询当前模型
     * @access public
     * @param  string $relation 关联方法名
     * @param  mixed  $where    查询条件(数组或者闭包)
     * @param  mixed  $fields   字段
     * @return Relation|Query
     */
    public static function hasWhere($relation, $where = [], $fields = null)
    {
        return (new static())->$relation()->hasWhere($where, $fields);
    }
  
    /*...省略若干...*/
    
    public function __call($method, $args)
    {
        $query = $this->db(true, false);
        if (method_exists($this, 'scope' . $method)) {
            // 动态调用命名范围
            $method = 'scope' . $method;
            array_unshift($args, $query);
            call_user_func_array([$this, $method], $args);
            return $this;
        } else {
            return call_user_func_array([$query, $method], $args);
        }
    }

    public static function __callStatic($method, $args)
    {
        $model = new static();
        $query = $model->db();
        if (method_exists($model, 'scope' . $method)) {
            // 动态调用命名范围
            $method = 'scope' . $method;
            array_unshift($args, $query);

            call_user_func_array([$model, $method], $args);
            return $query;
        } else {
            return call_user_func_array([$query, $method], $args);
        }
    }
    
    /*...省略若干...*/
    
}

think\Model 是 模型类的公共父类。

where order with 等是 think\db\Query 中的方法,返回的也是 think\db\Query 对象,所以不存在 hasWhere 方法:

<?php
namespace think\db;

use PDO;
use think\App;
use think\Cache;
use think\Collection;
use think\Config;
use think\Db;
use think\db\exception\BindParamException;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use think\exception\PDOException;
use think\Loader;
use think\Model;
use think\model\Relation;
use think\model\relation\OneToOne;
use think\Paginator;

class Query
{
     /*...省略若干...*/
     
    /**
     * 指定AND查询条件
     * @access public
     * @param mixed $field     查询字段
     * @param mixed $op        查询表达式
     * @param mixed $condition 查询条件
     * @return $this
     */
    public function where($field, $op = null, $condition = null)
    {
        $param = func_get_args();
        array_shift($param);
        $this->parseWhereExp('AND', $field, $op, $condition, $param);
        return $this;
    }
    
     /*...省略若干...*/
    
    /**
     * 指定排序 order('id','desc') 或者 order(['id'=>'desc','create_time'=>'desc'])
     * @access public
     * @param string|array $field 排序字段
     * @param string       $order 排序
     * @return $this
     */
    public function order($field, $order = null)
    {
        if (empty($field)) {
            return $this;
        } elseif ($field instanceof Expression) {
            $this->options['order'][] = $field;
            return $this;
        }

        if (is_string($field)) {
            if (!empty($this->options['via'])) {
                $field = $this->options['via'] . '.' . $field;
            }
            if (strpos($field, ',')) {
                $field = array_map('trim', explode(',', $field));
            } else {
                $field = empty($order) ? $field : [$field => $order];
            }
        } elseif (!empty($this->options['via'])) {
            foreach ($field as $key => $val) {
                if (is_numeric($key)) {
                    $field[$key] = $this->options['via'] . '.' . $val;
                } else {
                    $field[$this->options['via'] . '.' . $key] = $val;
                    unset($field[$key]);
                }
            }
        }
        if (!isset($this->options['order'])) {
            $this->options['order'] = [];
        }
        if (is_array($field)) {
            $this->options['order'] = array_merge($this->options['order'], $field);
        } else {
            $this->options['order'][] = $field;
        }

        return $this;
    }
    
     /*...省略若干...*/
     
    /**
     * 设置关联查询JOIN预查询
     * @access public
     * @param string|array $with 关联方法名称
     * @return $this
     */
    public function with($with)
    {
        if (empty($with)) {
            return $this;
        }

        if (is_string($with)) {
            $with = explode(',', $with);
        }

        $first = true;

        /** @var Model $class */
        $class = $this->model;
        foreach ($with as $key => $relation) {
            $subRelation = '';
            $closure     = false;
            if ($relation instanceof \Closure) {
                // 支持闭包查询过滤关联条件
                $closure    = $relation;
                $relation   = $key;
                $with[$key] = $key;
            } elseif (is_array($relation)) {
                $subRelation = $relation;
                $relation    = $key;
            } elseif (is_string($relation) && strpos($relation, '.')) {
                $with[$key]                   = $relation;
                list($relation, $subRelation) = explode('.', $relation, 2);
            }

            /** @var Relation $model */
            $relation = Loader::parseName($relation, 1, false);
            $model    = $class->$relation();
            if ($model instanceof OneToOne && 0 == $model->getEagerlyType()) {
                $model->eagerly($this, $relation, $subRelation, $closure, $first);
                $first = false;
            } elseif ($closure) {
                $with[$key] = $closure;
            }
        }
        $this->via();
        if (isset($this->options['with'])) {
            $this->options['with'] = array_merge($this->options['with'], $with);
        } else {
            $this->options['with'] = $with;
        }
        return $this;
    }
     
     /*...省略若干...*/
    
}

看一个实战的例子:

$filter = json_decode($this->request->get('filter'), true);
$op = json_decode($this->request->get('op'), true);

if (isset($filter['address.contact_name'])) {
    $address_contact_name = $filter['address.contact_name'];
    unset($filter['address.contact_name']);
}

$this->request->get(['filter' => json_encode($filter)]);
$this->request->get(['op' => json_encode($op)]);

list($where, $sort, $order, $offset, $limit) = $this->buildparams();

$model = $this->model;

$hasWhere = [];
if (!empty($address_contact_name)) {
    $hasWhere['contact_name']= ['LIKE', '%'. $address_contact_name .'%'];
}
if (!empty($hasWhere)) {
    $model = $model->hasWhere('address', $hasWhere);
}

$model = $model->with(["address"])
    ->where($where)
    ->order($sort, $order)
    ->paginate($limit);

$total = $model->total();
$rows = $model->items();






参考资料

ThinkPHP5.0完全开发手册 官方手册 https://www.kancloud.cn/manual/thinkphp5

ThinkPHP5.1完全开发手册 官方手册 https://www.kancloud.cn/manual/thinkphp5_1

ThinkPHP6.0完全开发手册 官方手册 https://www.kancloud.cn/manual/thinkphp6_0

ThinkPHP 官方入门系列教程 https://www.kancloud.cn/special/thinkphp5_quickstart

ThinkPhP5基础视频教程 https://www.bilibili.com/video/av25629718/

ThinkPHP5视频教程系列 https://www.kancloud.cn/special/thinkphp5_video

TPshop视频 http://www.tp-shop.cn/index.php/doc/indexbbc/video


返回