在 PHP 中重定向子域和域的非标准情况

Posted

技术标签:

【中文标题】在 PHP 中重定向子域和域的非标准情况【英文标题】:Not standard situation with redirecting subdomain and domain in PHP 【发布时间】:2012-04-13 03:54:48 【问题描述】:

伙计们!

我会解释我想做什么。如果有人可以帮助解决这个问题,请给一些建议。

我有一个网站,我们称之为http://mysite.com。还有子域,比如说http://myname.mysite.com。

有一个配置文件inc.php,其中包含mysite.com 和myname.mysite.com 的一些个人数据,例如ICQ 编号。位于 mysite.com 目录中的所有通用网站文件。

我希望能够在子域 myname.mysite.com 中创建 mysite.com 的所有常规文件,以免在子域中创建完全相似的文件。但包含单独的配置文件,位于 myname.mysite.com,包含单独的 ICQ 编号。

这是我希望它如何工作的示例:

    主域“mysite.com”的根文件夹“public_html”包含以下页面:index.php、about.php、articles.php 和配置文件 inc.php,icq 编号为“111-111”。因此,当服务“mysite.com”网站时,您会看到来自 inc.php 的 ICQ 编号。

    子域“myname.mysite.com”的文件夹“public_html/subdomain/myname”只有一个配置文件 inc.php,ICQ 编号为“222-222”。因此,当您访问 myname.mysite.com 时,您将看到来自“mysite.com”的网页,但 ICQ 编号将从此处获得“public_html/subdomain/myname/inc.php”。在地址栏中,您将看到网页: http://myname.mysite.com/index.php http://myname.mysite.com/about.php http://myname.mysite.com/articles.php

因此,访问者会认为他们在为个别网站 myname.mysite.com 提供服务,但实际上,访问者将在 mysite.com 网页上提供服务。因此,如果我更改 mysite.com 上的内容,此内容将更改为 myname.mysite.com。

我需要所有这些员工,因为我想组织会员计划,为我的合作伙伴提供个人子域名,但使用个人配置文件 inc.php,这将使用 ICQ 号码进行咨询。

我想我已经试图解释我想要做什么了。上帝,请努力解释这种情况。啊,忘了说,这都是我想在 PHP 上做的。

【问题讨论】:

【参考方案1】:

如果真的只有一个(或几个)微小的设置在子域之间是不同的,那么您可能应该考虑从同一个文档/Web 根目录为所有子域提供服务。通过调整您的虚拟主机配置来做到这一点。在 Apache 中,它看起来像这样(假设 NameVirtualHost *:80):

<VirtualHost *:80>
  ServerName mysite.com
  ServerAlias *.mysite.com
  DocumentRoot /var/www/websites/mysite
</VirtualHost>

然后在您的代码中,您可以使用子域确定要使用(或覆盖)哪些设置,这可能是这样确定的:

$domain = !empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
$subdomain = implode('.', explode('.', $domain, -2));

然后使用$subdomain 确定要使用的设置。

我不会提供示例代码来说明您如何确定在给定子域的情况下使用哪些设置,因为您的实现选择对您的需求非常主观。

编辑 - 回应 OP 在第一条评论中提出的问题

如果您绝对不能将ServerAlias *.mysite.com 放入您的虚拟主机配置中,那么可能仍然有一种简单的方法可以让事情以类似方式工作:使用符号链接作为文档/网络根目录。

因此,如果 myname.mysite.com 具有 /var/www/websites/myname.mysite.com 的文档/Web 根目录,而 mysite.com 具有 /var/www/websites/mysite.com 的文档/Web 根目录

然后使 /var/www/websites/myname.mysite.com 成为 Web 服务器上 /var/www/websites/mysite.com 的符号链接:

cd /var/www/websites/
ln -s mysite.com myname.mysite.com

这应该会导致 Apache 为 myname.mysite.com 使用/服务的文件来自服务器上与 mysite.com 相同的位置。

编辑 - 用于 cPanel

好的,我现在确信cPanel is lame。

如果您已经启用了 mod_proxy,您可以在每个根 .htaccess 中执行此操作

RewriteRule ^([^/]*)(/?)(.*) http://mysite.com/$1$2$3 [L,P]

当然,这甚至不考虑通过 https 进来的请求。您可以通过将所有请求定向到 myname.mysite.com 的 web/文档根目录中的符号链接来避免使用 mod_proxy,但这让我们回到了创建符号链接的问题。在文档/Web 根目录中获取符号链接可能比让文档/Web 根目录符号链接本身更容易。

我希望这能给你一些想法。似乎您需要做一些超出 cPanel 提供的操作才能让事情按您希望的方式工作。

【讨论】:

如果我使用共享主机会怎样?无权更改虚拟主机配置。可能还有另一种变体如何在PHP级别上实现它?可能是 htaccess 脚本? @ilnur777 查看我编辑的答案。如果您想向我提供有关您服务器上目录名称的详细信息,我可以更具体地定制答案。 我使用共享主机,我不能访问和更改任何服务器配置。子域将被创建太多。当我给出有问题的目录时,我有所有文件所在的目录“public_html”。所有子域都是使用 cPanel 在此目录“public_html/subdomain”中创建的。【参考方案2】:

如果您想要更改的唯一内容是 inc.php 文件,我建议对其进行稍微不同的结构(下面的代码假设只有 1 级子域,例如 subdomain.mysite.com,并在点上进行了一些修改(3 ) 和 (4) 将需要更深的子域,例如 sub.subdomain.mysite.com)。

1) 在您的 apache 虚拟主机配置中,将所有子域定义为主域的别名:

<VirtualHost *:80>
    ...

    SernarName mysite.com
    ServerAlias *.mysite.com

    ...
</VirtualHost>

2) 将所有子域的所有 PHP 文件放在一个目录中,并将 apache 配置指向该目录。

3) 在该目录中,创建一堆inc 文件:inc.phpinc-subdomain1.phpinc-subdomain2.php 等等。

4) 拥有某种config.php 文件,您可以从站点中的所有其他文件中包含该文件,并让它包含如下内容:

if(isset($_SERVER['HTTP_HOST'])) 
    $host = explode('.', strtolower($_SERVER['HTTP_HOST']));
    if(count($host) == 3)    //have something more than just mysite.com
        $subdomain = $host[0];
        if($subdomain == 'www')      //www.mysite.com is the same as just mysite.com
            $subdomain == '';
        
    
    else       //if just mysite.com, then no subdomains
        $subdomain = '';
    

else   //if no http_host info exists, then assume it's just mysite.com
    $subdomain = '';


$incfile = 'inc' . ($subdomain == '' ? '' : "-$subdomain") . '.php';
if(!file_exists($incfile))     //if no include file for the requested subdomain, just use mysite.com
    $incfile = 'inc.php';


require_once($incfile);

现在,所有这些当然会给您很大的灵活性,但如果您只需要不同的 ICQ 号码,则可能没有必要。在这种情况下,我会将第 (4) 点的代码更改为只有 1 个包含文件,例如 inc.php,并且在该文件中有如下内容:

$icq_default = '111-111';
$icq_nums = array('subdomain1' => '222-222',
                  'subdomain2' => '333-333',
                  ...);

if(isset($_SERVER['HTTP_HOST'])) 
    $host = explode('.', strtolower($_SERVER['HTTP_HOST']));
    if(count($host) == 3)    //have something more than just mysite.com
        $subdomain = $host[0];
        if($subdomain == 'www')      //www.mysite.com is the same as just mysite.com
            $subdomain == '';
        
    
    else       //if just mysite.com, then no subdomains
        $subdomain = '';
    

else   //if no http_host info exists, then assume it's just mysite.com
    $subdomain = '';


$required_number = isset($icq_numbers[$subdomain]) ? $icq_numbers[$subdomain] : $icq_default;

【讨论】:

我在阅读你的答案之前发布了我的答案。确保(尤其是对于我确信的 OP)注意到我们提出了非常相似的方法。 @ghbarratt 是的,确实是一样的。 @Aleks G 如果我使用共享主机会怎样?无权更改虚拟主机配置。可能还有另一种变体如何在PHP级别上实现它?可能是 htaccess 脚本? @ilnur777 那么你是如何为子域设置目录的呢?这是 unix/linux 主机还是 windows 主机? @Aleks G,它是一个 Linux 主机。我有所有文件所在的目录“public_html”。所有子域都是在此目录“public_html/subdomain”中使用 cPanel 创建的

以上是关于在 PHP 中重定向子域和域的非标准情况的主要内容,如果未能解决你的问题,请参考以下文章

不要在 htaccess 中重定向子域

301 在 Django 中重定向 www 子域

301从主域(www和非www)重定向到子域

.htaccess - 将旧网站重定向到主域,但也将一些内容重定向到主域的子域

在 Laravel 中重定向域名

在win32中重定向标准输出不会重定向标准输出