我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

一般来说,正常的thinkphp项目都会有多个模块,包括:面向用户的pc版网站,面向用户的m版网站,面向管理员的用户界面。在项目实际上线后,这些模块往往会要求有不同的域名,比如:pc版和手机版不同域名,后台管理要单独的域名。在代码层面,这些不同的域名上线部署,需要我们做些额外的配置。

苏南大叔:thinkcmf高级应用之多模块自定义域名及入口文件 - thinkcmf-domain
thinkcmf高级应用之多模块自定义域名及入口文件(图2-1)

在本文中,苏南大叔将以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地址一般不敏感。所以,这个小问题是可以忽略不计的。

苏南大叔:thinkcmf高级应用之多模块自定义域名及入口文件 - 后台分支域名
thinkcmf高级应用之多模块自定义域名及入口文件(图2-2)

/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文件的存在。当然出于代码复用角度来看,苏南大叔includeindex.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/

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php    thinkphp