24

This seems like a common request, but I haven't been able to find definitive instructions on doing something like this.

I'd like a subdomain to trigger a certain controller on my CI installation. For example:

students.mysite.com : would open mysite.com/students (technically: mysite.com/index.php/students. controller: students)

teachers.mysite.com : would open mysite.com/teachers

While preserving the subdomain when traversing deeper. For example:

students.mysite.com/help : would open mysite.com/students/help (controller: students(), method: help())

students.mysite.com/help/contact : would open mysite.com/students/help/contact (controller: students(), method: help(), argument: "contact")

students.mysite.com/help/contact/email : would open mysite.com/students/help/contact (controller: students(), method: help(), arguments: "contact", "email")

I realize that something.mysite.com right now returns an error. So I figure:

Step 1 would be allowing anything.mysite.com to return the root (mysite.com/index.php)

Step 2 would be reading the subdomain and calling that controller

Step 3 would be reading the first argument after the first "/" and calling that method of the controller, and passing the remaining url parts as arguments

I guess really I'm stumped at Step 1. I'm on a shared hosting account, is this something I can do via CPanel? I tried adding a subdomain for *.mysite.com without any luck (unless I just needed to wait longer for propogation, but I feel the chances are higher that I got it wrong).

Back on my home WAMP installation, I'd change up httpd.conf, right? Can I acheive this effect without modifying that file (since I probably can't, since I'm shared using webhostinghub.com)

Phew, thanks for your time! - Keith

Keith
  • 4,144
  • 7
  • 25
  • 43
  • Have you set up a wildcard dns for your domain? The Apache config is the other half of it. You need a CNAME or A record pointing all *.domain.com to your website. Google would help you here. – Ravi K Thapliyal Oct 22 '13 at 09:38
  • Thanks for the tip. I just set up a *.mysite.com CNAME record with a value of mysite.com. That will take care of step 1 right? It doesn't seem to be working yet, so I'm going to let it propogate then try again later – Keith Oct 22 '13 at 09:49
  • can't give you code off the top of my head, but your .htaccess should be able to rewrite the subdomains the way you like, I would think – jmadsen Oct 22 '13 at 10:09
  • Did you solve this? Your question is now the top result in Google for this particular topic. – Joel Murphy Jan 30 '14 at 15:11
  • Nope, not yet. I kind of gave up and we're hosting different sites on different servers. I'm leaving it open hoping someone'll know how to do this – Keith Feb 02 '14 at 03:39
  • @Prodikl Does your hosting support wildcard subdomains? That is the first step, not all shared hostings support redirecting *.something.com to another IP address. – Gustavo Rubio Feb 26 '14 at 20:30
  • Well, I can set up sub-domains, but I'm not sure about wildcard subdomains, I'll have to look into it! – Keith Feb 27 '14 at 07:18
  • @Prodikl You have to check that first... I already implemented a mapping between CodeIgniter and subdomains... so I know it works, but you have to make sure that your registrar (which may not be the same as your hosting provider) allows you to add a wildcard C Name (*.domain.com) so that anything that is under the .domain.com goes to a specific IP, then with apache you'll redirect everything to CI, finally in CI you'll catch the request subdomain. – Gustavo Rubio Feb 27 '14 at 23:09
  • May be help you http://stackoverflow.com/questions/19663849/htaccess-redirect-subdomain-to-folder – Lal krishnan S L Mar 01 '14 at 11:20

4 Answers4

36

As you want to use a particular domain to lead to your controllers, what I came up with was using the application/config/routes.php file to achieve it. The idea is load different controllers depending on what subdomain you use, so, instead of writing a list of routes for your domain, you write a list of routes DEPENDING on the domain you're accessing from:

switch ( $_SERVER['HTTP_HOST'] ) {
    case 'students.mysite.com':
        $route['default_controller'] = "students";
    break;
    case 'teachers.mysite.com':
        $route['default_controller'] = "teachers";
    default:
        // The list of your $routes lines at is was...
    break;
}

To make this work, you only have to point the subdomain to your CI project (Dwayne Towell in the step 1 of the other answer explains how to do it perfectly) and you'll have everything working, your shared hosting won't be a problem and you won't have to configure the server.

UPDATE

After reading this answer, check the answer from @Josh (https://stackoverflow.com/a/47368922/1168804) as it offers a wonderful way to organize the routing code to avoid unexpected routing behaviour with the controllers. It's worthy reading it (and upvoting it, ;D)

Federico J.
  • 15,388
  • 6
  • 32
  • 51
  • Damn, very smart solution to the problem. Thanks a lot! – Keith Feb 27 '14 at 00:36
  • 2
    No-touching a .htaccess file, and controllers exclusivity for subdomains, great answer. – jbltx Jul 29 '15 at 05:00
  • And this saved my lot of time :) Thanks alot. – Anand Singh Mar 09 '16 at 12:05
  • But you'll have issues between different `ENVIRONMENT`s... I am working on a perfect solution as this does not solve mine. – Ema4rl Jan 03 '17 at 02:24
  • @Ema4rl, at the end this is about routing. If you have several environments, the only thing that may happen is that you'll need something different that a switch (maybe an `in_array('dev.student.site.com', 'student.site.com') or even two `switch` and select which one you want to use depending on the environment. Or even better, create a Router class where you pass the domain and the environment and it returns automatically the controller. – Federico J. Feb 16 '17 at 10:34
  • Also from your hosting you should redirect from subdomain to public_html. – Riyad Khalifeh Apr 09 '20 at 16:29
4

Step 1: In CPanel, in Domains, in subdomains, add *.mysite.com (you only enter the * part) to redirect to /public_html/ (you enter nothing and/or delete wildcard) (or set this to whatever the current default value for www.mysite.com is currently.

Step 2 & 3: Use mod_rewrite to capture subdomain and move it to the "directory" part of the URL. I suspect it will be something like: (but I haven't tried it yet, RewriteLogLevel 9 is your friend)

RewriteEngine on
RewriteCond %{HTTP_HOST} ^([^\.]+)\.mysite\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/index.php/%1/$1 [L]

I also don't know if you can do the above using .htaccess. I have only done rewriting from httpd.conf.

Dwayne Towell
  • 8,154
  • 4
  • 36
  • 49
  • Thanks a lot for this write up. I tried something very similar but it didn't work last time. I'll try writing it the way you did and post back with results! – Keith Feb 26 '14 at 05:10
  • 1
    How do I modify this .htaccess snippet to allow www. prefix? – Erich García Sep 29 '16 at 02:06
4

In application/config/routes.php file, you need to write

$subDomains = array();
$subDomains['students.mysite.com'] = "student";
$subDomains['teachers.mysite.com'] = "teachers";

if(array_key_exists($_SERVER['HTTP_HOST'], $subDomains)) {
  $route['default_controller'] = $subDomains[$_SERVER['HTTP_HOST']];
}
AkshayBandivadekar
  • 839
  • 10
  • 18
3

!!!
A very important step you don't want to forget in addition to Chococroc's great example is to route any segments back to the subdomain controller otherwise you will end up routing to a controller that probably doesn't exist. Example using Chococroc's existing code

switch ( $_SERVER['HTTP_HOST'] ) {
    case 'students.mysite.com':
        $route['default_controller'] = "students";
    break;
    case 'teachers.mysite.com':
        $route['default_controller'] = "teachers";
    default:
        // The list of your $routes lines at is was...
    break;
}

Navigating to 'teachers.mysite.com/login' will load the 'login' controller NOT the expected 'teachers' controller.

If you don't want this unexpected behavior you need to route any segments back to the subdomain controller. They will now be a function of that controller.

switch ( $_SERVER['HTTP_HOST'] ) {
    case 'students.mysite.com':
        $route['default_controller'] = "students";
        $route['(:any)'] = "students/$1";
    break;
    case 'teachers.mysite.com':
        $route['default_controller'] = "teachers";
        $route['(:any)'] = "teachers/$1";
    default:
        // The list of your $routes lines at is was...
    break;
}

Navigating to 'teachers.mysite.com/login' will now load the 'teachers' controller and run the 'login' function within that controller.

There are other things you could enforce such as a subfolder for each domain, etc.

Josh
  • 63
  • 7
  • Very nice addition! I've added an update in my answer to help people finding yours, it offers very good advice, :D – Federico J. Apr 10 '20 at 05:34