https://www.kancloud.cn/hubqin/thinkphp/1361597
如果看不懂的 可以看下之前的文档 比如tp5.1 5.0 有的东西没搬过来
记得加路径 或者(全路劲)php (全路径)composer.phar 命令 的方式运行。避免php版本问题==
要开启多应用,必须使用 composer require topthink/think-multi-app 安装多应用拓展!!
php think run -p 1000
这中方式启动的是php的内置服务器 所以如果nginx设置了这个端口号 启动不起来 。
这个仅用于测试 平常还是用nginx的好。而且可以把目录指定为public目录,这样直接 ip:1000 就能访问到了 。但是会不会php使用info的时候 根目录出错?
另外安装composer的时候 不要要从小皮面板安装 坑货······
【
且需要更改php命令行的版本 或者好像curl -sS https://getcomposer.org/installer | php 这个命令改最后一个参数为安装路径就行?
然后php8.0要安装zip拓展 直接小皮面板会报错 要手动安装 ==都是坑
】不用小皮就不会遇到这些问题!
用刚刚tp自带的服务器 退出终端命令行就不能访问了,所以用nginx
记得设置端口为你指定的即可 。
注意ssl的话 端口号不能冲突 比如一个1000 一个10001 不一定非要443.
域名名称也是随便填写的 实际只用看端口号。
一个https证书能多个端口用
server{
listen 10001 ;
server_name www.tp6.com ;
root /www/admin/www.tp6.com_80/wwwroot/public/ ;
#301重定向
#rewrite ^(.*)$ $1 permanent;
#强制SSL
#rewrite ^(.*)$ https://$host$1 permanent;
#防盗链
location / {
#伪静态
include /www/admin/www.tp6.com_80/wwwroot/public/.rewrite.conf;
#首页
root /www/admin/www.tp6.com_80/wwwroot/public/;
index index.php index.html error/index.html;
}
#流量限制
#防火墙配置
access_by_lua_file /www/common/waf_lua//access_ctrl.lua;
set $RulePath "/www/admin/www.tp6.com_80/data/rule";
set $logdir "/www/admin/www.tp6.com_80/log/hacklog";
set $CCDeny on;
set $attacklog on;
set $whiteModule on;
set $getMatch on;
set $cookieMatch on;
set $postMatch on;
#日志
access_log /www/admin/www.tp6.com_80/log/nginx_access_$logdate.log main;
error_page 403 /error/403.html;
error_page 400 /error/400.html;
error_page 404 /error/404.html;
error_page 502 /error/502.html;
error_page 503 /error/503.html;
#处理PHP
location ~ [^/]\.php(/|$) {
root /www/admin/www.tp6.com_80/wwwroot/public/;
fastcgi_pass 127.0.0.1:8000;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi.conf;
}
#DenyFiles
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
}
server{
listen 1000 ssl ;
server_name www.tp6.com;
root /www/admin/www.tp6.com_80/wwwroot/public/;
#301重定向
#rewrite ^(.*)$ $1 permanent;
#开启SSL
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#证书文件
ssl_certificate /usr/local/phpstudy/certs/www.tp6.com/www.tp6.com_nginx_public.crt;
ssl_certificate_key /usr/local/phpstudy/certs/www.tp6.com/www.tp6.com_nginx.key;
location / {
#伪静态
include /www/admin/www.tp6.com_80/wwwroot/public/.rewrite.conf;
root /www/admin/www.tp6.com_80/wwwroot/public/;
index index.php index.html error/index.html;
}
#防盗链
#流量限制
#防火墙配置
access_by_lua_file /www/common/waf_lua//access_ctrl.lua;
set $RulePath "/www/admin/www.tp6.com_80/data/rule";
set $logdir "/www/admin/www.tp6.com_80/log/hacklog";
set $CCDeny on;
set $attacklog on;
set $whiteModule on;
set $getMatch on;
set $cookieMatch on;
set $postMatch on;
#日志
access_log /www/admin/www.tp6.com_80/log/nginx_access_$logdate.log main;
error_page 403 /error/403.html;
error_page 400 /error/400.html;
error_page 404 /error/404.html;
error_page 502 /error/502.html;
error_page 503 /error/503.html;
#处理PHP
location ~ [^/]\.php(/|$) {
root /www/admin/www.tp6.com_80/wwwroot/public/;
fastcgi_pass 127.0.0.1:8000;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi.conf;
}
#DenyFiles
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
}
phpstudy 网站那 要关了open_dir 防止跨站攻击的 不然设置public目录为 网站根目录后 就访问不到外面的
如果php_ini中设置了 也关了 或者设置下正常目录
nginx中 和fastcgi.conf里可能也有这个设置
然后 要开启php的
display_errors = On
display_startup_errors = On
默认是不开启的==
这个 即使没开 框架也能报错 可能是因为设置了iniset的 但是框架要正常启动了才有效。否则比如遇到的500错误 框架根本没启动起来 自然也就显示不了报错了
另外 如果是拷贝的文件 权限可能也要设置下 为755
env也要开启debug
然后runtime目录设置为777
[DATABASE]
USERNAME = root
PASSWORD = 123456
use think\facade\Env
function(){
// 获取环境变量 如果不存在则使用默认值root
Env::get('database.username', 'root');
}
一. 基础控制器
游标的意义
例如, 在 TP3 的时候, 可能是这样判断的:
$name = I('name', '');
if (empty($name)) {
// 抛出异常
}
如果参数比较多的时候, 需要判断的变量越多代码量也随着增加. 如果使用验证器就会好很多.
验证器的官方文档: https://www.kancloud.cn/manual/thinkphp6_0/1037624
直接上代码:
namespace app\api\controller;
use think\facade\Validate;
use think\Request;
class Auth
{
public function index(Request $request)
{
$input = $request->post();
$validate = Validate::rule([
'name|名称' => 'require|max:25',
'email|邮箱' => 'require|email'
]);
if (!$validate->check($input)) {
return $validate->getError();
}
}
}
验证的好处
https://www.jb51.net/article/176683.htm
主要是 重复使用 而且直接输出错误信息 避免重复写代码
使用系统服务有大大的好处和避免了直接修改类的坏处。从以上分析来看,个人觉得,使用系统服务,可以对一个类进行非入侵式的「配置」,如果哪天一个类的某些设定需要修改,我们不用直接修改这个类,只需要修改服务提供类就好了。对于扩展包来说,系统服务使其可以在扩展中灵活配置程序,达到开箱即用的效果。不过,有个缺点是系统服务类都要在程序初始化是进行实例化,如果一个系统的服务类很多,势必影响程序的性能。
————————————————
原文作者:tsin
转自链接:https://learnku.com/articles/33428
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
使用 thinkphp 开发网站,在没有 thinkphp6 版本出来以前,常规的开发模式都是使用它自带的多应用开发方式来进行项目开发。
多应用开发的一个好处就是开发方便和快速,只需要在thinkphp规定的app目录建立一个目录,比如 admin 目录,然后在其内建立一个 controller 目录就可以开始一个项目的基本开发了。
然而这样开发只适合基于它本身的目录进行开发,如果想要把项目做成一个包来开发和发布,这样的方式明显不行。
而这次,thinkphp6 引入了 Service 的概念,增加了项目转移到包开发的可能性。
Service 的使用需要继承 \think\Service ,同时 Service 默认的 register 和 boot 这两个方法是非必须的,就是说可以不用添加也是可以的。
但是,我们使用 Service 就是为了在项目启动前添加自己的配置和注册一些自己的东西,所以这两个方法对项目开发来说,都利用起来是最好的方法。
register的使用
register 的加载要先于 boot 方法,也同时在系统里属于提前注册一些具体的配置及绑定类,所以在具体的项目开发中,也是推荐只做一些项目的配置。
Service 的引入会根据 thinkphp6 生成的 Services.php 缓存顺序进行加载,所以在使用过程中需要注意当前的 Service 在缓存中属于哪个位置,防止在注册配置时候出现配置加载时出现不可知的问题。
boot 的使用
boot 通常是在 register 注册完成后进行加载,boot 方法里推荐做一些对 register 注册完成后的信息的补充处理。
thinkphp6 由于在 boot 前已做了系统配置的初始化操作,所以在这里处理一些数据库操作也是没有问题的。
Service 的其他方法
loadRoutesFrom :导入路由,传入数据为匿名函数
registerRoutes :功能于 loadRoutesFrom 一样
commands :导入脚本命令,传入数据为数组或者单个脚本
使用 Service 的场景
如果你想要把一个项目独立成一个包进行发布或者为 thinkphp6 提供扩展包。
如果只是单纯的想做一个 app 项目,Service 估计不太适合你。
最后,Service 的具体实践有没有什么好的项目推荐啊,那当然有的,这里隆重推荐一个完全使用 Service 开发的项目:
laket-admin: https://github.com/deatil/laket-admin
laket-admin 使用 thinkphp6 的 Service 模式加单应用开发而成,避开了 thinkphp6 多应用下 url 出现的一些问题,对用户端的 url 更加友好。
©著作权归作者所有:来自51CTO博客作者爱看雨的猫的原创作品,请联系作者获取转载授权,否则将追究法律责任
thinkphp6的Service的简明使用介绍
https://blog.51cto.com/u_11949903/2671735
依赖注入其实本质上是指对类的依赖通过构造器完成自动注入,例如在控制器架构方法和操作方法中一旦对参数进行对象类型约束则会自动触发依赖注入,由于访问控制器的参数都来自于URL请求,普通变量就是通过参数绑定自动获取,对象变量则是通过依赖注入生成。
api/manager/TestMgr.php
namespace app\api\manager;
class TestMgr
{
public string $name1 = 'a';
}
api/controller/Test.php
class Test
{
public function __construct(TestMgr $testMgr){
$this->testMgr=$testMgr;
}
public function index()
{
return $this->testMgr->name1; //输出a
//same as $a=new TestMgr();return $a->name;
}
如果换成我们手动调用的方式,那么正常的流程应该是
$testMgr = new TestMgr();//多出来了这一步 要先实例化TestMgr
$test = new Test($testMgr);
$test->index($testMgr);
然而 浏览器直接调用的方式是 ,因为 正常情况下 不可能我们接口调用 还去 先new一堆东西吧
$test = new Test();
$test->index($testMgr);
但这样肯定会报错 因为 构造器有参数 但是你没传。所以我们不能直接这么写,要写成上面那种自动注入的参数的形式。而事实上 我们也可以通过invoke函数来完成递归实例化这一操作。
所以,相当于容器自动帮我们完成了这个操作。我们要做的 只是在方法的参数中写需要的那个类的即可 不需要去手动去new底层的一堆对象
api/manager/TestMgr.php
namespace app\api\manager;
class TestMgr
{
public string $name1 = 'a';
}
api/controller/Test.php
namespace app\api\controller;
use app\api\manager\TestMgr;
class Test
{
public function index(TestMgr $testMgr)
{
return $testMgr->name1;//1
}
}
//使用容器来实例化的话,可以自动进行依赖注入。
invoke(类名)
//某个方法依赖注入
invoke(['类名','方法名'])
$bar = new Bar();
$foo = new Foo($bar);
等价于
$foo = invoke('Foo');
也支持对某个函数或者闭包使用依赖注入
$result = invoke(function(Bar $bar) {
// ...
});
ThinkPHP使用容器来更方便的管理【类依赖】及【运行依赖注入】
简而言之,容器内部是通过反射类或闭包等来实现类的实例化(单例)。
容器并非只能用于依赖注入
//官方说明:容器中已经调用过的类会自动使用单例,除非你使用下面的方式强制重新实例化。
// 每次调用都会重新实例化->$cache = app(‘user’,true);
$arrayItem = app(‘org\utils\ArrayItem’);
上述代码会判断在容器中是否存在这个单例,如果有就直接返回,没有就帮我们自动创建一个这个类的单例然后返回。
比如:
echo app(‘user’)->name;
注释:new是写死的 而上面是字符串 可以动态解析的!!
app 快速获取容器中的实例 支持依赖注入
invoke 调用反射执行callable 支持依赖注入
依赖注入的类统一由容器进行管理,大多数情况下是在自动绑定并且实例化的。不过你可以随时进行手动绑定类到容器中(通常是在服务类的register方法中进行绑定),支持多种绑定方式。
bind就是给实例起一个别名 方便app快速调用
// 绑定类库标识
bind('user','\app\index\model\User');
// 快速调用(自动实例化)
echo app('user')->name;
更多bind的用法看手册
ps:bind 实际上是$this->app->bind(‘think\Cache’, ‘app\common\Cache’);的快捷调用
也叫助手函数
一般来说,bind只能在定义的那个地方用,其他地方就用不了了。所以,为了其他地方也能用,我们将bind函数写在provider.php文件中
容器:【“拿来即用”,不需要通过实例化,松耦,节约资源】
容器主要用于依赖注入,依赖注入会首先检查容器中是否注册过该对象实例,如果没有就会自动实例化,然后自动注入
支持使用依赖注入的场景包括(但不限于):
控制器架构方法;
控制器操作方法;
路由的闭包定义;
事件类的执行方法;
中间件的执行方法;
门面 face就大量使用了依赖注入
看设计模式那个文档。
tp中,说的直白一点,Facade功能可以让类无需实例化而直接进行静态方式调用。使用静态方式调用非静态方法时隐式的实例化了该类,无需额外的实例化工作(看最下面总结 因为要实例化的可能很多个)。
简单来说 就是request实际上是用依赖注入的方式写的,所以需要实例化一大堆。所以要么使用门面模式 要么使用自动依赖注入的方式调用!