Create subdomains on the fly with .htaccess (PHP)
The quick rundown
- You need to create a wildcard domain on your DNS server
*.website.example
- Then in your vhost container you will need to specify the wildcard as well
*.website.example
- This is done in theServerAlias
DOCs - Then extract and verify the subdomain in PHP and display the appropriate data
The long version
1. Create a wildcard DNS entry
In your DNS settings you need to create a wildcard domain entry such as *.example.org
. A wildcard entry looks like this:
*.example.org. 3600 A 127.0.0.1
2. Include the wildcard in vhost
Next up in the Apache configuration you need to set up a vhost container that specifies the wildcard in the ServerAlias
DOCs directive. An example vhost container:
<VirtualHost *:80>
ServerName server.example.org
ServerAlias *.example.org
UseCanonicalName Off
</VirtualHost>
3. Work out which subdomain you are on in 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];
}
I have used regex here to to allow for people hitting your site via www.subdomain.example.org
or subdomain.example.org
.
If you never anticipate having to deal with www. (or other subdomains) then you could simply use a substring like so:
$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.
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.
Can I dynamically create subdomains (PHP, .htaccess) with GoDaddy Hosting?
DNS is only 1 part of the configuration. You need to have a ServerAlias for *.mydomain.com in the configuration for the virtual host in Apache, otherwise Apache will not have any idea where to route requests for *.mydomain.com - which means the .htaccess never has a chance to work at all.
If GoDaddy provides a way to manually edit your virtual hosts' directives, or at least the ability to add server aliases through their GUI, then it's easy enough. If you can't find it, you should contact GoDaddy for information.
Creating subdomains on the fly
In a nutshell:
- Create a wildcard domain in DNS (i.e., resolving whatever.yourdomain.example returns your IP),
- create a default virtual host in your web server and
- check the URL in your application.
How to do this depends on what technology you use. Let me give you some examples:
- How to set up a wildcard domain in BIND and in Windows Server DNS.
- To create a default virtual host, you just need to create a web server without a host entry in IIS. In Apache, the first virtual host listed in the configuration file becomes the default host.
- Here, you can either (a) rewrite the URL depending on the domain (i.e., converting the subdomain into a parameter in the URL, example for ASP.NET, examples for Apache with mod_rewrite: Link1, Link2), or (b) just have a look at the host part of the URL (e.g.
Request.Url
in ASP.NET).
Addition by bortzmeyer (sorry for overwriting your edit, there was an edit conflict):
The syntax for a wildcard, in the usual DNS zone file format (described in RFC 1035 and implemented in BIND, nsd and may be others) is with a star:
* IN A 198.51.100.3
Create subdomains on the fly with info from database
I presuppose that you setup a wildcard dns entry (access random.domain.tld to test it!). Then you have two options:
Correct your rewrite rules
Something like [aA-zZ]
should be [a-zA-Z]
and the RewriteRule
should be only after the RewriteCond
and not in front of it and two of them. And do you really want to force a -
inside the subdomain with ([a-z0-9][-a-z0-9]+)
? Maybe you should check this answer. Note: The www
inside of your domain is a subdomain as well. So it would rewrite to sub.php?url=www
With the corrected rewriting random.domain.tld
returns the content of random.domain.tld/sub.php?url=random
. But at the moment your sub.php does not return content. Instead it returns a http redirect to the URL random.domain.tld
. This means your sub.php produces an infinite loop on itself. Instead sub.php should only contain something like <?php echo $_SERVER['HTTP_HOST']; ?>
.
Maybe you did not understand how URL rewriting works. Then read this answer for further explanation.
Update1
You corrected your code as follows:
RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9]+)\.domain\.tld\.?(:80)?$ [NC]
RewriteRule ([a-zA-Z0-9]+) /view.php?url=$1
But it's still wrong. As I said you need to read and understand this answer. @JoachimIsaksson uses $1
and %1
in his 2nd example:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ /subdomains/%1/$1 [L,NC,QSA]
%1
is the subdomain catched through RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com
. And $1
is the path catched through RewriteRule ^(.*)$
. You missed to use %1
.
But your code can not work as you forced an unempty alphanummeric string by RewriteRule ([a-zA-Z0-9]+)
. But a path could contain more than that. For example a slash or question mark. And of course it could be empty as well.
And why did you add (:80)?
? Do you think someone will access your domain with a specific port?
And why the last optional dot in tld\.?
?
At last you need to bring the flags into question. You used the NC flag. It means your rule is case-insensitive. So why do you use [a-zA-Z0-9]
? As your rule is already case-insensitive it can be [a-z0-9]
. And why don't you used the L and QSA flag? They are important.
Update2
Try this:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.tld
RewriteRule .* view.php?url=%1 [L,NC,QSA]
Use PHP only
$_SERVER['HTTP_HOST']
contains your full domain. This answer explains how to extract the subdomain name:
$subdomain = array_shift((explode('.', $_SERVER['HTTP_HOST'])));
Now you are able to use your general index.php to switch between your general page or the users subdomain content:
$domain_parts = explode('.', $_SERVER['HTTP_HOST']);
// access without any subdomain (TLDs like "co.uk" would "need == 4")
if (count(domain_parts) == 3) {
$subdomain = "www";
}
else {
$subdomain = array_shift($domain_parts);
}
if ($subdomain == 'www') {
// general page
}
else {
// users page
}
Related Topics
Is "MySQLi_Real_Escape_String" Enough to Avoid SQL Injection or Other SQL Attacks
How to Sum All Column Values in Multi-Dimensional Array
Using .Htaccess to Make All .Html Pages to Run as .PHP Files
Sort Array of Objects by One Property
Warning: a Non-Numeric Value Encountered
When Should I Use Prepared Statements
How to Encrypt/Decrypt Data in PHP
How to Get Numeric Types from MySQL Using Pdo
Using Braces With Dynamic Variable Names in PHP
Pdo Prepared Inserts Multiple Rows in Single Query
Difference Between Bindparam and Bindvalue
Create Subdomains on the Fly With .Htaccess (PHP)
Session Variables Not Working PHP
How to Extract Data from CSV File in PHP
How to Get a File Name from a Full Path With PHP
Curl Error 60: Ssl Certificate: Unable to Get Local Issuer Certificate