1、框架概述
1.什么是框架
框架就是一些代码类、方法(函数)、变量、常量的集合,这些代码是功能结构性的代码(并非业务代码)
业务代码其实就是具体的一些模块的增删改查逻辑代码。
使用框架开发项目,有便于代码重用、开发效率高、代码规范好、便于功能扩展等优点。
2.用框架和不用那个效率高?
项目小:原生快。
项目大:框架快(原因是项目太大,那么肯定不会是你单人开发,所以如果没有统一的规范的话,那么每个人的习惯和思维不太一样,比如文件乱放,代码这里丢一坨,哪里丢一坨,会导致很多问题,因为项目大,所以需要复用的地方肯定也比较多,那么此时框架就会提高效率)
3.常用的框架
- Zend Framework 框架,PHP官方框架。
- YII框架,又叫易框架
- Symfony 框架。
- Laravel框架,市场使用较多。
- Codelgniter框架,简称CI框架。
- ThinkPHP框架,简称TP框架,常用版本:3.2.3和 5.0.*版本。
Zend Framework :用的人真的不太多,比较重
YII:国内也还有一部分在用
Symfony:国内几乎没有,国外很多很多,封装思想很好
Laravel:国内用它的也非常多,我也经常用,相当优雅,用过的都说好。
Codelgniter:通常和ThinkPHP3.2作比较,封装的也不是很深,适合入门,还包含很多面向过程的思想,封装了很大一批的函数直接调用的,不是通过对象调用方法的,现在见到的一般就是一些老项目在用了,10-11年是很火的,因为很简单
ThinkPHP:目前好像是到tp6了,它经典的版本应该是3.2.3和5.0系列和5.1系列,到现在的tp6,如果你碰到一些15年左右的项目,很有可能就是tp3.2做的
这些框架大多都基于MVC设计思想和面向对象的
M:模型model,处理业务数据,与数据库做交互。
V:视图view,显示html页面,用户能够看到并与之交互的页面。
C:控制器controller,接收请求,调用模型处理数据,调用视图显示页面。
整个网站应用,分为模型、视图、控制器三大部分组成。
2、框架的下载
1.框架下载
http://www.thinkphp.cn/down/framework.html
#composer 地址
https://packagist.org/packages/topthink/think#v5.0.24
注意:php版本太高,会报错,各种报错,现在都php8了,建议用tp5.0系列的时候php版本也用php5.4及以上版本
2.配置虚拟主机
<VirtualHost *:80>
# 设置网站目录
DocumentRoot "F:\wamp\www\tpshop\public"
ServerName www.tpshop.com
# 错误日志
ErrorLog "F:\wamp\www\tpshop\logs\error.log"
# 成功日志
CustomLog "F:\wamp\www\tpshop\logs\access.log" combined
# 设置目录访问权限
<Directory "F:\wamp\www\tpshop\public">
# 指定目录启用特性
Options Indexes FollowSymLinks
# 是否允许使用.htaccess文件
AllowOverride All
# 访问目录权限 apache2.4
Require all granted
# 默认起始页面
DirectoryIndex index.php
</Directory>
</VirtualHost>
因为配置了错误日志,所以需要在项目根目录创建一个logs文件夹,否则无法启动
域名解析
成功访问
3、tp框架基础
1.目录结构
project 应用部署目录
├─application 应用目录(可设置)
│ ├─common 公共模块目录(可更改)
│ ├─index 模块目录(可更改)
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ ├─command.php 命令行工具配置文件
│ ├─common.php 应用公共(函数)文件
│ ├─config.php 应用(公共)配置文件
│ ├─database.php 数据库配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─route.php 路由配置文件
├─extend 扩展类库目录(可定义)
├─public WEB 部署目录(对外访问目录)
│ ├─static 静态资源存放目录(css,js,image)
│ ├─index.php 应用入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于 apache 的重写
├─runtime 应用的运行时目录(可写,可设置)
├─vendor 第三方类库目录(Composer)
├─thinkphp 框架系统目录
│ ├─lang 语言包目录
│ ├─library 框架核心类库目录
│ │ ├─think Think 类库包目录
│ │ └─traits 系统 Traits 目录
│ ├─tpl 系统模板目录
│ ├─.htaccess 用于 apache 的重写
│ ├─.travis.yml CI 定义文件
│ ├─base.php 基础定义文件
│ ├─composer.json composer 定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 惯例配置文件
│ ├─helper.php 助手函数文件(可选)
│ ├─LICENSE.txt 授权说明文件
│ ├─phpunit.xml 单元测试配置文件
│ ├─README.md README 文件
│ └─start.php 框架引导文件
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
extend:拓展目录,可以被自动加载
runtime:访问页面的时候会自动生成出来,很多时候改代码不生效,可能就是这个缓存问题,可以尝试删除该目录,重新访问,其它的记本是每个后面都说的很清楚
最重要的一点就是记住:入口文件在哪里
注意:下载下来的和这个目录结构是有出入的,比如刚下载的框架
还有一个注意的点是:每个模块下都有自己的配置文件和函数文件
注意:这个think文件用来用指令来快速创建目录结构的
2.配置文件
2.1配置文件的层级
框架主配置文件(惯例配置文件) thinkphp/convention.php
应用公共配置文件 application/config.php, application/database.php 对整个应用生效
模块配置文件 application/模块目录/config.php 对当前模块生效
注意:一般不要去改框架主配置文件,改应用公共配置文件就行了,原因是要升级的时候,直接替换掉thinkphp这个核心目录。
2.1配置文件的其它说明
配置文件格式 return array( 键值对 );
加载顺序: 框架主配置文件 》 应用公共配置文件 》 模块配置文件
配置文件生效顺序: 后加载的生效(后加载的配置项会覆盖之前配置项)
3.函数文件
框架助手函数文件 thinkphp/helper.php
应用公共函数文件 application/common.php
模块函数文件 application/模块目录/common.php
我们知道函数名称重复会报错,自己定义函数的时候我们可以借鉴thinkphp/helper.php里面的写法,定义之前先进行判断
注意:一般不建议直接修改thinkphp/helper.php
4.开发规范
ThinkPHP5遵循PSR-2
命名规范和PSR-4
自动加载规范,同时弄了一些自己的一些规范
https://www.kancloud.cn/manual/thinkphp5/118007
拓展知识:PSR代码规范
https://www.kancloud.cn/thinkphp/php-fig-psr/3139
5.请求的生命周期
框架的生命周期,也就是请求的执行流程
请求开始-》入口文件public/index.php->底层流程start.php->注册自动加载-》注册错误和异常机制-》应用初始化-》URL访问检测-》路由检测-》请求分发-》控制器方法-》
控制器-》模型-》-》返回数据到控制器
控制器-》视图(响应输出)-》结束
4、控制器
1.控制器的后缀
打开配置文件application/config.php,有如下配置
'controller_suffix' => false,
修改控制器后缀的话
'controller_suffix' => 'Controller',
表示控制器以Controller为后缀。例如Index控制器,文件名为IndexController.php
2.控制器的定义
定义位置及命名规则
定义位置:application/模块目录/controller/目录下
命名规则:控制器名称(首字母大写) + (控制器后缀,默认没有) + .php
默认:Index控制器 Index.php
我们给它改改,再访问看看
示例:我们模仿默认的Index创建一个用户控制器User.php
<?php
//1.引入命名空间
namespace app\index\controller;
//2.引入 基类控制器
use think\Controller;
//定义当前的控制器类,并继承控制器基类(可选)
class User extends Controller
{
public function index()
{
return "我是这个Index模型下的/User控制器下的/index方法";
}
}
3.框架中的命名空空间
命名空间本身是PHP就有的,用来防止命名冲突问题的。
TP框架中的命名空间,通常和目录挂钩。
原因:TP中的自动加载机制,会将类的命名空间作为加载路径的一部分。
如果自己手写过mvc框架,那么这点肯定是可以理解的
TP中命名空间使用:
①声明命名空间 使用namespace关键字
②引入指定的类 使用use关键字 命名空间\类名称
③完全限定式访问 在使用类时,\完整命名空间\类名称(继承和实例化)
如果一个类没有命名空间,使用 \类名
4.url访问
(见手册–架构–URL访问)
ThinkPHP5.0框架中,默认使用PATH_INFO方式的url进行访问。
格式
http://域名/入口文件/模块名/控制器名称/操作方法名称/参数名/参数值
例子
http://www.tpshop.com/index.php/Index/Test/index/page/10
隐藏入口文件写法
http://域名/模块名/控制器名称/操作方法名称/参数名/参数值
例子:
http://www.tpshop.com/index/user/index
需要对apache进行设置(手册–架构–URL访问、手册–部署–URL重写)
步骤总结:
httpd.conf
配置文件中加载了mod_rewrite.so
模块
虚拟主机配置中AllowOverride None 将None改为 All
在应用入口文件同级目录添加.htaccess文件,内容如下
<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>
这个要注意:一般原生的php环境比如amp一个一个分别安装的一般是没问题的,但是如果是phpstudy的话,可能会有问题(不推荐大家用集成环境)
比如不携带入口文件访问会出现 No input file specified
需要修改一下.htaccess
文件
<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>
大白话,就是说/index/user/index
这一部分不是一个文件不是一个目录,它就会去找index.php文件,然后通过一个?
把这一串,传递给框架中的入口文件进行处理(那个$1
就是反向引用前面那一大串路径),框架就会解析这个路径,把第一个斜杠后面的当作模块,第二个当作控制器,第三个当作方法名称。
使用Apapche的重写机制隐藏入口文件后,如果在整个url后面加上.html后缀, 让整个url看起来像是访问的静态页面。这叫做“伪静态”。
5.调试模式
见手册–错误与调试–调试模式
然后我地址乱输入一个
5、模块创建
1.创建前台模块和后台模块
一个典型的应用是由多个模块组成的(通常有前台网站模块和后台管理系统模块),这些模块通常都是应用目录下面的一个子目录,每个模块都有自己独立的配置文件、公共文件和类库文件。
我们给项目创建home(前台)和admin(后台)两个模块:
编写控制器和方法
2.配置默认的访问模块
打开配置文件application/config.php
,有如下配置
'default_module' => 'index',
表示默认访问模块为index模块
可以更改默认模块为home模块
'default_module' => 'home',
此时直接输入域名,就会发现,直接访问到home模块了
注意:可以省略的规则只能是从后往前一级一级的省略
6、命令行创建模块目录及文件
这里是用phpstorme演示,这里就把刚才手动创建的模块删除,方便演示
1.命令行创建模块
php think build --module 模块名
2.命令行创建控制器
php think make:controller 模块名/控制器名
php think make:controller 模块名/控制器名 --plain
加上 --plain 参数 表示创建没有方法的空控制器类。否则控制器类中会自带一些方法
3.命令行创建模型
php think make:model 模块名/模型名
注意:模型名首字母大写。
4.其它命令
有兴趣的可以自己看看
7、Request请求类
1.获取输入变量
(见手册–请求–输入变量)
比如这个地址:
http://www.tpshop.com/home/index/index/id/10/name/jack?age=20&sex=man
该如何接收?原生php接收是用这些方式
使用框架则不要用原生的接收了,框架封装过的做过一些特殊的处理功能也比较强大
有两种方式
第一种直接使用助手函数input
助手函数来接收参数
input('name');//jack
第二种可以使用\think\Request
类
$request = \think\Request::instance();
或者使用助手函数得到request
实例
$request = request();
例子:
Request::instance()->param('name');//jack
再或者如果继承了控制器基类可以这样使用
$id = $this->request->param('id');
dump($id);
它能够调用的方法有如下
param:能自动识别GET、POST或者PUT请求的一种变量获取方式,是系统推荐的获取请求参数的方法
这里主要说明一下get和route的区别
route只能取到这部分的参数
get方法只能取到如下部分的参数,这就是区别
代码演示
$request = request();
$get = $request->get();
$param = $request->param();
$route = $request->route();
dump($get);
dump($param);
dump($route);
参数的解释
变量类型方法('变量名/变量修饰符','默认值','过滤方法')
变量修饰符
例如
input('get.id/d');
input('post.name/s');
input('post.ids/a');
Request::instance()->get('id/d');
什么时候这个默认/s
会出问题呢?
比如你表单里面要接收一个爱好,name属性值比如我设置为如下
这个时候如果被转换为字符串就会报错,所以该参数需要接收为数组
Request::instance()->get('hobby/a');
第二个参数 默认值
比如没有传递,我接收一个默认值
Request::instance()->get('age',20);
第三个参数 过滤方法
第三个参数我们直接写上方法名称就行
Request::instance()->get('age',20,'trim');
回头我们看看param
方法
// 获取当前请求的name变量
Request::instance()->param('name');
// 获取当前请求的所有变量(经过过滤)
Request::instance()->param();
// 获取当前请求的所有变量(原始数据)
Request::instance()->param(false);
// 获取当前请求的所有变量(包含上传文件)
Request::instance()->param(true);
input()
与之等效的操作是
input('param.name');
input('param.');
或者
input('name');
input('');
param
默认不传递参数是获取所有的经过过滤
的数据
这个默认过滤的方法在配置文件中进行配置,
默认框架是空的,我们可以自己传递一个trim方法
实际操作
2.判断变量是否传递
Request::instance()->has('id','get');
Request::instance()->has('name','post');
input('?get.id');
input('?post.name');
3.参数绑定
手册–请求–参数绑定
3.1按照参数名称绑定
我们通过命令行创建控制器 后面不加参数 --plain时默认带有几个方法,我们发现它有的方法是需要参数的
这就是参数绑定,否则,我们想得到这个id就还需要下面的操作
一般我们只接收id,但是也可以接收多个
如果进行了参数绑定,没有传递参数则会报错
此时我们可以给一个默认值
3.2按照顺序绑定
一般我们不推荐用这个
4.依赖注入
手册–请求–依赖注入
依赖注入:简单的说,要在一个类A中使用另一个依赖类B时,不直接在类A中实例化类B,而是先实例化类B后再以参数的形式传入类A.
ThinkPHP的依赖注入(也称之为控制反转)是一种较为轻量的实现,无需任何的配置,并且主要针对访问控制器进行依赖注入。可以在控制器的构造函数或者操作方法(指访问请求的方法)中类型声明任何(对象类型)依赖,这些依赖会被自动解析并注入到控制器实例或方法中。
依赖注入基本原理代码示例
<?php
//一个请求类
class Request{
public function param(){
return 'params';
}
}
//我们自己的控制器
class Goods{
//控制器中的方法
public function index(){
$request = new Request();
$params = $request->param();
return $params;
}
}
$goods = new Goods();
echo $goods->index();
这是最基本原理,当然了,框架的话,肯定会检测你方法是否传递了一个依赖对象,然后才判断是否要传递实例化对象到方法中
<?php
//一个请求类
class Request{
public function param(){
return 'params';
}
}
//我们自己的控制器
class Goods{
//控制器中的方法
public function index(Request $request){
$params = $request->param();
return $params;
}
}
$goods = new Goods();
$request = new Request();
echo $goods->index($request);
5.总结
//1.获取请求对象
$request = request();
$request = \think\Request::instance();
$request = $this->request; //仅限于继承了底层控制器的情况下
public function save(Request $request) //依赖注入
//2. 接收请求参数 param方法
$params = $request->param();
$params = input();
$params = request()->param();
$id = $request->param('id');
$id = input('id');
public function edit($id)//参数绑定
8、视图
1.视图的组成
View视图类(继承了自定义模板引擎,功能与Smarty类似)
HTML模板文件
2.模板的定义
手册–模板–模板定位
为了对模板文件更加有效的管理,ThinkPHP对模板文件进行目录划分,默认的模板文件定义规则是:视图目录/控制器名(小写)/操作名(小写)+模板后缀
默认的视图目录是模块的view目录,框架的默认视图文件后缀是.html。
2.1return view()
2.2return $this->fetch()
2.3 名称不一样传递参数
2.4给模板传递参数
页面上输出
直接使用view()方法传递参数
$user = ['id'=>11,'name'=>'Jack'];
$age = 30;
return view('edit',['user'=>$user,'age'=>$age]);
使用compact函数,简化一点代码,效果是一样的
9、静态模板和框架整合
一般模板去网上扒,要么前台写好,要么自己边开发边写
1.整合步骤
模板整合思路:
①确定页面的访问路径(模块、控制器、方法)
②新建对应的控制器方法,在方法中调用模板
③将模板页面移动到对应的视图目录下(创建子目录)
④将静态资源文件移动到public/static/admin目录下
⑤修改模板文件中静态资源路径
2.模板布局
手册–模板–模板布局
使用模板布局,就是把多个模板页面都有的公共代码给抽取出来,放到一个公共位置开发维护
好处:相同的代码只维护一份,减少代码工作量
后台全局布局设置步骤:
①修改配置文件application/admin/config.php,加入以下设置
'template' => [
'layout_on' => true,//开启布局
'layout_name' => 'layout',//布局文件名称
]
②将静态资源文件移动到/public/static/admin目录下
③在application/admin/view目录下,新建layout.html
将后台页面公共的头部、底部代码提取到layout.html中,在中间位置放一个特殊字符串“{ CONTENT}”,表示此位置,替换为原始要访问的页面内容。
layout.html文件中, 只保留所有页面公共 的css和js相关代码,修改静态资源路径
注: 一定不能 直接将所有css和js都放在layout.html中。
注:TP框架中,模板中的静态资源路径,不能使用相对路径./ ,必须使用以/开头的路径。
④