tp5.1学习笔记1
[TOC]
安装
composer create-project topthink/think tp5
配置文件:
默认配置都在app.php配置文件,并且配置参数区分大小写
两种层级的配置:
应用配置目录 config
模块配置目录 application/module/config
以上两种配置,只能有一种生效。如果模块module下面有config配置,那么此模块,应用此配置。全局配置失效。
快速入门
控制器
默认继承controller。访问:http://localhost/tp/public/index.php/index/index/index 其中,index.php后面,模→控→操
命名空间:app\index\controller 除了app是缩写,其他都代表真实的路径。
<?php namespace app\index\controller; use \think\Controller; class Index extends Controller { public function index() { return '<h1>Hello world</h1>'; } public function hello($name = 'ThinkPHP5') { return 'hello,' . $name; } public function test(){ echo \json_encode(['age'=>123,'name'=>'']); } public function test1(){ $data = ['age'=>123,'name'=>'wangduoduo']; return xml($data);//或json } }提交的参数:
$this->request 对象。 $this->request->param('name') $this->request->get('name') //进行了区分。 $data = $this->request->param();//返回所有的提交数据返回数据:
return json($data); 注意: 如果是使用了助手函数,请return。如果echo,则会报错。因为框架,会根据控制器的返回,进行处理。
常见的助手函数,json/xml等。
配置连数据库等
数据库的配置 application/config/database.php 简单的更新如下的几个配置即可。
'type' => 'mysql', // 服务器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'test', // 用户名 'username' => 'root', // 密码 'password' => 'root',
测试表:
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`sex` int(1) DEFAULT NULL,
`age` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
测试查询数据
use \think\Db; //导入类
//返回查询数据
public function index(){
$data = Db::connect()
->table('user')
->select();
return json($data);
}
备注:查询find 跟select的区别,find即findOne,而select 是取出所有匹配的结果集。官方文档如此备注:默认情况下,find和select方法返回的都是数组,区别在于后者是二维数组。
添加数据:
public function add(){
$data = $this->request->param();
// Db::name('user')->insert($data); //方式一
Db::name('user')->data($data)->insert(); //方式二
}
更新数据:
public function update(){
Db::name('user')
->where('id', 1)
->update(['name' => '猪大强']);
}
删除数据:
// 根据主键删除
Db::table('think_user')->delete(1);
Db::table('think_user')->delete([1,2,3]);
// 条件删除
Db::table('think_user')->where('id',1)->delete();
Db::table('think_user')->where('id','<',10)->delete();
如上,基本完成了增删改查的功能。
数据验证
每个字段增加若干个验证规则,以|分隔。如果有详细的规则,以冒号:逗号,来描述。验证为假,并不会阻止表单的的insert行为,而是自己需要手动的根据判断结果来控制。
<?php /** * 2019-08-19 17:06:38 */ namespace app\index\validate; use think\Validate; class User extends Validate{ protected $rule = [ 'name'=>'require|max:25', 'age'=>'number|between:1,150', 'sex'=>'number|between:1,2' ]; protected $message = [ 'name.require' =>'姓名是必填字段', 'name.max' =>'姓名最多不能超过25个字', 'age.number' =>'年龄必须是数字', 'age.between' =>'年龄只能在1-120之间', 'sex.number' =>'性别填写有误', 'sex.between' =>'性别填写有误' ]; }也可以使用数组来定义。
控制器内,进行验证。
//数据验证,可选。 推荐使用这种方式。 $validate = new \app\index\validate\User; if (!$validate->batch()->check($data)) { dump($validate->getError()); exit; }
小结
按照完整的业务流程,应该包含提供数据展示,数据的提交表单,用户提交表单后,前端要对数据进行验证,后端过滤用户数据,后端进行数据验证(数据格式的验证、业务逻辑验证),数据入库。数据处库时,也要验证。上面的例子将所有的逻辑,都写在的控制器内。后期应该更改。
接下来,应该学习:
路由功能、数据库高级查询功能、
配置文件
应用配置
config/app.php配置文件直接返回一个数组。估计在调用的时候,$cfg = include ‘app.php’类似的调用方式。
app_debug
很重要,开启调试模式。能在调试的时候,看到直观的错误提示。
app_trace
开启html模式下,返回的性能跟踪工具。
config/database.php数据库配置。
模块配置
例如为index模块增加单独的数据库配置文件。拷贝config/database.php→
application\index\config\database.php
然后,在上面的文件中设置独立的数据库连接信息。
备注:config是跟application同级目录。
钩子和行为
参照架构→总览的例子
类似于AOP编程中的“切面”的概念,给某一个钩子绑定相关行为就成了一种类AOP编程的思想。
这里面有两个概念,一个是钩子,另外一个是行为。
钩子,类似于Extjs中的fireEvent,表示要触发的地方。
行为,类似于Extjs中的on,表示要执行回调的地方。
总结:行为的类,要实现run方法。关于顺序,肯定是先on,然后再fireEvent。
官网提了示例的代码,但是没有告诉这些代码放在哪。behavior类如何编写等。经过试探,总结如下:
先定义add的监听的方法,然后才能去监听,listen。
新建目录,application\index\behavior新建一个类,该类必须要有一个run方法。方法:public function run
相关代码:
在控制器类,添加(演示,都放到一起了。):
\think\facade\Hook::add('app_init','\app\index\behavior\Applisten');
\think\facade\Hook::listen('app_init');
定义具体的类。
<?php
/**
* 2019-08-20 11:30:11
*/
namespace app\index\behavior;
class Applisten {
public function run(){
echo __FILE__." app_init ";
}
}
中间件
事件
主要是数据库增删改查的事件。又分为模型事件、数据库操作事件。
think\Model::beforeUpdate($callback, $override = false)
但是,这个事件,比以前的tp3.2的复杂了很多。之前的版本,实际上就是,在相关事件中,调用模型的方法而已。
数据库操作事件
public function update(){
Db::event('after_update', function($query){
var_dump($query); //think\db\Query对象
return $query; //不return,应该也没有问题。
});
Db::name('user')
->where('id', 1)
->update(['name' => '强大强12']);
}
说明:上面的after_update是在update之后才会触发,如果没有更改,则不会触发。如果update执行多个,估计都会执行回调?
不太明白,为啥before_update没有触发。难道,真的是框架上说明的那样(架构→架构总览),数据库查询支持的只有before_select。before_find、after_insert、after_update、after_delete。
模型事件
这个很难理解。
public function update(){
$user = new \app\index\model\User;
$user::beforeUpdate(function($query){
echo '1234314';
});
$user->where('id',1)->update(['name' => '强大强11']);
}
结果还抛出异常。
method not exist:app\index\model\User->beforeUpdate
架构
Facade
说的直白一点,Facade功能可以让类无需实例化而直接进行静态方式调用。
框架内部默认已经包含了一些实现。参见thinkphp\library\think。 仿照这些,可以写自己的demo。通过增加定义一个类,来减少调用时,像使用静态方法那样直接调用。
简单的demo
//在入口控制器内增加如下:
\app\index\facade\User::sayhello();
增加类文件application\index\facade\User.php:
namespace app\index\facade;
class User extends \think\Facade{
protected static function getFacadeClass()
{
return 'app\index\model\User';
}
}
然后就能直接使用未经实例化的model对象的方法呢。
注意:
1、在进行类型约束的时候,要用原本的类来进行约束。
2、框架默认为一些类,提供了别名,即更简短的名称。
3、facada这种类,对编辑器不友好,代码自动提示有问题。增加_ide_helper.php文件(具体如何实现?我也不清楚)
入口
[ Apache ]
httpd.conf配置文件中加载了mod_rewrite.so模块AllowOverride None将None改为All把下面的内容保存为
.htaccess文件放到应用入口文件的同级目录下(Server API: Apache 2.0 Handler)
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
上面的重写机制好像是要求,必须放到文件的根目录中。没有放到根目录中,就提示,文件不存在。
错误提示如下:
No input file specified.
需要注意如下:
查看phpinfo() 打印的,如果是Server API: CGI/FastCGI,而phpstudy中正好是这种。
RewriteRule ^(.)$ index.php/$1 [QSA,PT,L]
必须改成
RewriteRule ^(.)$ index.php?/$1 [QSA,PT,L]
还可以改写成如下:
RewriteRule ^(.)$ index.php [L,E=PATH_INFO:$1] //推荐这种,在子目录下,也能使用
完整如下:
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
</IfModule>
另外,还可能有FPM/FastCGI这种形式。说明是nginx服务器。
换用之前项目中的方式,提示找不到tp模块。
RewriteEngine on
RewriteRule !\.(pdf|ps|js|ico|gif|jpg|png|bmp|css|JPG|xap|xml|xls|json|html|swf|cab|mp3|wav)$ index.php
试过了,想要放到子目录中,都不好使。
助手函数
命令行
大概也就几种。说白了,就是根据模板自动生成一些空白的代码模板。(也没有啥大用,完全可以用自己的模板生成工具。)好总比没有强。
总共也就下面的几种:
make:command
make:controller
make:model
make:middleware
make:validate
- 中间件
php think make:middleware Check
- 模型
//这个在common模块中生成
php think make Test
//这个制定了模块
php think make:model index/Test
- 控制器
php think make:controller index/Hello
- 验证器
php think make:validate index/Hello
框架源码
延迟绑定
第一次听到这个词,是因为看了Container的实现。new static。实在是不理解。就百度了。
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
总结:new static 跟new self 两者都是实例化自身,区别在于继承。如果没有继承,则两者返回的实例都是属于一个类;如果有继承,子类调用该方法,new self 仍然返回原类的实例,而 new static 返回实际子类的实例。这就是延迟静态绑定,static 的值,使用的是最后实际调用那个方法的类。