tp5 的灵活之处

1.路由

tp5 的路由配置在 application 文件夹下的 route.php 文件中。
有两种写法,详见官方文档。
默认的写法是配置写法,有点繁琐,如下:

<?php

return [
    '__pattern__' => [
        'name' => '\w+',
    ],
    '[hello]'     => [
        ':id'   => ['index/hello', ['method' => 'get'], ['id' => '\d+']],
        ':name' => ['index/hello', ['method' => 'post']],
    ],

];

这里我们使用一下动态注册

<?php

use think\Route;

Route::rule("hello","sample/Test/hello");

非常简单。

但是有一个需要注意的问题,一旦路由生效,PATH_INFO 的访问模式就会失效,即访问z.cn/sample/test/hello是无效的了。

现在我们来详细的看一下 Route::rule 的完整写法:

Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)')

我们来看一下请求类型,有以下几种:
GET, POST, DELETE, PUT, * ( *表示为任意的请求类型)
当 Route::rule 缺省该参数的时候,默认是 * 类型。(可以通过 PostMan 进行验证)
这样当然不好,因为每一种 http 请求都是有特定意义的,使用 * 号会导致语义不明确。
所以我们可以修改一下:

Route::rule("hello","sample/Test/hello","GET");

对于某些时候,我们可能希望既支持 GET 也支持 POST。写法:

Route::rule("hello","sample/Test/hello","GET|POST");

路由参数可以查看官方文档

变量规则今后有好的示例的时候再来讲解。//TODO

补充:由于我们平时开发常用的就是前三个参数,即路由表达式,路由地址和请求类型,所以 tp5 给我们提供了简写的方式:

Route::get("hello","sample/test/hello");
Route::post();
Route::any();  // any 即对应http请求中的 *

2.获取 http 参数

先补充一下基础知识:
路由里get 传参的两种方式
1.在 url 路径中传参:
/:自定义名字

Route::get("hello/:id","sample/Test/hello");

2.在 url 路径中加问号
?参数名=参数值

我们在路由中传递参数的目的是在控制器的操作方法里成功获取这些参数
在操作方法中获取 http 参数的方式有三种。

第一种:

通过操作方法的参数获取:

public function hello($id,$name)
    {
        return "hello $id, $name";
    }

然后我们在浏览器或 Postman 中输入 url:
z.cn/hello/123?name=frank
就可看到输出:

浏览器展示结果

下面我们看一下 post 请求参数的获取
我们先改一下路由:

Route::post("hello/:id","sample/test/hello");

并且在操作方法中新加一个参数:$age

public function hello($id,$name,$age)
    {
        return "hello $id, $name, $age";
    }

然后打开 postman:
选择 POST 方式。
在 Body 中通过键值对进行传值:(默认 form-data 即可)
KEY 输入 age,VALUE 输入相应值。
就能看到相应输出的结果。


Body_KEY-VALUE

第二种:

通过 Request 类。
Request::instanse() 拿到 Request 的实例。
->param 调用实例的 param() 方法。

use think\Request;

class Test
{
    public function hello()
    {
        $id = Request::instance()->param("id");
        $name = Request::instance()->param("name");
        $age = Request::instance()->param("age");   

        return "hello $id, $name, $age";
    }
}

param方法不管请求是从 get 还是 post 还是 delete 等里来的,它是不区分这些 http 类型的。
如果我们不想一次一次的单独获取,想一次性获取所有:
可以在 ->param() 里面不写参数。

use think\Request;

class Test
{
    public function hello()
    {
        $all = Request::instance()->param();
        var_dump($all);
    }
}

下面我们看一下获取的内容的类型,发现是一个数组。


Postman Preview 下的展示结果

我们现在知道了 ->param() 是获取所有的,那么我们要单独获取 ? 后面的参数该如何实现呢?实际上,tp5 不仅提供了这一个方法,例如:
我们修改一下

$all = Request::instance()->get();

发现打印的就只有 name 了:


Request::instance()->get()

有的人可能会有疑问,为什么只打印了 query 里的参数 name ,而没有打印 url 路径里的参数 id 呢?
tp5 提供了另一个方法:route来解决这个问题:

$all = Request::instance()->route();
Request::instance()->route()

同理,获取 body 里的 POST 请求的内容:

$all = Request::instance()->post();

测试结果:


Request::instance()->post()

上面我们只介绍了 param、get、route、post,tp5 文档里还有很多,大家有需要的时候再查即可。

第三种:

助手函数:
有的时候我们每次都要写 Request::instance()-> 太过麻烦,tp5 定义了一个叫做助手函数的东西,具体写法如下:

class Test
{
    public function hello()
    {
        $all = input("param.");
        $id = input("route.id");
        $name = input("get.name");
        $age = input("post.age");
    }
}

助手函数的使用很简单,但要注意获取 $all 的时候参数是"param."

【补充】依赖注入的小实例:

use think\Request;

class Test
{
   public function hello(Request $request)
   {
       $all = $request->param();

       var_dump($all);
   }
}

可以看到,我们在 hello 方法的参数里面写了 Request 作为参数,那么这个 $request 是谁来传入他的呢?
正是我们在使用 Request 实例的时候我们不关心是谁实例化的这个 Request 对象,这一点恰恰就是依赖注入的优势。不需要知道这个 $request 是谁传入的或是谁实例化的,只需要参数里声明,就可以在下面直接使用 $request

3.数据库操作

在配置完 database.php 中的数据库名、用户名、密码和端口之后,就可以进行操作数据库了。
tp5 中操作数据库的方式有三种:使用原生 sql 语句操作数据库、使用查询构造器操作数据库、使用模型和关联模型操作数据库(我们重点讨论)。
原生 sql

$result =Db::query('select * from banner where banner_id = ?',[$id]);

原生 sql 查询非常简单,$result 就是查询出来的数据。
但是原生的查询不能满足数据库环境变化的情况,缺点很明显。所以需要用到 tp5 的数据库访问层来进行跨数据库的操作。

查询构造器

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

这样返回的 result 是一个 query 对象,要想得到查询结果可以在后面使用 find 或 select 方法。
find 只能返回一条记录

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

select 能返回所有记录

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

让我们再来分析一下这个的结构:
查询构造器的辅助方法(也叫链式方法):
Db::table('banner')->where('banner_id','=','$id')
允许多层链式方法,都返回 query 对象,不会进行实际的查询操作。根据配置文件中的数据库的值(例如 'mysql' )对 connection 属性和 builder 属性进行相应实例化(例如 '[Mysql]')。不同的链式方法的顺序对最终结果没有影响,相同的链式方法最终的查询结果可能有区别。
后面的执行方法,进行数据库操作,并清空前面的链式方法的状态。例如:
增:->insert()
删:->delete()
改:->update()
查:->find() ->select()

where 链式方法的参数除了用表达式的写法,还可以用数组法和闭包。由于官方文档不推荐使用安全性不高且不够灵活的数组法,我们现在看一下闭包:

$result = Db::table('banner')
          ->where( function ($query) use($id){
                     $query -> where('banner_id','=','$id');})
          ->select();

闭包的写法就是在 where 的参数中传入一个匿名函数,匿名函数拿到外界的 $id 需要通过 use ($id) 来引入。
还有如果我们想看到中间 tp5 生成的 sql 语句,可以通过 fetchSql() 链式方法来实现:

$result = Db::table('banner')
          ->fetchSql()
          ->where( function ($query) use($id){
                     $query -> where('banner_id','=','$id');})
          ->select();

这样即使有 select 也不会执行,而是因为有 fetchSql() ,会返回相应的 sql 语句。
但我们有的时候不会每一条语句中都加一个 fetchSql() 方法,这时我们可以通过 tp5 生成的 sql 日志来观察。
我们可以在 index.php 中初始化日志(config.php 中的日志一般都是处于 test 的非开启模式的)

\think\Log::init([
  'type'  =>  'File',
  'path' => LOG_PATH,
  'level' => ['sql']
])

建议生产模式下关闭该日志,以节约性能。

ORM 和模型
对于中小型的项目,我们一般采取 ORM( Object Relation Mapping ) 的方式操作数据库。
在传统的操作中,我们一般把每次对数据库的操作想象成是返回一个二维或一维的结构。而在 ORM 中,我们把每次操作想象成是一个对象。我们通过对象拿到每一次的操作结果,此时表与表之间的关系也由键之间的关系变成了对象与对象之间的关系。
ORM 不是一种语言,也不是一种框架,而是一种思想。很多语言都有实现这个思想的框架。
通过继承 tp5 的内置 Model 类,我们将我们的业务层变成一个对象模型(事实上,不论是否继承,我们都应该把它想象成对象模型),一个模型相当于一个业务,里面可以包含多个数据库操作。这样,在控制器中我们可以直接调用被继承的 Model 类的 get 方法来获得结果。

$banner = BannerModel::get($id);
return $banner; 

由于返回的 $banner 是一个对象,所以输出时不需要用 json() 包着。如果输出的 json 没有相应格式,可以在 config.php 将 default_return_type 改为 'json'。

下面我们总结一下 tp5 中的模型:

  • 继承 Model 类
  • 在简单的业务中,模型与表一一对应,复杂的业务中,一个模型关联多张表。
  • 默认情况下,模型的名字与数据库表名存在映射关系,自动对应,可以通过写入 protected $table = 'banner_item'进行指定。
  • 模型类相当于表,get 方法实例化得到的对象相当于记录

利用命令行快速创建模型:
在项目文件夹下,例如 zerg

D:\xampp\htdocs\zerg>php think make:model api/BannerItem

自动写入了:

<?php

namespace app\api\model;

use think\Model;

class BannerItem extends Model
{
    //
}

(如果遇到 php 不是内部命令,需要配置环境变量,然后重启 PhpStorm,再次运行)

最后,不要弄混了get、all、find 和 select 这几个方法。
Db 查询用到 find 和 select,但是不能用 get 和 all。
而模型查询由于做了兼容,以上四种都可以。

对于关联模型我们新写一篇文章来探讨:
tp5 关联模型

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,511评论 18 139
  • 理工寝室商店-微信小程序 疑问小结 当时在XAMMP下mysql目录下的bin下 php -v 不起作用.到ph...
    这个超人不会飞阿阅读 1,688评论 1 1
  • 安装配置 官网下载TP5完整版(初学者学习用的)解压到本地的开发环境phpstudy中,默认的入口文件是publi...
    我要挖0day阅读 42,109评论 3 56
  • # 一、框架概述 # 课程概述 1. laravel 4天(之前TP框架还是很大的区别)(国外框架) 2. 在线教...
    关进一阅读 357评论 0 0
  • 不忘初心,方得始终。 人处在不同的生长环境,都会有自己对“善良”和“好”的不同标准,并且都喜欢从自己的标准去判断别...
    跳舞的小雪人阅读 110评论 0 0