使用 .htaccess (PHP) 即时创建子域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/586129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create subdomains on the fly with .htaccess (PHP)
提问by Ben McRae
I am looking to create a system which on signup will create a subdomain on my website for the users account area.
我希望创建一个系统,该系统在注册时将在我的网站上为用户帐户区域创建一个子域。
e.g. johndoe.website.com
例如 johndoe.website.com
I think it would be something to do with the .htaccess file and possibly redirecting to another location on the website? I don't actually know. But any information to start me off would be greatly appreciated.
我认为这与 .htaccess 文件有关,并可能重定向到网站上的另一个位置?我其实不知道。但任何让我开始的信息将不胜感激。
Creating a sign up area is not the problem - I have done this many a time. I am just unsure where to start with the subdomain.
创建注册区不是问题 - 我已经做过很多次了。我只是不确定从哪里开始使用子域。
回答by Treffynnon
The quick rundown
快速破败
- You need to create a wildcard domain on your DNS server *.website.com
- Then in your vhost container you will need to specify the wildcard as well *.website.com - This is done in the
ServerAliasDOCs - Then extract and verify the subdomain in PHP and display the appropriate data
- 您需要在您的 DNS 服务器上创建一个通配符域 *.website.com
- 然后在您的 vhost 容器中,您还需要指定通配符 *.website.com - 这是在DOC 中完成的
ServerAlias - 然后在PHP中提取并验证子域并显示相应的数据
The long version
长版
1. Create a wildcard DNS entry
1. 创建通配符 DNS 条目
In your DNS settings you need to create a wildcard domain entrysuch as *.example.org. A wildcard entry looks like this:
在您的 DNS 设置中,您需要创建一个通配符域条目,例如*.example.org. 通配符条目如下所示:
*.example.org. 3600 A 127.0.0.1
2. Include the wildcard in vhost
2.在vhost中包含通配符
Next up in the Apache configuration you need to set up a vhost container that specifies the wildcard in the ServerAliasDOCsdirective. An example vhost container:
接下来在 Apache 配置中,您需要设置一个 vhost 容器,该容器在ServerAliasDOCs指令中指定通配符。一个示例 vhost 容器:
<VirtualHost *:80>
ServerName server.example.org
ServerAlias *.example.org
UseCanonicalName Off
</VirtualHost>
3. Work out which subdomain you are on in PHP
3. 找出你在 PHP 中的子域
Then in your PHP scripts you can find out the domain by looking in the $_SERVERsuper global variable. Here is an example of grabbing the subdomain in PHP:
然后在您的 PHP 脚本中,您可以通过查看$_SERVER超级全局变量来找出域。这是在 PHP 中抓取子域的示例:
preg_match('/([^.]+)\.example\.org/', $_SERVER['SERVER_NAME'], $matches);
if(isset($matches[1])) {
$subdomain = $matches[1];
}
I have used regex here to to allow for people hitting your site via www.subdomain.example.org or subdomain.example.org.
我在这里使用了正则表达式来允许人们通过 www.subdomain.example.org 或 subdomain.example.org 访问您的网站。
If you never anticipate having to deal with www. (or other subdomains) then you could simply use a substring like so:
如果您从未预料到必须处理 www. (或其他子域)然后您可以简单地使用子字符串,如下所示:
$subdomain = substr(
$_SERVER['SERVER_NAME'], 0,
strpos($_SERVER['SERVER_NAME'], '.')
);
Mass Virtual Hosting
海量虚拟主机
Mass virtual hosting is a slightly different scheme to the above in that you would usually use it to host many distinct websites rather than attempting to use it power an application as the question proposes.
大规模虚拟主机与上述方案略有不同,因为您通常会使用它来托管许多不同的网站,而不是像问题所建议的那样尝试使用它来为应用程序提供动力。
I have documented my mod_rewrite based mass virtual hosting environment before in a post on my blog, which you could look at if that is the route you wish to take. There is also, of course, the respective Apache manual page.
我之前在我的博客上的一篇文章中记录了我的基于 mod_rewrite 的大规模虚拟托管环境,如果这是您希望采取的路线,您可以查看。当然,还有相应的 Apache 手册页。
Apache also has an internal way of dealing with mass virtual hosting that is slightly less flexible than the mod_rewrite method I have used. This is all described on the Apache Dynamically Configured Mass Virtual Hosting manual page.
Apache 也有一种处理大量虚拟主机的内部方法,它比我使用的 mod_rewrite 方法稍微不那么灵活。这一切都在 Apache动态配置的大规模虚拟主机手册页上进行了描述。
回答by Gumbo
You could allow every subdomain in the first place and then check if the subdomain is valid. For example:
您可以首先允许每个子域,然后检查子域是否有效。例如:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+\.example\.com$
RewriteRule !^index\.php$ index.php [L]
Inside the index.phpyou can than extract the subdomain using:
在里面,index.php您可以使用以下方法提取子域:
if (preg_match('/^([^.]+)\.example\.com$/', $_SERVER['HTTP_HOST'], $match)) {
var_dump($match[1]);
}
But all this requires that your webserver accepts every subdomain name.
但这一切都要求您的网络服务器接受每个子域名。
回答by Rowland Shaw
In addition to setting up a DNS wildcard, you might want to take a look at Dynamic Mass Virtual Hosting for Apachewhich is how I've solved this in the past
除了设置 DNS 通配符之外,您可能还想看看Dynamic Mass Virtual Hosting for Apache这就是我过去解决这个问题的方法
回答by Glavi?
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:
最简单的方法是将所有子域(使用通配符 *)重定向到您的 /wwwroot。然后使用以下代码将 .htaccess 放入此文件夹:
RewriteCond %{ENV:REDIRECT_SUBDOMAIN} =""
RewriteCond %{HTTP_HOST} ^([a-z0-9][-a-z0-9]+)\.domain\.com\.?(:80)?$ [NC]
RewriteCond %{DOCUMENT_ROOT}/%1 -d
RewriteRule ^(.*) %1/ [E=SUBDOMAIN:%1,L]
RewriteRule ^ - [E=SUBDOMAIN:%{ENV:REDIRECT_SUBDOMAIN},L]
This will accomplish that every subfolder of the /wwwroot folder in acceptable via subdomain (foldername.domain.com).
这将通过子域 (foldername.domain.com) 实现 /wwwroot 文件夹中的每个子文件夹。
Found this years ago on http://www.webmasterworld.com/apache/3163397.htm
回答by Adrian P.
I found it easier doing it with PHP. In fact is creating a subdomain within cPanel and create your folder under the desired domain name. As you will do it manually in cPanel but all it's done in milliseconds by a simple PHP function. No click necessary :)
我发现用 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";
}
回答by Julien Tartarin
Mod_vhost_aliasis the right module to do this.
Mod_vhost_alias是执行此操作的正确模块。
With one line you can tell Apache to look at the right place, with directory hashing, etc. For example, the line:
通过一行,您可以告诉 Apache 查看正确的位置,包括目录散列等。例如,该行:
VirtualDocumentRoot /http/users/%3.1/%3.2/%3
would tell Apache to set the document root to /http/users/s/u/subdomain when requested for subdomain.yourdomain.com
当请求 subdomain.yourdomain.com 时,会告诉 Apache 将文档根目录设置为 /http/users/s/u/subdomain
回答by chaos
It's nothing to do with .htaccess. You'll need to set up DNS records and virtual hosting for the subdomains.
与 .htaccess 无关。您需要为子域设置 DNS 记录和虚拟主机。
回答by Barrett Conrad
I think the wild card DNS with Apache's Dynamic Mass Virtual Hosting is a reasonable solution also. Although, I have never tried it.
我认为带有 Apache 动态大规模虚拟主机的通配符 DNS 也是一个合理的解决方案。虽然,我从来没有尝试过。
If you have the need to scale out to multiple servers or the other solutions just don't work for you, I recommend using a database driven DNS server. I have successfully used MyDNSin the past. Since it uses MySQL (or PostgreSQL) you can update your DNS on the fly with PHP or just about anything else. The code doesn't look like it has been updated in a while, but it's DNS and therefore not exactly cutting edge.
如果您需要扩展到多台服务器或其他解决方案对您不起作用,我建议您使用数据库驱动的 DNS 服务器。我过去曾成功使用过MyDNS。由于它使用 MySQL(或 PostgreSQL),因此您可以使用 PHP 或其他任何东西即时更新您的 DNS。该代码看起来好像已经有一段时间没有更新了,但它是 DNS,因此并不是最前沿的。
回答by karthikeyan ganesan
Wildcard subdomain creation methods
通配符子域创建方法
FIrst you have to create the DNS settings using your server DNS editor.
首先,您必须使用服务器 DNS 编辑器创建 DNS 设置。
Create
Arecord in DNS settings with host*wild card in server ip address.* 1400 IN A ip_addressCreate once again a
Arecord in DNS settings with host@ordomain_name.tldin server ip address. tld means top level domains or the extension of the domains such as .com, .org, etc....@ 1400 IN A ip_addressordomain_name.tld 1400 IN A ip_addressCreate
CNAMErecord like:www 1400 IN A domainname.tld- Create the subdomain with
*wildcard like*.domain.tld Create htaccess in your subdomain directory of
*.domain.tldand put this code :Options +FollowSymLinks RewriteEngine On RewriteBase / RewriteRule ^([aA-zZ0-9]+)$ index.php?data= RewriteCond %{HTTP_HOST} ^([aA-zZ0-9]+)\.([aA-zZ0-9-]+)\.([aA-zZ]+) RewriteRule ([aA-zZ0-9]+) index.php?data=%1Test your first wildcard subdomain like
example.domainname.tld
在服务器 ip 地址中
A使用主机*通配符在 DNS 设置中创建记录。* 1400 IN A ip_addressA使用主机@或domain_name.tld服务器 IP 地址在 DNS 设置中再次创建记录。tld 表示顶级域或域的扩展名,例如 .com、.org 等......@ 1400 IN A ip_address或者domain_name.tld 1400 IN A ip_address创建
CNAME记录,如:www 1400 IN A domainname.tld- 使用
*通配符创建子域,例如*.domain.tld 在您的子域目录中创建 htaccess
*.domain.tld并放置以下代码:Options +FollowSymLinks RewriteEngine On RewriteBase / RewriteRule ^([aA-zZ0-9]+)$ index.php?data= RewriteCond %{HTTP_HOST} ^([aA-zZ0-9]+)\.([aA-zZ0-9-]+)\.([aA-zZ]+) RewriteRule ([aA-zZ0-9]+) index.php?data=%1测试您的第一个通配符子域,例如
example.domainname.tld
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:
如果您不想使用 htaccess 将数据作为参数传递,您还可以使用以下编码获取数据:
define("SUBDOMAIN_PARENT","domainname.tld");
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();
and use your global variable at any place like global $get_data.
并在任何地方使用您的全局变量,例如global $get_data.
echo $get_data->data; //example
(note: This class mainly used for get the exact subdomainname from http_host. because some extra names combined before your subdomain is also applicable like www.example.domainname.tld. This return $_GET['data']='wwww'So my suggestion is to use the $_SERVER['http_host']for get the exact values instead of using the $_SERVER['query_string']or passed htaccess parameters in your index page)
(注:这个类主要用于得到确切的SUBDOMAINNAMEhttp_host因为一些额外的名字您的子之前合并也适用等。www.example.domainname.tld这种回报。$_GET['data']='wwww'所以我的建议是使用$_SERVER['http_host']为得到确切的值,而不是使用$_SERVER['query_string']或通过htaccess的参数您的索引页)
6.Speed up the execution of this wildcard subdomains use N seconds in TTL - DNS SETTINGS.
6.加速此通配符子域的执行在TTL - DNS SETTINGS中使用N秒。
7.Check the subdomain after your given ttl time (600 - 10 minutes) like => http://abc.domain.tld
7.在给定的 ttl 时间(600 - 10 分钟)后检查子域,例如 => http://abc.domain.tld
(note: wildcard subdomains not override the existed subdomains. Because First priority always for your existed subdomains)
(注意:通配符子域不会覆盖现有的子域。因为您现有的子域始终是第一优先级)

