Subdomaining with Cake
In this article, following a practical approach to subdomaining, we will make one model available through subdomains. Can be inspiring for alternative uses.
Inspired by the Hosting Admin URLs on a Subdomain at http://bakery.cakephp.org/articles/view/hosting-admin-urls-on-a-subdomain, I have tried to come up with some piece of code that makes uses of subdomains in an elegant way.
The aim is to access all instances of a model through subdomains. For instance, every user may have their subdomains, accessible at username.example.com
In order to deal with this, I assume that you already made the necessary implementations in your controller. Some sample code would look like (user_controller.php) :
Download code
Also, you need to route your users model at app/config/routes.php with something like:
Download code
Now, what we will actually do is run some piece of code before the MVC implementation is started. The correct place to do this is the app/config/bootsrap.php
bootstrap.php : Download code
This piece of code is pretty self explanatory. if the subdomain is different than "www", the page displayed is users//. So, mumchamber.example.com/about is actually displaying the url www.example.com/users/mumchamber/about
To test subdomains on localhost, you may want to have a look at http://digitalpbk.blogspot.com/2007/01/making-subdomains-on-localhost.html Only remember that in linux, your hosts file is probably located at /etc/hosts
Also, you may want to see http://httpd.apache.org/docs/1.3/vhosts/ for virtual host documentation
The aim is to access all instances of a model through subdomains. For instance, every user may have their subdomains, accessible at username.example.com
In order to deal with this, I assume that you already made the necessary implementations in your controller. Some sample code would look like (user_controller.php) :
Download code
function view($unique_title){
$this->set('users', $this->User->findByUniqueTitle($unique_title) );
}
Also, you need to route your users model at app/config/routes.php with something like:
Download code
Router::connect('/user/*', array('controller' => 'user', 'action' => 'view'));
Now, what we will actually do is run some piece of code before the MVC implementation is started. The correct place to do this is the app/config/bootsrap.php
bootstrap.php : Download code
$subdomain = substr( env("HTTP_HOST"), 0, strpos(env("HTTP_HOST"), ".") );
if( strlen($subdomain)>0 && $subdomain != "www" ) {
$_GET["url"] = "user/" . $subdomain . "/" . (isset($_GET["url"]) ? $_GET["url"] : "");
}
This piece of code is pretty self explanatory. if the subdomain is different than "www", the page displayed is users/
To test subdomains on localhost, you may want to have a look at http://digitalpbk.blogspot.com/2007/01/making-subdomains-on-localhost.html Only remember that in linux, your hosts file is probably located at /etc/hosts
Also, you may want to see http://httpd.apache.org/docs/1.3/vhosts/ for virtual host documentation
Comments
Comment
1 maybe htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?(([a-z0-9_-]{1,100})\.)?example\.com$
RewriteRule ^(.*)$ /users/%3/about [L]
Regards
Comment
2 Why not htaccess
Comment
3 Thanks
$url_parts = explode('.', env('HTTP_HOST'));
foreach($url_parts as $part) {
if(!in_array($part, array('www', 'example', 'com'))) {
$ident = $part;
}
}
Comment
4 Nice idea for social sites
i think it will help me a lot on my 'blogging' project.
currently, i am working on a 'social bookmarking' project. will try to implement your code so that users bookmarks can be accessed from user.sitename.com ;)
Comment
5 nice article
Question
6 Named parameters with this approach to subdomaining
However, when I introduce named parameters - I immediately get a 403 Permission Denied from Apache. This is odd because if I directly access the controller/view/ in the URL even ith the named parameters it works fine.
Thus, I have set things up according to this article such that:
http://username.localhost/cakejunction/ essentially goes to:
http://localhost/cakejunction/partners/username/load/
Works great. However, If I add named parameters to the URL like this:
http://username.localhost/cakejunction/p1:page1/p2:value2 I immediately get a 403 - Permission Denied from Apache.
What is interesting, is if I use the direct equivalent URL that this would have translated into:
http://localhost/cakejunction/partners/username/load/p1:page1/p2:value2
It works fine.
So - I conclude that it is likely some combination of the subdomaining mechanism, the named parameters with colons and the Apache configuration.
WinXP
PHP5
Apache 2
Cake 1.2
Question
7 do I have to create subdomains individually
Thanks
Comment
8 Use wildcard subdomain
Comment
9 my version
preg_match('/^(?:www\.)?(?:(.+)\.)?(.+\..+)$/i', env('HTTP_HOST'), $matches);
define('SUBDOMAIN',empty($matches[1])?false:$matches[1]);
define('HOST',$matches[2]);
define('BASE_URL','http://'.HOST);
if(SUBDOMAIN) $_GET['url'] = 'users/view/'.SUBDOMAIN.(isset($_GET['url'])?'/'.$_GET['url']:'');
It works with or without www. in front of the URL. It also snags the HOST (without subdomain) because you're probably going to want to use it around the site to remove the subdomain from your links when you don't need it.