CodeIgniter Forums
Advanced Controller Routing (based on domain) - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: CodeIgniter Archived (from EllisLab) (https://forum.codeigniter.com/forum-20.html)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forum-23.html)
+--- Thread: Advanced Controller Routing (based on domain) (/thread-43244.html)

Pages: 1 2


Advanced Controller Routing (based on domain) - El Forum - 07-05-2011

[eluser]stealthify[/eluser]
Hi all,
First post, but long-time fan of CodeIgniter. While things have been smooth-sailing with CI for my previous adventures, my first question for you guys happens to be a doozy.

The Concept
One CI installation, one database, one application --> routed to from multiple domains --> domain determines the controller to route to (so multiple controllers, multiple languages, multiple views)

I understand that there are probably a few different ways to go about this, but the folder structure I decided upon was:

-----------------------------------------
application/
-- controllers/
---- sites/
------- domain1/
--------- home.php (domain1.com/)
--------- about.php (domain1.com/about)
------- domain2/
--------- home.php (domain2.com/)
--------- about.php (domain2.com/about)
---- home.php (default fallback)
---- about.php (default fallback)
-- language/
---- sites/
------- domain1/
--------- english/
------- domain2/
--------- english/
---- english/
-- views/
---- sites/
------- domain1/
--------- home.php
--------- about.php
------- domain2/
--------- home.php
--------- about.php
---- home.php
---- about.php

-----------------------------------------

I figured this was my best bet, since really all of my configs, helpers, models, libraries, etc will remain the same, no matter which domain I have routed to my CI install.

My Goal
After poking around and exploring how the current routing system works, my plan of action was to determine which domain the code is executing under, and then querying a database to gather some preliminary info on which controller to call (ie: the default fallback if it doesn't exist in the database, or if it is found, the appropriate controller in the 'controllers/sites/' directory).

My Progress
The idea sounds simple enough, and I know how to extract the domain and run a query based on this domain. From there, I also know how to run a check to make sure that the controller exists (ex: controllers/sites/domain1/home.php).

My Question
What I'm stuck on is trying to figure out where I need to start in order to tell CI to call my alternate controller as opposed to the default controller. Will something like this require a modification of the system core? Or is it override-able from my 'application/' folder?

Lastly, do any of you see any pitfalls to using this method? Is there a better way to go about this?

Thanks for the help guys, hope everyone had a great weekend.


Advanced Controller Routing (based on domain) - El Forum - 07-05-2011

[eluser]toopay[/eluser]
Well, i see you're about to works with a huge lines of routes here. You may consider this structure instead :
————————————————————-
(on your public_html folder)

domain1.com/
—index.php
—.htaccess
—application/
——controllers/
———- welcome.php
——models/
——libraries/
——views/
——..everything else

domain2.com/
—index.php
—.htaccess
—application/
——controllers/
———- welcome.php
——models/
——libraries/
——views/
——..everything else

frameworks/
—codeigniter/
——core/
——database/
——libraries/
——..everything else
—kohana/
—yii/
—zend/

————————————————————-

In this way, you just need to specify the system folder/path on every index.php on each domain.


Advanced Controller Routing (based on domain) - El Forum - 07-05-2011

[eluser]stealthify[/eluser]
Hi Toopay, thanks for that! I like that idea, especially since it keeps all of the frameworks together (CI, Kohana, etc).

I'll run that direction with it tonight, I saw some other people suggesting this method in other multi-domain/single-system threads that I found when searching.

The part I imagine I'll need the most guidance on is trying to figure out how to share the same application cache, config, core, helpers, hooks, libraries, logs and models across all of the domains. I was hoping that the index.php would have given a spot to define these custom folder paths, but there must be another way.

Any suggestions in this department?

(once again, the only folders that will be dynamic across all of the domains include: controllers, language and views. All others will be shared.)


Advanced Controller Routing (based on domain) - El Forum - 07-06-2011

[eluser]toopay[/eluser]
With above suggestion, each domain is a single independent application, which use same framework resource (in this case, CI). That mean each application has its own resource. If you need, to share common resource (like core, config, helper, libraries etc) in your each application its look like HMVC with one application folder (with modules) is your solution instead create multiple application. Search on forum or wiki 'HMVC' or 'Modular CI' for that. Then you may just need to set a proper htaccess on every domain/sub domain to redirect it properly to each modules.


Advanced Controller Routing (based on domain) - El Forum - 07-07-2011

[eluser]stealthify[/eluser]
Wow, this is genius! I hadn't even considered this approach, and it appears to be working well. I took your advice, and added HMVC to my application, and then reworked the file structure. As it stands now, this is what I'm working with:

-------------------------------------
frameworks/
-- codeigniter/
---- core/
---- database/
---- .. etc


public_html/
-- .htaccess
-- index.php
-- application/
---- cache/
---- config/
---- core/
---- ...etc
---- modules/
------ domain1/
-------- controllers/
---------- home.php
---------- about.php
-------- views/
---------- home.php
---------- about.php
------ domain2/
-------- controllers/
---------- home.php
---------- about.php
-------- views/
---------- home.php
---------- about.php

-------------------------------------

With the above, I have successfully gotten the following to work, each with their unique controllers and views:

http://localhost/public_html/domain1/
http://localhost/public_html/domain1/about

http://localhost/public_html/domain2/
http://localhost/public_html/domain2/about

Looks great!

Now that the game has changed, a new question has come up. In my current .htaccess (in the public_html) folder, I have the following rewrite condition:

Code:
RewriteEngine on
RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

I have been struggling throughout the night to figure out the best way to capture the domain that is requesting the public_html directory, and then disguising what they see so that all they see is the following:

http://www.domain1.com/
http://www.domain1.com/about

and

http://www.domain2.com/
http://www.domain2.com/about

I suspect this will have something to do with %{HTTP_HOST} and %{REQUEST_URI}, but I can't find a combination that works, especially with the current condition for the index.php/$1 rule.

Willing to help me determine what my final htaccess should look like?

Thanks again for the help so far.


Advanced Controller Routing (based on domain) - El Forum - 07-07-2011

[eluser]Taftse[/eluser]
Hey stealthify,

you could create multiple domain folders within the public_html folder
in each domain folder you have a index.php and a .htacces file (forward the domain to the folder)
make sure that the directory for the application folder is set correct in the index.php
then you just add a .htaccess file like this

Code:
RewriteEngine on
RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteRule ^(.*)$ ./index.php?/domain1/$1 [L]

where domain1 is the name of the module folder

you can then do the same for domain 2,3,4,5,..... etc

this is the way i do it for all domains and sub domains (per project)

hope this helps

Regards

Taftse


Advanced Controller Routing (based on domain) - El Forum - 07-07-2011

[eluser]toopay[/eluser]
Or write one htaccess file in public_html : with your recent structure, this is a trivial example for that
Code:
RewriteEngine on

RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{HTTP_HOST} ^www\.domain1\.com
RewriteCond %{HTTP_HOST} ^domain1\.com
RewriteRule ^(.*)$ index.php/domain1.com/$1 [R=permanent,L]

RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{HTTP_HOST} ^www\.domain2\.com
RewriteCond %{HTTP_HOST} ^domain2\.com
RewriteRule ^(.*)$ index.php/domain2.com/$1 [R=permanent,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Or more less line...
Code:
RewriteEngine on

RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.([^.:]+)
RewriteCond %{DOCUMENT_ROOT}application/modules/%1%2/ -d

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php/%1%2/$1 [R=permanent,L]
Also note that unless you did put your application in weird environment (like centOS with Cherooke instead Apache, or anything else that odd), dont use '?' in your htaccess.


Advanced Controller Routing (based on domain) - El Forum - 07-07-2011

[eluser]stealthify[/eluser]
Brilliant. Thanks to you both! This is the ultimate solution to help reduce redundancies, and I now see where I was messing up.

I hope to one day return the favor, I really appreciate your help.


Advanced Controller Routing (based on domain) - El Forum - 07-08-2011

[eluser]stealthify[/eluser]
Ahh something is not quite right. I might have missed something small. I'm getting a 404 on everything except for the home page. (example: http://www.domain1.com/about)

I ended up going with the second htaccess in your post, Toopay, so it currently looks like this:

Code:
RewriteEngine on

RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.([^.:]+)
RewriteCond %{DOCUMENT_ROOT}application/modules/%1%2/ -d

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php/%1%2/$1 [R=permanent,L]

I have a domain, say domain1.com, pointed to the directory with the 'application/' and index.php file in it. I have also, just for now, hardcoded the $config['base_url'] to be 'http://www.domain1.com/'. I will make this dynamic again after I figure this out.

My modules folder currently looks like this:

----------------------------------
public_html/application/modules/domain1.com/controllers/about.php
public_html/application/modules/domain1.com/views/about.php
----------------------------------

And I can successfully get the correct controller to load by manually going to:

http://www.domain1.com/index.php/domain1.com/about

but it will not work, I'll only get a error 404, if I go to:

http://www.domain1.com/domain1.com/about
or
http://www.domain1.com/about

Any ideas?

(also, I am running this on Apache)


Advanced Controller Routing (based on domain) - El Forum - 07-08-2011

[eluser]toopay[/eluser]
What about these :
Code:
RewriteEngine on
RewriteCond $1 !^(index\.php|assets|robots\.txt|user_guide)
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.([^.:]+)
RewriteCond %{DOCUMENT_ROOT}application/modules/%1%2/ -d

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule (.*) index.php/%1%2/$1 [R=permanent,L]
# If above lines didnt works, swap it with these line...
# RewriteRule (.*) /index.php/%1%2/$1 [R=permanent,L]
With above regex, it will capture your exist domain (site1.com/foo or http://www.site1.com/foo) and after validate if the directory is valid(represented with DOCUMENT_ROOT) these should be redirect it into index.php/domain1.com/foo