使用.htaccess (PHP)动态创建子域名

我期待创建一个系统,在注册将创建一个子域名在我的网站的用户帐户区域。

例如 johndoe.website.example

我认为这将是一些与 .htaccess文件,并可能重定向到网站上的另一个位置?我也不知道。不过,如果能提供一些有用的信息,我将不胜感激。

创建一个注册区域不是问题-我已经这样做了很多次。我只是不确定从哪里开始的子域。

67806 次浏览

It's nothing to do with .htaccess. You'll need to set up DNS records and virtual hosting for the subdomains.

你可以首先允许每个子域,然后检查子域是否有效。例如:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+\.example\.com$
RewriteRule !^index\.php$ index.php [L]

index.php内部,您可以使用以下方法提取子域:

if (preg_match('/^([^.]+)\.example\.com$/', $_SERVER['HTTP_HOST'], $match)) {
var_dump($match[1]);
}

但是所有这些都要求你的网络服务器接受每个子域名。

简要说明一下

  1. 您需要在 DNS 服务器 *.website.example上创建通配符域
  2. 然后在 vhost 容器中,您需要指定通配符以及 *.website.example-这是在 ServerAlias < sup > DOCs 中完成的
  3. 然后在 PHP 中提取和验证子域,并显示适当的数据

长话短说

1. 创建通配符 DNS 条目

在您的 DNS 设置中,您需要创建一个 通配符域入口通配符域入口,如 *.example.org。通配符条目如下:

*.example.org.   3600  A  127.0.0.1

2. 在 vhost 中包含通配符

在 Apache 配置中,接下来需要设置一个 vhost 容器,该容器在 ServerAlias < sup > DOCs 指令中指定通配符。Vhost 容器示例:

<VirtualHost *:80>
ServerName server.example.org
ServerAlias *.example.org
UseCanonicalName Off
</VirtualHost>

3. 找出你在 PHP 中的子域名

Then in your PHP scripts you can find out the domain by looking in the $_SERVER super global variable. Here is an example of grabbing the subdomain in PHP:

preg_match('/([^.]+)\.example\.org/', $_SERVER['SERVER_NAME'], $matches);
if(isset($matches[1])) {
$subdomain = $matches[1];
}

我在这里使用正则表达式,以允许人们通过 www.subdomain.example.orgsubdomain.example.org访问您的网站。

如果您从来没有预料到必须处理 www。(或其他子域) ,然后你可以像这样简单地使用子字符串:

$subdomain = substr(
$_SERVER['SERVER_NAME'], 0,
strpos($_SERVER['SERVER_NAME'], '.')
);

大规模虚拟主机

大规模虚拟主机是一个略有不同的方案,以上,因为你通常会使用它托管许多不同的网站,而不是试图使用它的电源应用程序的问题建议。

我已经在 发表在我的博客上中记录了我的基于 mod _ rewrite 的大规模虚拟主机环境,如果您希望采用这种方式,您可以查看 发表在我的博客上。当然,还有 各自的 Apache 手册页

Apache 还有一种处理大规模虚拟主机的内部方法,它的灵活性略低于我使用的 mod _ rewrite 方法。这在 Apache Dynamically Configured Mass Virtual Hosting manual page中都有描述。

除了设置 DNS 通配符之外,您可能还想了解一下 面向 Apache 的动态大规模虚拟主机,这是我过去解决这个问题的方法

我认为通配符 DNS 与 Apache 的动态大规模虚拟主机也是一个合理的解决方案。虽然我从没试过。

如果您需要扩展到多个服务器,或者其他解决方案不适合您,我建议使用数据库驱动的 DNS 服务器。我曾经成功地使用过 MyDNS。因为它使用 MySQL (或 PostgreSQL) ,所以您可以使用 PHP 或其他任何东西动态更新 DNS。这段代码看起来不像是已经更新了一段时间,但它是 DNS,因此并不完全是最新的。

The easiest way is to redirect all subdomains (with wildcard *) to point to your /wwwroot. Then put .htaccess to this folder with the following code:

RewriteCond %{ENV:REDIRECT_SUBDOMAIN} =""
RewriteCond %{HTTP_HOST} ^([a-z0-9][-a-z0-9]+)\.domain\.example\.?(:80)?$ [NC]
RewriteCond %{DOCUMENT_ROOT}/%1 -d
RewriteRule ^(.*) %1/$1 [E=SUBDOMAIN:%1,L]
RewriteRule ^ - [E=SUBDOMAIN:%{ENV:REDIRECT_SUBDOMAIN},L]

这将实现通过子域(foldername.domain.example)在可接受的/wwwroot 文件夹的每个子文件夹。

这是几年前发现的 Http://www.webmasterworld.com/apache/3163397.htm

Mod _ vhost _ alias 是执行此操作的正确模块。

With one line you can tell Apache to look at the right place, with directory hashing, etc. 例如,这句话:

VirtualDocumentRoot /http/users/%3.1/%3.2/%3

将告诉 Apache 在请求 subdomain.yourdomain.example时将文档根设置为 /http/users/s/u/subdomain

我发现用 PHP 做起来更容易。实际上是在 cPanel 中创建一个子域,并在所需的域名下创建文件夹。正如您将在 cPanel 中手动执行的那样,但所有这些都是通过一个简单的 PHP 函数在毫秒内完成的。无需点击:)

function create_subdomain($subDomain,$cPanelUser,$cPanelPass,$rootDomain) {


//  $buildRequest = "/frontend/x3/subdomain/doadddomain.html?rootdomain=" . $rootDomain . "&domain=" . $subDomain;


$buildRequest = "/frontend/x3/subdomain/doadddomain.html?rootdomain=" . $rootDomain . "&domain=" . $subDomain . "&dir=public_html/subdomains/" . $subDomain;


$openSocket = fsockopen('localhost',2082);
if(!$openSocket) {
return "Socket error";
exit();
}


$authString = $cPanelUser . ":" . $cPanelPass;
$authPass = base64_encode($authString);
$buildHeaders  = "GET " . $buildRequest ."\r\n";
$buildHeaders .= "HTTP/1.0\r\n";
$buildHeaders .= "Host:localhost\r\n";
$buildHeaders .= "Authorization: Basic " . $authPass . "\r\n";
$buildHeaders .= "\r\n";


fputs($openSocket, $buildHeaders);
while(!feof($openSocket)) {
fgets($openSocket,128);
}
fclose($openSocket);


$newDomain = "http://" . $subDomain . "." . $rootDomain . "/";


//  return "Created subdomain $newDomain";


}

通配符子域创建方法

FIrst you have to create the DNS settings using your server DNS editor.

  1. 使用服务器 IP 地址中的主机 *通配符在 DNS 设置中创建 A记录。

    * 1400 IN A ip_address

  2. 再次创建一个 A记录在 DNS 设置与主机 @domainname.example在服务器 IP 地址。Tld 表示顶级域或域的扩展,例如。来吧。组织,等等。

    @ 1400 IN A ip_address 或者 domainname.example 1400 IN A ip_address

  3. 创建如下 CNAME记录:

    www 1400 IN A domainname.example

  4. 使用 *通配符(如 *.domainname.example)创建子域

  5. *.domainname.example的子域目录中创建 .htaccess,并将以下代码放入:

     Options +FollowSymLinks
    RewriteEngine On
    RewriteBase /
    RewriteRule ^([aA-zZ0-9]+)$ index.php?data=$1
    RewriteCond %{HTTP_HOST} ^([aA-zZ0-9]+)\.([aA-zZ0-9-]+)\.([aA-zZ]+)
    RewriteRule ([aA-zZ0-9]+) index.php?data=%1
    

测试您的第一个通配符子域,如 some.domainname.example

If you are not interest to pass the data as parameter using the .htaccess, you can also get the data by using the following coding:

define("SUBDOMAIN_PARENT","domainname.example");
class getData
{
function __construct()
{
$this->data="";
$http_host=$_SERVER['HTTP_HOST'];
$subdom_data= str_replace(SUBDOMAIN_PARENT,"",$http_host);
$expl_subdom_data=explode(".",$subdom_data);
$expl_subdom_data=array_filter($expl_subdom_data);


if($expl_subdom_data!=NULL)
{
$this->data=end($expl_subdom_data);
}
}
}
$GLOBALS['get_data']=new getData();

并在任何地方使用全局变量,如 global $get_data

echo $get_data->data; //example

(注意: 这个类主要用于从 http_host获取确切的子域名。因为一些额外的名字组合之前,你的子域也适用于像 www.some.domainname.example。这个返回 $_GET['data']='wwww'所以我的建议是使用 $_SERVER['http_host']来获得准确的值,而不是使用 $_SERVER['query_string']或在索引页中传递的 .htaccess参数)

6. 在 TTL-DNS 设置中使用 N 秒来加速这个通配符子域的执行。

在给定的 ttl 时间(600-10分钟)后检查子域,如 = > http://abc.domainname.example

(注意: 通配符子域不覆盖现有的子域。因为第一优先级总是为您现有的子域)