1、解除禁用函数:curl -Ss https://www.workerman.net/webman/fix-disable-functions | php
2、安装webman:composer create-project workerman/webman
3、服务器安全组和宝塔安全规则放开8787端口,即可通过http://182.254.227.189:8787/访问
4、运行项目:php start.php start
5、配置网站运行目录为public目录
6、配置反向代理,让域名访问代替端口访问,在宝塔:站点修改-反向代理,添加:http://127.0.0.1:8787和$host即可
宝塔伪静态配置如下: #这个让域名可以访问/public下的文件,否则只能通过http://ip:8787/abc.css访问 if (-f $request_filename){ break; }
根据域名重写url if ($host = 'fy63.com') { rewrite ^/(.)$ /cn/$1 last; } if ($host = 'www.fy63.com') { rewrite ^/(.)$ /cn/$1 last; } if ($host = 'ming.fy63.com') { rewrite ^/(.)$ /admin/$1 last; } if ($host = 'api.fy63.com') { rewrite ^/(.)$ /api/$1 last; }
7、解析绑定泛域名并解析
8、申请泛域名ssl证书
9、安装多应用绑定多域名插件:composer require webman/domain
安装后,域名无法访问,解决方法如下:
1、/config/plugin/webman/domain/app.php把true改为false即可【无须重启服务】
10、把默认应用移到cn应用下,并修改控制器命名空间为:namespace app\cn\controller
修改多应用绑定域名插件配置为: 'df81.com' => 'cn', // 绑定到cn应用'www.df81.com' => 'cn', 并把enable的false改为true, 伪静态添加: if ($host = 'df81.com') {rewrite ^/(.)$ /cn/$1 last;}if ($host = 'www.fy63.com') {rewrite ^/(.)$ /cn/$1 last;} 重启http服务 不能移除在app根目录下的默认应用,否则报错【参考报错信息:】 process error: class app\process\Http not existsprocess error: class app\process\Monitor not exists app\functions.php
11、去掉控制器后缀标识
config/app.php中修改 // 'controller_suffix' => 'Controller','controller_suffix' => '',
12、测试宝塔里与传统fpm框架站点并存已OK
13、多应用路由重写已OK
1、config/route.php里: use Webman\Route; // 加载cn应用下的路由配置require_once app_path('cn/config/route.php'); 2、app/cn/config/route.php里: use Webman\Route; Route::group('/cn', function () {// 测试路由Route::any('/bbb/', [\app\cn\controller\Test::class, 'bbb']);}); 3、app/cn/controller/Test.php里: namespace app\cn\controller; use support\Request; class Test{// 路由测试public function bbb(Request $request){return 'cn应用test控制器bbb方法';}
14、安装think-view模板
1、安装tp模板 2、config/view.php use support\view\ThinkPHP; return [ 'handler' => ThinkPHP::class ]; 3、app/admin/controller/index.php use support\View; class Index { public function index(Request $request) { View::assign('name', 'value3'); return view(); } 4、app/admin/view/index/index.html hello {$name}
15、多应用中间件已OK
1、新建中间件文件:/app/admin/middleware/AdminGlobal.php namespace app\admin\middleware;use Webman\MiddlewareInterface;use Webman\Http\Response;use Webman\Http\Request; class AdminGlobal implements MiddlewareInterface{public function process(Request $request, callable $next): Response{if (strpos($request->path(), '/.') !== false) {return response(' 403 forbidden============= ', 403);}// 获取控制器类名部分$request->controller = basename(str_replace('\', '/', $request->controller));// 驼峰法转为下划线小写$request->controller = strtolower(preg_replace('/(?<!^)[A-Z]/', '$0', $request->controller));$request->action = strtolower(preg_replace('/(?<!^)[A-Z]/', '$0', $request->action));
// 模板文件,调用公共函数template $request->template = template($request->controller.'/'.$request->action); $response = $next($request); // Add cross domain HTTP header /*$response->withHeaders([ 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Credentials' => 'true', ]);*/ return $response; }
2、修改中间件配置文件:/config/middleware.php return [// admin应用中间件'admin' => [app\admin\middleware\AdminGlobal::class,],]; 3、控制器获取中间件参数:/app/admin/controller/index.php View::assign('title', $request->action);
16、安装ThinkORM
17、多应用及前后台采用不同模板方案已OK
1、修改/config/view.php文件配置(变更前台模板位置): use support\view\ThinkPHP; return ['handler' => ThinkPHP::class,'options' => ['view_path' => base_path().DIRECTORY_SEPARATOR.'template'.DIRECTORY_SEPARATOR,],]; 2、前台控制器:/app/cn/controller/index.php: 直接:return view();即可调佣 3、后台模板通过中间件及自定义函数方式实现: A、自定义函数:functions.php: function template($path = 'index/index', $app = 'admin'){$path = '../app/'.$app.'/view/'.$path;return $path;} B、中间件/app/admin/middleware/AdminGlobal.php: // 模板文件,调用公共函数template$request->template = template($request->controller.'/'.$request->action); C、控制器/app/admin/controller/index.php return view($request->template);
18、自动加载后台admin应用函数functions.php
/config/autoload.php如下: 'files' => [ base_path() . '/app/functions.php', base_path() . '/app/admin/functions.php', base_path() . '/support/Request.php', base_path() . '/support/Response.php', ]
19、安装isMobile移动端检测类库
官网:https://docs.mobiledetect.net/及https://github.com/serbanghita/Mobile-Detect $detect = new MobileDetect();$detect->setUserAgent($request->header('user-agent'));//webman框架要加这个if($detect->isMobile() or $detect->isTablet()){$equipment = 'mobile';}else{$equipment = 'pc';}
20、更改process位置与app平级
1、剪切app/process到/process/【与app目录平级】 2、修改config/process.php文件: 第17行:use app\process\Http;修改为:use process\Http; 第40行:'handler' => app\process\Monitor::class,修改为: 'handler' => process\Monitor::class, 3、重启
21、安装缓存cache
composer require -W symfony/cache psr/simple-cache
22、安装验证码
composer require webman/captcha
23、安装多语言
composer require symfony/translation
24、安装验证器
composer require topthink/think-validate
25、安装图像处理
composer require intervention/image
26、安装推送【先不安装】
composer require webman/push
27、安装短信
composer require "overtrue/easy-sms"
28、安装邮件
composer require symfony/mailer
29、安装qrcode
composer require endroid/qr-code
30、安装jwt
composer require firebase/php-jwt
31、安装拼音【标记:云存储、微信开发扩展包未安装】
composer require overtrue/pinyin:^5.0
32、安装社交登录
composer require "overtrue/socialite" -vvv
33、安装中文简繁转换
composer require overtrue/php-opencc -vvv
34、安装中国公农历转换
35、安装微信和支付宝支付
composer require yansongda/pay:~3.7.0 -vvv
36、基础控制器并赋值模板
1、Base.php控制器: namespace app\cn\controller;use support\Request;use think\facade\Db;use support\View; class Base {public function common(Request $request){View::assign('request',$request); // 站点信息 $siteRs = Db::name('site')->where('lang',$request->app)->field('title,keyword,description,company,logo,ico,signid,closereason,icp_number,icp_link,htmlcode,agreement,lang')->find(); View::assign('siteRs',$siteRs); // 字段管理 $fieldList = Db::name('field')->where('lang',$siteRs['lang'])->field('id,fieldlabel,fieldvalue')->select(); foreach($fieldList as $w){ View::assign($w['fieldlabel'],$w['fieldvalue']); } // 导航嵌套循环 $navWhere[] = ['att_type','in','head,tile']; $navWhere[] = ['lang','=',$siteRs['lang']]; $navWhere[] = ['parentid','=',0]; $navWhere[] = ['signid','=',1]; $client = $request->detect->isMobile() ? 'wap' : 'pc'; $navigation = sublist('navigation',$navWhere,20,'sequence desc','',$client); View::assign('navigation',$navigation); return; } 2、Index.php控制器: namespace app\cn\controller; use support\Request; use support\View; class Index extends Base { public function index(Request $request) { $this->common($request); return view($request->template); }
37、整合ueditor编辑器
知识点:在控制器加载config.json,判断action为config时,return config
html代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>UEditor Image Upload Example</title> <script src="/skin/admin/ueditor/ueditor.config.js" type="text/javascript"></script> <script src="/skin/admin/ueditor/ueditor.all.min.js" type="text/javascript"></script> <script src="/skin/admin/ueditor/lang/zh-cn/zh-cn.js" type="text/javascript"></script> </head> <body> <form action="<?php the_view_url('ueditor/index'); ?>" method="post" enctype="multipart/form-data"> <script id="editor" type="text/plain" style="width:100%;height:500px;"></script> <input type="hidden" name="content" id="content"> <button type="submit">Submit</button> </form> <script> var editor = UE.getEditor('editor', { serverUrl: '<?php the_view_url('ueditor/index'); ?>' // 设置上传图片的接口 }); // 提交表单时将内容填入隐藏域 document.querySelector('form').onsubmit = function() { document.getElementById('content').value = editor.getContent(); }; </script> </body> </html>
php控制器上传代码:
<?php namespace app\cn\controller; use support\Request; class Ueditor { public function index(Request $request){ date_default_timezone_set("Asia/Chongqing"); error_reporting(E_ERROR); header("Content-Type: text/html; charset=utf-8"); $CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents(public_path().'/skin/admin/ueditor/php/config.json')), true); $action = $request->get('action'); switch ($action) { case 'config': $result = json_encode($CONFIG); return $result; break; /* 上传图片 */ case 'uploadimage': $fieldName = $CONFIG['imageFieldName']; $file = $request->file($fieldName); if ($file && $file->isValid()) { $suffix = $file->getUploadExtension(); $size = round($file->getSize() / 1024,1); $filename = date('YmdHis').rand(1000,9999).'.'.$suffix; $path = "/uploads/".$filename; $file->move(public_path().$path); $data = array( 'state' => 'SUCCESS', 'url' => $path, // 上传后的地址,采用绝对路径,把前面的点.去掉 'title' => $filename, // 上传后的文件名 'original' => '', 'type' => '', 'size' => $size, // 文件大小,MB ); return json_encode($data); } return json_encode(array('state' => '上传失败')); break; default: return json(['code' => 1002, 'msg' => '文件不存在', 'data' => $action]); break; } } }
38、ueditor改造
编辑器去掉图片的title属性:
找到ueditor.all.min.js,将其中的 d.setAttribute("title", a.title || ""), d.setAttribute("alt", a.original || "") 改为 d.removeAttribute("title"), d.removeAttribute("alt")
多图上传对话框去掉图片搜索功能【后期改为搜索服务器里的图片】
ueditor/dialogs/image/image.html 注释掉tab选项卡 <span class="tab" data-content-id="search"><var id="lang_tab_search"></var></span>
涂鸦失败是因为缺少下面代码:
error_reporting(E_ERROR); 上传涂鸦用post而不是get,即用这个: $base64Data = $request->post($fieldName);
下一篇: webman开发学习步骤(二)