thinkcmf高级应用之多模块自定义域名及入口文件
发布于 作者:苏南大叔 来源:程序如此灵动~一般来说,正常的thinkphp项目都会有多个模块,包括:面向用户的pc版网站,面向用户的m版网站,面向管理员的用户界面。在项目实际上线后,这些模块往往会要求有不同的域名,比如:pc版和手机版不同域名,后台管理要单独的域名。在代码层面,这些不同的域名上线部署,需要我们做些额外的配置。
在本文中,苏南大叔将以thinkcmf为例,说说:如何给不同的模块配置不同的域名。服务器容器使用的是nginx。
背景描述
因为thinkcmf
的代码默认根目录是/public/
,默认入口文件是/public/index.php
。这样的话,我们新建一个/public/m.php
作为手机版的入口文件,然后新建一个/public/admin.php
作为后台管理的入口文件。根据不同的使用场景,新建的这两个文件,苏南大叔将采用两种写法来配置,各有利弊。本文涉及的thinkcmf
的版本为5.0.180123
。
/public/index.php
的代码如下:
define("APP_DEBUG", false);
define('CMF_ROOT', __DIR__ . '/../');
define('APP_PATH', CMF_ROOT . 'app/');
define('CMF_PATH', CMF_ROOT . 'framework/cmf/');
define('PLUGINS_PATH', __DIR__ . '/plugins/');
define('EXTEND_PATH', CMF_ROOT . 'framework/extend/');
define('VENDOR_PATH', CMF_ROOT . 'framework/vendor/');
define('RUNTIME_PATH', CMF_ROOT . 'data/runtime/');
define('THINKCMF_VERSION', '5.0.180123');
require CMF_ROOT . 'framework/thinkphp/base.php';
\think\App::run()->send();
涉及的nginx的版本号1.12.2
,本文中的pc站的nginx
配置如下:
server{
listen 80;
server_name <pc版的域名>;
root /<代码路径>/public/;
location / {
index index.php index.html index.htm;
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php/$1;
}
}
location ~ \.php {
include fastcgi_params;
set $path_info "";
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000;
}
location ^~ /upload/ {
alias /<用户的上传文件的路径>/usr/upload/ ;
}
location ^~ /admin/ {
deny all;
}
location ^~ /m/ {
rewrite ^(.*)$ http://<手机站的域名>/$1 permanent;
}
}
第一种方案:最简单最小化的方案
在这种方案下,/public/admin.php
仅仅是做个跳转,后面的一切请求还是由/public/index.php
来承担,比较适合作为后台的入口文件处理方案。这种方案改动最小。
但是这种方案,也会有些问题,就是:页面地址url中,会一直出现着/admin/
这个模块名称。这对于有洁癖的人来说,也许是个负担,毕竟已经启用了独立的域名用于后台管理了。所以,url中这个一直出现的/admin/
字样是有些多余的。
不过考虑到:后台的使用人员相对固定,而且对于url地址一般不敏感。所以,这个小问题是可以忽略不计的。
/public/admin.php
的代码如下:
header("Location:/admin/");
管理后台的nginx
配置如下,仅仅写出个关键点,其余配置请参考pc版的nginx配置内容。
server{
server_name <后台的域名>;
// ...
location / {
index admin.php;
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php/$1;
}
}
#location ^~ /portal/ {
# rewrite ^(.*)$ http://<pc站的域名>/$1 permanent;
#}
location ^~ /m/ {
rewrite ^(.*)$ http://<手机站的域名>/$1 permanent;
}
# ...
}
这里请注意:对于以/portal/
开头的请求,理论上来说,应该都是前台pc版的内容。但是事实上,thinkcmf
的后台页面中,也是有几个页面(内容管理)功能是调用的/portal/
开头的地址。苏南大叔认为:这个是thinkcmf
代码构架本身的问题。修复的方案,在后面的文章中,苏南大叔会做相关介绍。
作为最简单弱智的方案来说,nginx里面就暂时对于/portal/
开头的请求,不做任何拦截处理了。否则,后台中的一些功能是不能使用的,具体表现就是:后台的文章内容管理模块。
第二个方案:近乎完美版方案
针对上一个方案中,页面的地址栏会一直存在/<模块名称>/
的弊端。对于这个对象广大用户的手机版来说,这样似乎是不妥当的,所以在这里,苏南大叔提出了一个新的方案,近乎完美,但是为了兼容模板里面资源文件的写法,需要修改thinkcmf
的一个核心文件。当然,苏南大叔认为,这个也许是thinkcmf
的一个小小bug。
/public/m.php
的代码如下:
define('BIND_MODULE','m');
require_once "index.php";
手机版网站的nginx
配置如下,仅仅写出个关键点,其余配置请参考pc版的nginx配置内容。
server{
server_name <手机版的域名>;
// ...
location / {
index m.php;
if (!-e $request_filename){
rewrite ^/(.*)$ /m.php/$1; //注意这里
}
}
location ^~ /portal/ {
rewrite ^(.*)$ http://<pc站的域名>/$1 permanent;
}
location ^~ /admin/ {
deny all;
}
# ...
}
这里,/public/m.php
全权负责起入口文件的责任,替代了/public/index.php
文件的存在。当然出于代码复用角度来看,苏南大叔include
了index.php
。其实,主要的作用点就是下面这句话,指定了这个入口文件m.php
的对应的模块的是m
。
define('BIND_MODULE','m');
在nginx配置中,注意:除了默认首页配置为m.php
外,所有的不存在实体文件的请求,也都由m.php
来处理。这样配置之后,访问页面,会出现很多的404错误。模板中常用的变量,比如__STATIC__
也会被替换成显然有错误的/m.php/static/
,而不是期待的/static/
。注意,第一种方案是没有这个问题的,因为所有文件还是由/public/index.php
处理的。
不细说调试过程,说一下解决方案。就是修改thinkcmf的内核文件。请找到如下内核文件:/<framework目录>/cmf/common.php
,切换到函数cmf_get_root()
。
修改前的cmf_get_root()
函数:
function cmf_get_root()
{
$request = Request::instance();
$root = $request->root();
$root = str_replace('/index.php', '', $root);
if (defined('APP_NAMESPACE') && APP_NAMESPACE == 'api') {
$root = preg_replace('/\/api$/', '', $root);
$root = rtrim($root, '/');
}
return $root;
}
苏南大叔修改后的cmf_get_root()
函数:
function cmf_get_root()
{
$request = Request::instance();
$root = $request->root();
//$root = str_replace('/index.php', '', $root);
//主要是入口文件不是index.php的话,就出各种问题了.....
$root = dirname($root);
if (defined('APP_NAMESPACE') && APP_NAMESPACE == 'api') {
$root = preg_replace('/\/api$/', '', $root);
}
$root = rtrim($root, '/');
return $root;
}
这样修改这个内核文件后,就可以愉快的新增新的入口文件,并且可以愉快的使用__STATIC__
等系统常量了。perfect~
结论
这两种新增入口文件的方案,一个简单一个完美。根据您的实际情况。选择一个即可。本文的内容,较为高级。一般来说,不会有这么高级的需求的。对吧?最终的结果就是:三个入口文件,对应于三个不同域名。访问不同的域名的时候,显示的内容是完全不一样的。
更多thinkcmf的经验文章,请点击这里查看:https://newsn.net/tag/thinkcmf/ 。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。