二十五、多库
我们可以在数据库配置文件中定义多个连接信息,配置多个数据库连接参数
1、配置数据库信息
注意:配置多库的时候,建议不要启用.env文件环境变量,不然数据库配置优先从当中获取数据,我们配置的多库信息将不起作用。
'connections' => [
'mysql' => [
// 数据库类型
'type' => env('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', 'mydb'),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', 'root'),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => false,
],
'admin' => [
// 数据库类型
'type' => env('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', 'admin'),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', 'root'),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => env('database.prefix', 'admin_'),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => false,
]
],
2、创建用户表
新建数据库admin,添加admin_user表
CREATE TABLE `admin_user` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '管理员ID',
`account` varchar(64) CHARACTER SET utf8 NOT NULL COMMENT '账号',
`password` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '密码',
`name` varchar(32) CHARACTER SET utf8 DEFAULT NULL COMMENT '姓名',
`times_login` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登陆次数',
`status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态 1开启 0禁用',
`time_add` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`time_last` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后登录时间',
PRIMARY KEY (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
INSERT INTO `admin_user` VALUES ('1', 'zhang', 'e10adc3949ba59abbe56e057f20f883e', '张帅', '10', '1', '1619159236', '1619159236');
3、controller
访问多库
我们可以调用 Db::connect 方法动态配置数据库连接信息,例如:
namespace app\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
class Index extends BaseController{
public function index(){
$select = Db::connect('admin')->table('admin_user')->select();
$select = Db::connect('admin')->name('user')->select();
print_r($select);
}
}
connect 方法必须在查询的最开始调用,而且必须紧跟着调用查询方法,否则可能会导致部分查询失效或者依然使用默认的数据库连接。
4、model
访问多库
如果某个模型类里面定义了 connection 属性的话,则该模型操作的时候会自动按照给定的数据库配置进行 连接,而不是配置文件中设置的默认连接信息
- 创建
model
文件:app/Model/AdminUser.php
namespace app\model;
use think\Model;
class AdminUser extends Model{
protected $connection = 'admin';
protected $table = 'admin_user';
protected $name = 'User';
protected $pk = 'uid';
public function get_data(){
$select = static::select();
return $select->toArray();
}
}
app\controller\Index.php 控制器
namespace app\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
use app\model\User;
class Index extends BaseController{
public function index(){
$db = new AdminUser();
$index = $db->get_data();
print_r($index);
}
}
二十六、路由
路由是应用开发中比较关键的一个环节,其主要作用包括但不限于:
- 让URL更规范以及优雅;
- 隐式传入额外请求参数;
- 统一拦截并进行权限检查等操作;
- 绑定请求数据;
- 使用请求缓存;
- 路由中间件支持;
路由定义文件
- 要使用Route路由,必须在route\app.php文件引入
use think\facade\Route;
1、路由方法
Route::rule('路由表达式', '路由地址', '请求类型');
// 注册路由到News控制器的read操作
Route::rule('new/:id','News/read');
// 我们访问:http://zhang.com/new/5
// 会自动路由到:http://zhang.com/News/read/id/5
// 并且原来的访问地址会自动失效。
// 请求类型不指定的话默认为任何请求类型有效
Route::rule('new/:id', 'News/update', 'POST');
Route::rule('new/:id','News/read','GET|POST');
Route::快捷方法名('路由表达式', '路由地址');
Route::get('new/<id>','News/read'); // 定义GET请求路由规则
Route::post('new/<id>','News/update'); // 定义POST请求路由规则
Route::put('new/:id','News/update'); // 定义PUT请求路由规则
Route::delete('new/:id','News/delete'); // 定义DELETE请求路由规则
Route::any('new/:id','News/read'); // 所有请求都支持的路由规则
2、配置路由
use think\facade\Route;
Route::rule('/', 'index');
Route::rule('/', 'index/index');
Route::rule('dlu', 'login/login');
// 路由直接调用回调函数
Route::get('think', function () {
return 'hello,ThinkPHP6!';
});
// 路由到http://zhang.com/Code/index控制器方法
Route::get('code', 'code/index');
// 路由也可以携带参数跳转到对应控制器
Route::get('hello/:name?', 'index/hello');
Route::rule('/', 'index'); // 首页访问路由
Route::rule('my', 'Member/myinfo'); // 静态地址路由
Route::rule('blog/:id', 'Blog/read'); // 静态地址和动态地址结合
Route::rule('new/:year/:month/:day', 'News/read'); // 静态地址和动态地址结合
Route::rule(':user/:blog_id', 'Blog/read'); // 全动态地址
3、参数传值
use think\facade\Route;
// 必选参数 这两种传值都可以,但必须传值
// http://zhang.com/hello?name=zhang
// http://zhang.com/hello/zhang
Route::rule('hello/:name', 'index/hello');
Route::rule('hello/<name>', 'index/hello');
// 可选参数,可以不传值,控制器方法中将按默认值输出
Route::rule('hello/:name?', 'index/hello');
Route::rule('hello/[:name]', 'index/hello');
Route::rule('hello/<name?>', 'index/hello');
4、获取参数
- 使用
Request
基类、门面类、助手函数都可以获取参数
namespace app\controller;
use app\BaseController;
use think\facade\Request;
class Login extends BaseController
{
public function login()
{
print_r(request()->param());
print_r(Request::param());
}
}
5、参数可选
use think\facade\Route;
Route::rule('login/:id?', 'login/login');
Route::rule('login/[:id]', 'login/login');
Route::rule('login/<id?>', 'login/login');
6、完全匹配
在写路由地址的时候,发现写的路由前面的参数一样,后面无论添加什么,依然是访问前面的一个,这种情况就要用到路由完全匹配。
use think\facade\Route;
Route::rule('login/[:id]',function () {
return 'hello,ThinkPHP6!';
});
Route::rule('login/admin/:id', function ($id) {
return 'hello,'.$id;
});
Route::rule('login/:id$', 'login/login');
Route::rule('login/<id>$', 'login/login');
// 开启完全匹配
Route::rule('login/<id>$', 'login/login')->completeMatch(true);
对象方式配置路由参数:https://www.kancloud.cn/manual/thinkphp6_0/1037499
- 通过route.php配置路由参数 开启:完全匹配
<?php
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
return [
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => true,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 访问控制器层名称
'controller_layer' => 'controller',
// 空控制器名
'empty_controller' => 'Error',
// 是否使用控制器后缀
'controller_suffix' => false,
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache_key' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 操作方法后缀
'action_suffix' => '',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
];
7、额外参数
- 隐式传值,
URL
中看不到,起安全防护作用。如冲突,append
方法优先
use think\facade\Route;Route::rule('login/<id>$', 'login/login')->append(['status' => 1, 'app_id' =>5]);
8、变量规则
变量规则:https://www.kancloud.cn/manual/thinkphp6_0/1037496
- 配置参数:
default_route_pattern
- 系统默认的变量规则设置是
\w+
,只会匹配字母、数字、中文和下划线字符,并不会匹配特殊符号以及其它字符
return [
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => true,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => true,
// 访问控制器层名称
'controller_layer' => 'controller',
// 空控制器名
'empty_controller' => 'Error',
// 是否使用控制器后缀
'controller_suffix' => false,
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache_key' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 操作方法后缀
'action_suffix' => '',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
];
- 局部变量规则
use think\facade\Route;
// pattern 方法作用:改变路由的传值规则,规则是用正则表达式
// 路由传参的id只能为数字
Route::rule('login/<id>$', 'login/login')->pattern(['id'=>'[0-9]+']);
- 全局变量规则
use think\facade\Route;
Route::rule('login/<id>$', 'login/login');
Route::pattern([
'id' => '\d+',
]);
- 不需要开头添加
^
或者在最后添加$
,也不支持模式修饰符,系统会自动添加 - $ ^ 修饰符:他们是正则表达式里的符号
9、分组路由
路由分组功能允许把相同前缀的路由定义合并分组,这样可以简化路由定义,并且提高路由匹配的效率,不必每次都去遍历完整的路由规则
路由分组:https://www.kancloud.cn/manual/thinkphp6_0/1037500
use think\facade\Route;
Route::group('blog', function () {
Route::rule(':id', 'blog/read');
Route::rule(':name', 'blog/read');
})->ext('html')->pattern(['id' => '\d+', 'name' => '\w+']);
Route::group('login', function () {
Route::rule('l/<id>', 'login/login');
Route::rule('r/<name>', 'login/reg');
})->ext('html')->pattern(['id' => '\d+', 'name' => '\w+']);
Route::group('/', function () {
Route::rule('l/<id>', 'login/login');
Route::rule('r/<name>', 'login/reg');
});
Route::group('blog', function () {
Route::get('think/:id', function ($id='') {
return 'blog/think'.$id;
});
// http://zhang.com/blog/think/6
Route::get('php/:name?', function ($name='zhang') {
return 'blog/php'.$name;
});
// http://zhang.com/blog/php/shuai
Route::get('tp', function () {
return 'thinkphp6';
});
// http://zhang.com/blog/tp
});
Route::group('blog', function () {
Route::get('think/:id', function ($id='') {
return 'blog/think'.$id;
});
// http://zhang.com/blog/think/6.html
Route::get('php/:name?', function ($name='zhang') {
return 'blog/php'.$name;
});
// http://zhang.com/blog/php/shuai.html
Route::get('tp', function () {
return 'thinkphp6';
});
// http://zhang.com/blog/tp.html
})->ext('html|php');
// URL后缀检测,支持匹配多个后缀
// 如果ext方法不传入任何值,表示不允许使用任何后缀访问。
10、路由参数
路由分组及规则定义支持指定路由参数,这些参数主要完成路由匹配检测以及后续行为。
https://www.kancloud.cn/manual/thinkphp6_0/1037499
路由参数可以在定义路由规则的时候直接传入(批量),推荐使用方法配置更加清晰。
参数 | 说明 | 方法名 |
---|---|---|
ext | URL后缀检测,支持匹配多个后缀 | ext |
deny_ext | URL禁止后缀检测,支持匹配多个后缀 | denyExt |
https | 检测是否https请求 | https |
domain | 域名检测 | domain |
complete_match | 是否完整匹配路由 | completeMatch |
model | 绑定模型 | model |
cache | 请求缓存 | cache |
ajax | Ajax检测 | ajax |
pjax | Pjax检测 | pjax |
json | JSON检测 | json |
validate | 绑定验证器类进行数据验证 | validate |
append | 追加额外的参数 | append |
middleware | 注册路由中间件 | middleware |
filter | 请求变量过滤 | filter |
二十七、多应用
- 一个项目中往往要有前台index应用和后台admin应用以及更多,这时候就要开启多应用模式。
- 如果要使用多应用模式,你需要安装多应用模式扩展
think-multi-app
composer require topthink/think-multi-app
- 通过
php think build 应用名
命令创建多应用目录文件夹,也可以手动新建应用文件夹和其中的MVC文件 - 一般需要单独配置应用时需要从项目根目录把主文件下的config配置文件和route配置文件复制到应用目录下就可以单独设置应用配置
- 通过命令
php think make:controller admin@Index --plain
来命令创建控制器(其中—plain是否生成函数)
多应用模式:https://www.kancloud.cn/manual/thinkphp6_0/1297876
http://zhang.com ===> http://zhang.com/index/index/index
如果直接访问域名根目录,访问的其实是index
默认应用,可以通过app.php
配置文件的default_app
配置参数指定默认应用。
1、目录结构
├─app 应用目录
│ ├─index 主应用
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ ├─config 配置目录
│ │ ├─route 路由目录
│ │ └─ ... 更多类库目录
│ │
│ ├─admin 后台应用
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ ├─config 配置目录
│ │ ├─route 路由目录
│ │ └─ ... 更多类库目录
│ │
│ ├─AppService.php 应用服务类
│ ├─BaseController.php 默认基础控制器类
│ ├─common.php 全局公共函数文件
│ ├─event.php 全局事件定义文件
│ ├─ExceptionHandle.php 应用异常定义文件
│ ├─middleware.php 全局中间件定义文件
│ ├─provider.php 服务提供定义文件
│ ├─Request.php 应用请求对象
│ └─service.php 系统服务定义文件
│
2、创建目录
- 创建
app/index
应用目录 - 把之前的
MVC
目录放到刚创建的index应用目录中
namespace app\index\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
class Index extends BaseController{
public function index(){
$cat = Db::table('cat')->select();
$c = input('get.c',0);
$t = input('get.t','');
$where[] = ['status','=',1];
if($c != 0){
$where[] = ['cat','=',$c];
}else if(!empty($t)){
$where[] = ['title','like','%'.$t.'%'];
}
$select = Db::table('boke')->where($where)->paginate(10);
$page = $select->render();
echo $select->total();
View::assign([
'c' => $c,
't' => $t,
'cat' => $cat,
'select' => $select,
'page' => $page
]);
return View::fetch('index');
}
}
3、访问路径
单应用:http://zhang.com/index.php/控制器名称/操作方法/参数
多应用:http://zhang.com/index.php/应用名称/控制器名称/操作方法/参数
完整路径:http://zhang.com/index.php/index/index/index
4、创建多项目
- 创建
app/admin
应用 目录 - 创建
MVC
目录在admin
应用目录下 - 创建
Index.php
控制器
namespace app\admin\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
class Index extends BaseController
{
public function index(){
return View::fetch();
}
}
5、数据库配置
- 创建
app/index/config/database.php
文件
return [
// 默认使用的数据库连接配置
'default' => env('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('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', 'oyk'),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', 'root'),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => false,
],
'admin' => [
// 数据库类型
'type' => env('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', 'admin'),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', 'root'),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => false,
]
// 更多的数据库配置信息
],
];
6、路由配置
- 创建
app/index/route/app.php
文件
use think\facade\Route;
Route::group('/', function () {
Route::rule('login/<id>', 'login/login');
Route::rule('reg/<name>', 'login/reg');
});
ThinkPHP6 博客实战
博客数据库
boke.sql
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for boke
-- ----------------------------
DROP TABLE IF EXISTS `boke`;
CREATE TABLE `boke` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(300) DEFAULT NULL COMMENT '标题',
`img` varchar(300) DEFAULT NULL COMMENT '图片',
`content` text COMMENT '内容',
`date` date DEFAULT NULL COMMENT '时间',
`cat` varchar(50) DEFAULT NULL COMMENT '类型',
`num` int(10) unsigned DEFAULT '0' COMMENT '浏览量',
`hot` tinyint(1) unsigned DEFAULT '0' COMMENT '热门 1是 0否',
`status` tinyint(1) unsigned DEFAULT '1' COMMENT '状态 1开启 0关闭',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of boke
-- ----------------------------
INSERT INTO `boke` VALUES ('1', '《天龙八部》系列课程整理', 'https://img.php.cn/upload/course/000/000/001/5d242759adb88970.jpg', 'PHP中文网因专业的讲师水平和高效的视频质量,推出的各种视频课程系列一直以来都深受大家喜爱。特别是《天龙八部》系列、《独孤九贱》系列、《玉女心经》系列的原创课程在行业内更是具有强大的影响力,好评不断!为了让大家能更快速方便的寻找到相关教程资源,我们在这篇文章中特意将《天龙八部》系列课程整理出来供大家有针对性得学习!', '2021-02-18', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('2', 'php中文网《玉女心经》公益PHP WEB培训系列课程汇总', 'https://img.php.cn/upload/course/000/126/153/5aa23f0ded921649.jpg', 'php中文网近期推出的《独孤九贱》系列、《天龙八部》系列、《玉女心经》原创视频课程,好评如潮!由于《玉女心经》系列课程没有做成专题,所以大家找起来有点费劲,为了更好的服务广大php中文网粉丝们,特把课程整理汇总给大家!', '2021-02-11', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('3', 'html5中submit是按钮么', null, 'html5中submit是按钮,它是button的一个特例,它把提交这个动作自动集成了。submit会自动将表单的数据提交,使用submit时需要验证要加return', '2021-02-10', '4', '0', '0', '1');
INSERT INTO `boke` VALUES ('4', 'css如何去除下划线', null, 'css去除下划线的方法:首先创建一个HTML示例文件;然后在body中定义一个a标签;最后通过css属性为“a{text-decoration:none}”去除下划线即可。', '2021-02-01', '4', '0', '0', '1');
INSERT INTO `boke` VALUES ('5', 'linux如何查看进程', 'https://img.php.cn/upload/article/202102/24/2021022409272725770.jpg', 'windows defender是windows系统自带的一款杀毒软件,对于很多人来说,这款软件不仅没有起到保护电脑的作用,还增加了很多不必要的麻烦。比如我们安装了一些破解版软件,windows defender就会杀这些破解软件,很让人讨厌。', '2021-02-01', '6', '1', '0', '1');
INSERT INTO `boke` VALUES ('6', 'Ubuntu20.04/18.04下安装或更新至PHP8', 'https://img.php.cn/upload/article/000/000/020/2c02ff679ec7afab974a691aac09d535-0.png', '本指南让你了解如何安装最新的 php 版本 8,并在你的任何 VPS、云服务器、专用主机上的 Ubuntu 20.0 或 18.04 系统中升级到最新版本,并将其配置为 Apache 和 Nginx。', '2021-02-01', '2', '5', '0', '0');
INSERT INTO `boke` VALUES ('7', 'PHP 8新特性之JIT对PHP应用性能的影响', null, '即将发布的 PHP 8 最受大家关注的新特性就是引入了对 JIT 的支持,我已经简单介绍了 JIT 是什么,以及与 Opcache 的区别', '2021-02-01', '2', '97', '0', '1');
INSERT INTO `boke` VALUES ('8', '详解PHP7中的zval结构和引用计数机制', 'https://img.php.cn/upload/article/000/000/024/6053286f637d2966.jpg', '最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷惑。 仔细一想不难发现问题所在:这些文章大多是 PHP5.x 时代的,而 PHP7 发布后,采用了新的 zval 结构,相关的资料也比较贫瘠,所以我结合一些资料做了一个总结,主要侧重于解释新 zval 容器中的引用计数机制,如有谬误,还望不吝指教。', '2021-01-01', '2', '185', '0', '1');
INSERT INTO `boke` VALUES ('9', 'php登录失败怎么处理', 'https://img.php.cn/upload/article/202103/19/2021031909102812621.jpg', 'php登录失败的处理方法:首先创建一个表负责记录用户登录的信息;然后从user_login_info表查询最近30分钟内有没有相关密码错误的记录;接着统计记录总条数是否达到设定的错误次数;最后设置登录密码错误次数限制即可。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('10', 'php如何去掉字符串末尾字符', 'https://img.php.cn/upload/article/000/000/024/6053250623ecf930.jpg', 'php去掉字符串末尾字符的方法:1、直接使用substr()函数倒序裁掉最后一位字符,语法“substr(string,0,-1)”;2、使用rtrim()函数,语法“rtrim(string,charlist)”。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('11', 'php异常和错误的区别是什么', 'https://img.php.cn/upload/article/202103/18/2021031817511956954.jpg', 'php异常和错误的区别:1、PHP错误是属于php程序自身的问题,一般是由非法的语法,环境问题导致的;2、PHP异常一般是业务逻辑上出现的不合预期、与正常流程不同的状况,不是语法错误。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('12', 'linux下如何查看php-fpm是否安装', 'https://img.php.cn/upload/article/000/000/024/60532042dd48f908.jpg', 'linux下查看php-fpm是否安装的方法:打开终端,执行“whereis php-fpm”或者“find / -name php-fpm”命令,如果成功输出php-fpm的安装位置,则表示有安装。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('13', 'php的数据库修改语句是什么', 'https://img.php.cn/upload/article/202103/18/2021031817353472746.jpg', 'php的数据库修改语句是UPDATE,用于更新数据库表中已存在的记录,语法为【UPDATE table_name SET column1=value, column2=value2,...WHERE some_column=some 】。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('14', 'php怎么设置状态码', 'https://img.php.cn/upload/article/000/000/024/60531da39e7a2975.jpg', '在php中,可以使用http_response_code()函数来设置状态码,该函数用于设置响应的HTTP状态码,语法格式“http_response_code (状态码) ”。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('15', 'excel怎么冻结选定区域', 'https://img.php.cn/upload/article/202103/18/2021031817270344979.jpg', 'excel冻结选定区域的方法:首先选定你想固定不变的位置;然后点击表格最上面的菜单栏“视图”那里,再点击“冻结窗格”下方的“冻结窗格”即可。', '2021-01-01', '2', '0', '0', '1');
INSERT INTO `boke` VALUES ('16', '在线考试系统实战【公益直播】', 'https://img.php.cn/upload/course/000/000/001/60862c6ba99af257.png', '三天大型公益直播课《模仿驾校考试系统实战开发》,使用框架: bootstrap、jquery、ThinkPHP6.0', '2021-05-06', '2', '0', '0', '1');
cat.sql
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for cat
-- ----------------------------
DROP TABLE IF EXISTS `cat`;
CREATE TABLE `cat` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '分类名',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
`status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态 1开启 0关闭',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of cat
-- ----------------------------
INSERT INTO `cat` VALUES ('1', 'Layui', '0', '1');
INSERT INTO `cat` VALUES ('2', 'PHP', '2', '1');
INSERT INTO `cat` VALUES ('3', 'ThinkPHP', '0', '1');
INSERT INTO `cat` VALUES ('4', '前端', '0', '1');
INSERT INTO `cat` VALUES ('5', '小程序', '0', '1');
INSERT INTO `cat` VALUES ('6', '服务器', '0', '1');
一、控制器
- 新建
Base.php
文件
namespace app\index\controller;
use app\BaseController;
use app\AppApi;
use think\facade\Db;
use think\facade\View;
class Base extends BaseController{
public function __construct(){
$cat = Db::table('cat')->select();
$hot = Db::table('boke')->where('status',1)->where('hot',1)->limit(10)->select();
View::assign([
'cat' => $cat,
'hot' => $hot
]);
}
}
Index.php
文件
namespace app\index\controller;
use app\index\controller\Base;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
class Index extends Base
{
public function index(){
$select = Db::table('boke a')->join(['cat'=>'c'],'a.cat=c.id')->where('a.status',1)->limit(10)->order('a.bid DESC')->select();
View::assign([
'select' => $select
]);
return View::fetch();
}
public function lists(){
$c = Request::param('c',0);
$t = Request::param('t','');
$where[] = ['a.status','=',1];
if($c != 0){
$where[] = ['a.cat','=',$c];
}else if(!empty($t)){
$where[] = ['a.title','like','%'.$t.'%'];
}
$select = Db::table('boke a')->join(['cat'=>'c'],'a.cat=c.id')->where($where)->order('a.bid DESC')->paginate(10);
$page = $select->render();
View::assign([
't' => $t,
'select' => $select,
'page' => $page
]);
return View::fetch();
}
public function details(){
$id = Request::param('id');
$find = Db::table('boke')->where('bid',$id)->find();
if(!empty($find)){
$class = Db::table('cat')->where('id',$find['cat'])->find();
}
View::assign([
'find' => $find,
'class' => $class
]);
return View::fetch();
}
}
二、视图
Index/index.html
{include file="public/head" /}
<div id="main" class="wrapper">
<div id="primary" class="site-content">
{foreach($select as $select_v)}
<div id="content" role="main">
<article>
<header class="entry-header">
<h1 class="entry-title"><a href="/index/d/{$select_v['bid']}" title="{$select_v['title']}" rel="bookmark">{$select_v['title']}</a></h1>
</header>
<div class="entry-content">{$select_v['title']}</div>
<footer class="entry-meta">
发布于
<a href="/index/d/{$select_v['bid']}" title="{$select_v['date']}" rel="bookmark">
<time class="entry-date" datetime="{$select_v['date']}">{$select_v['date']}</time>
</a>。 属于
<a href="/index/l/{$select_v['cat']}" title="查看 {$select_v['name']}中的全部文章" rel="category">{$select_v['name']}</a> 分类
</footer>
</article>
</div>
{/foreach}
</div>
{include file="public/tail" /}
Index/lists.html
{include file="public/head" /}
<div id="main" class="wrapper">
<div id="primary" class="site-content">
{foreach($select as $select_v)}
<div id="content" role="main">
<article>
<header class="entry-header">
<h1 class="entry-title"><a href="/index/d/{$select_v['bid']}" title="{$select_v['title']}" rel="bookmark">{$select_v['title']}</a></h1>
</header>
<div class="entry-content">{$select_v['title']}</div>
<footer class="entry-meta">
发布于
<a href="/index/d/{$select_v['bid']}" title="{$select_v['date']}" rel="bookmark">
<time class="entry-date" datetime="{$select_v['date']}">{$select_v['date']}</time>
</a>。 属于
<a href="/index/l/{$select_v['cat']}" title="查看 {$select_v['name']}中的全部文章" rel="category">{$select_v['name']}</a> 分类
</footer>
</article>
</div>
{/foreach}
<div class="page">
<nav>
<ul class="pagination">
{$select|raw}
</ul>
</nav>
</div>
</div>
{include file="public/tail" /}
Index/details.html
{include file="public/head" /}
<div id="main" class="wrapper">
<div id="primary" class="site-content">
<div id="content" role="main">
<article>
<header class="entry-header">
<h1 class="entry-title">
{$find['title']}
</h1>
</header>
<div class="entry-content ql-editor" id="md-editor" style="padding: 0;">
{$find['content']}
</div>
<footer class="entry-meta">
发布于
<a href="" title="{$find['date']}" rel="bookmark">
<time class="entry-date" datetime="{$find['date']}">{$find['date']}</time>
</a>。 属于
<a href="/index.html?cate=4" title="查看 {$class['name']}中的全部文章" rel="category">{$class['name']}</a> 分类
</footer>
</article>
</div>
</div>
{include file="public/tail" /}
public/head.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>首页 - 欧阳克个人博客</title>
<meta name="keywords" content="博客,个人博客,欧阳克个人博客,PHP"/>
<meta name="description" content="欧阳克是PHP中文网的讲师,愿意把知识分享给大家。" />
<link rel="stylesheet" id="twentytwelve-style-css" href="/static/css/index.css" type="text/css" media="all" />
<style type="text/css" id="custom-background-css">
body.custom-background {background-color:#e6e6e6;}
input.btn-default:focus,input.no-border:focus {outline:none;}
input.no-border {font-size:15px;}
</style>
<script type="text/javascript" src="/static/js/jquery.js"></script>
<script type="text/javascript" src="/static/js/nav.js"></script>
</head>
<body class="home blog custom-background custom-font-enabled single-author">
<div id="page" class="hfeed site">
<header id="masthead" class="site-header" role="banner">
<hgroup>
<h1 class="site-title">
<a href="/" title="欧阳克个人博客" rel="home">欧阳克个人博客</a>
</h1>
<h2 class="site-description">欧阳克是PHP中文网的讲师,愿意把知识分享给大家。</h2>
</hgroup>
<nav id="site-navigation" class="main-navigation" role="navigation">
<ul class="nav-menu">
<li>
<a href="/">首页</a>
</li>
{if($cat)}
{foreach $cat as $cat_v}
<li>
<a href="/index/l/{$cat_v['id']}">{$cat_v['name']}</a>
</li>
{/foreach}
{/if}
</ul>
</nav>
</header>
public/tail.html
<div id="secondary" class="widget-area" role="complementary">
<aside id="search-2" class="widget widget_search">
<form role="search" action="/index/l" method="GET">
<div>
<label class="screen-reader-text" for="t">搜索:</label>
<input placeholder="搜索" type="text" class="no-border" name="t" id="t" value="" />
<input type="submit" class="btn btn-default" value="搜索" />
</div>
</form>
</aside>
{if(!empty($hot))}
<aside id="recent-posts-2" class="widget widget_recent_entries">
<h3 class="widget-title">热门文章</h3>
<ul>
{volist name="hot" id="hot_v" key="k"}
<li>
<font style="color:#7a7a7a;">[{$k}]</font>
<a href="/index/d/{$hot_v['bid']}" title="{$hot_v['title']}">{$hot_v['title']}</a>
</li>
{/volist}
</ul>
</aside>
{/if}
</div>
</div>
<footer id="colophon" role="contentinfo">
<div class="site-info">
<span>友情链接:</span>
<a href="https://www.php.cn" target="_blank">PHP中文网</a>
</div>
</footer>
<footer role="contentinfo" style="margin-top:0;">
<div class="site-info" style="text-align:center;">
<span>
<a href="https://beian.miit.gov.cn" target="_blank">苏ICP备2020058653号-1</a>
</span>
</div>
</footer>
</div>
</body>
</html>
三、配置
route/app.php
路由配置
use think\facade\Route;
Route::rule('/', 'index/index');
Route::rule('list/[:c]/[:t]', 'index/lists');
Route::rule('article/:id', 'index/details');