Multi Level Subfolder Controller in CodeIgniter
Well, this is my first post so be gentle to me :).
Recently i’m working on a web based application project using CodeIgniter framework. Problem arises when my boss wants this web application to have more than two level subfolder in controller folder (for example: /controller/company_a/admin/, /controller/company_a/reports/) for organizational purpose.
As the default CodeIgniter version 1.7.2 set up, controllers can’t have multi level subfolder, so I need to find a way to provide the request.
After a little bit of Googling and searching on CodeIgniter forums, I found this thread http://codeigniter.com/forums/viewthread/85554/
There’s a solution for this problem on that thread but i don’t like the idea hacking the CI core so I modified it. So here’s the solution:
- Copy this code into your CI application library folder (the default is /system/application/libraries), and name it as MY_Router.php:
<?php /* * Custom router function v 0.1 * * Add functionality : read into more than one sub-folder * */ Class MY_Router extends CI_Router { Function MY_Router() { parent::CI_Router(); } function _validate_request($segments) { if (file_exists(APPPATH.'controllers/'.$segments[0].EXT)) { return $segments; } if (is_dir(APPPATH.'controllers/'.$segments[0])) { $this->set_directory($segments[0]); $segments = array_slice($segments, 1); /* ----------- ADDED CODE ------------ */ while(count($segments) > 0 && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])) { // Set the directory and remove it from the segment array $this->set_directory($this->directory . $segments[0]); $segments = array_slice($segments, 1); } /* ----------- END ------------ */ if (count($segments) > 0) { if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT)) { show_404($this->fetch_directory().$segments[0]); } } else { $this->set_class($this->default_controller); $this->set_method('index'); if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT)) { $this->directory = ''; return array(); } } return $segments; } show_404($segments[0]); } } ?>
- And we’re done 🙂 . Simple isn’t it?
Feel free to test it and give your opinion. Any suggestions will be very much appreciated. Thanks!
Indeed, well done sir.
Glad to share some information 🙂
Brilliant..I’m very proud of you 🙂
Very use full for developers… nice think
Still Fuzzy with this things, I’m familiar with cisco command than this one Ge…
😀
Well,you have to learn the basic first before you use this framework 😉
Thank you for this! I especially like how you implemented it over other suggestions from the forums.
You’re welcome. I just modify it a little so it still follow Codeigniter rules about overriding the core. But thanks for your word 🙂
Nice Sir. Thank you.
Perfect… Thanks in advance.
Thanks for this, works perfectly!
This has made my day! 🙂
Nice effort put forth in doing this and sharing it to others. Its a shame that even though CI is open source everything is pretty much only done by EllisLabs (which I am grateful for) but if it was more open CI could have major improvements regularly such as this one.
We are constantly forced to hack or extend (a more elegant hack) it to meet our needs however if development was more open to community patches that pass all tests required to conform to CI’s quality it would probably cut the hacking of it down by 50% at the very least.
Regardless, at least they have the wiki which is a somewhat happy medium and where I post my contributions (hacks).
Thanks!
That’s why there’s Kohana 🙂
But i agree about your opinion. CI need a more “open development” to community patches.
Nice to know you 🙂
Thanks a lot! This has made my day too! Simple and well thought, and indeed, this could be implemented in CI…
Glenn,
Thanks for sharing you just saved my arse 🙂
Cheers,
You are the fu**** Master!!! thanks
Glenn,
Thanks for the useful post. I believe you made a typo, in that you are supposed to place the MY_Router.php file in /system/applications/libraries folder (not library) as you have.
Thanks again!
-Adam
thanks for your correction. Corrected 😉
nothing happening for me still getting 404 ERROR.
my form action to add region
http://localhost/server/connectionspot/admin/geographic/region/add
when i click submit to add regions my url will look like this
http://localhost/server/connectionspot/admin/regions/?lang=ch
geographic automatically removed plz help me our
controllers
!_admin
!_geographic
!_regions
i use my_route but still nothing happening
u placed the file in same level as admin, so it will looks like
http://localhost/server/connectionspot/regions/?lang=ch
Btw, why still use query string? It’s my opinion though, but try not to use query string on your url. Hope it will help
God bless u .. thanx
Okay I understood it. Thans a lot!
Nice one!
Still useful till now.
Why don’t you write anymore? 😉
thanks for your attention 🙂 i’ll start to write something pretty soon 🙂
Fanstastic! That’s exactly what I needed. Thanks.
Hi Glenn,
Good to see your post. I am new to CodeIgniter. I would like to know, how the one level folder url path will look like.
I have created “Products” folder in the “Controllers” directory and placed the main router file which I have copy/pasted from the above given code of My_Router.
——Controller
|
—Products – placed the Product_Router here (Let me know whether this is the right place of the file)
|
——Reports1
——Reports2
I am trying to call the Reports1 controller sampleReport() method
Url I tried out is:
http://localhost/CodeIgniter/index.php/products/reports1/products_router/sampleReport
Is the above url correct. If not, can you kinldy let me know the correct url.
That will make the url is like this : http://localhost/Codeigniter/index.php/products/reports1/samplereport
Please tell me if this is what you actually mean. Thanks 🙂
I got the solution. Thanks
sorry for late answer. Good for you then 🙂
hey, it’s work!
thank you
thank u very much. its help me to keep my project folder stature well
wel done sir. tks
saved my day! now things are working like a charm..
great post, I must say
thanks a lot 🙂
Cheers, saved me some time. Please have this virtual beer as a token of my appreciation. (if it doesnt break)
_.._..,_,_
( )
]~,”-.-~~[
.=])’ (; ([
| ]:: ‘ [
‘=]): .) ([
|:: ‘ |
~~—-~~
It broke.. sorry pal 😉
haha.. 😀
I’m newbie to codeigniter and implemented custom router function. I have currently http://localhost/services/webdesign which webdesign page works now but how do I also have content for services as when I create a services controller it then stops the webdesign controller from loading?
Thanks in advance!
U cant have services controller if you want webdesign controller to work. U can move webdesign controller to another folder, or u can make webdesign method in services controller.
Hope this will help u. Cheers
thank you very much.. this is my real solution… thanks a lot
Word of warning:
not that any of you would be this dumb but something to look out for:
Don’t name the subdirectory the same name as another controller… took me WAAAY too long to debug that.
Naming the subdirectory the same name as another controller in the same directory fails a check in MY_Router.php. I had a file: “api.php” and a subdir “api”. The way in which CI checks for a valid subdir is to immediately append a “.php” on the end of a subdir and see if it exists… well in my case it did exist, but it was checking for the wrong one…
I’m not going to comment on this algorithm, but watch out.
Decent MVC otherwise.
With your added code, I don’t think you can use 2+ deep directories. The “set_directory” command seems to screw things up in Router.php. The reason is that function removes all forward slashes then appends a forward slash on the end… that’s not what we want to do if you have more than 1 deep. Your mod helped with a single subdir, but not 2.
I’ve tried the mod I’m suggesting on several levels deep:
application/controller/file.php
application/controller/subdir/file.php
application/controller/subdir1/subdir2/file.php
Unless they changed the code for Router.php in the past – I’m running 1.7.3.
The following code should work in replacement of your modification. You should be able to easily see what I changed – I just commented it out:
/* ———– ADDED CODE ———— */
while(count($segments) > 0 && is_dir(APPPATH.’controllers/’.$this->directory.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->directory = $this->directory . $segments[0] . ‘/’;
//$this->set_directory($this->directory . $segments[0]);
$segments = array_slice($segments, 1);
}
/* ———– END ———— */
Nevertheless, thanks a ton for your mod, I would have been stuck for a long while without your fix.
Hmm, i’m not check this mod for version 1.7.3, but thanks for your mod. I’ll try this. 🙂
Hi, there. It’s me, again 🙂
I’ve just noticed that this won’t work with CI 1.7.3. I’ve got mine work well previously with 1.7.2.
The change in Router.php from 1.7.2 to 1.7.3 might have deals with it.
But as DonJohnII suggests, a little change in your code:
work as magic and my code work well again as before. 😀
Thanks, guys.
PS: I wonder if this would work also in the latest version of CI: 2.0.2. Anyone have tried it?
PPS: I’m still waiting for your next writing 😉
i’m sorry i don’t get this. how do we use it? aren’t we supposed to call my_router function or class?
you dont have to call this class, it will automatically override native core of CI itself. Cheers
Thanks for this library …. it’s work brot
this is not working with codeiginater 2.0 Please help me
http://codeigniter.com/user_guide/general/controllers.html#subfolders
thanks. But if you pay attention closely, what i wrote is for ci 1.7.2 🙂
This doesn’t work for me either in 2.0. please help
you can use version 2.1 and see this instead
gw coba nyang punya loe bro, trus filenya gw taro di application/libraries/ gak bisa bro, trus gw cari di forum codeigniter, type nya sih sama ama yg punya loe bro, tapi kalo dia naronya di application/core, and it work ^^
coba kesini kalo ada yang masih belum bisa:
http://codeigniter.com/forums/viewthread/202176/
ci yg gue pake ci lama bro. Itu utk ci 2 ke atas ya. Anyway thanks.
Hi Glenn, thanks very much for a job well done. Here are some fixes to your code to bring it in line with CI 2.0:
1) Like Don Jon posted above, you need to set $this->directory directly instead of using set_directory (allowed b/c it’s public). New code:
/* ———– ADDED CODE ———— */
while(count($segments) > 0 && is_dir(APPPATH.’controllers/’.$this->directory.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->directory = $this->directory . $segments[0] . ‘/’;
$segments = array_slice($segments, 1);
}
/* ———– END ———— */
2) My_Router.php needs to be in the “application/core/” folder, not “libraries”.
If you can just update your post, I don’t know if many readers would scroll down this far just to make it compatible with more recent installations.
Cheers and thanks again,
Mike
thanks for your fix 🙂