views:

35

answers:

3

I'm trying to learn more about the codeigniter framework by porting an existing website to it -- something that's not too complex, or so I thought.

Currently the site is replicated for its users and presents personalized data based on the url, for example, Joe might have his site at:

www.example.com/joe
www.example.com/joe/random-page.php

And you'd replace "joe" with any given user name. The URLs need to be structured this way: /joe/ isnt FOR joe, its for joe's visitors, so I can't rely on a user login or method of this sort. I could switch to joe.example.com but would rather not.

Is there a way I can make this play nice with Code Igniter?

Currently, it would want to call the joe controller. My initial thought is trying to find a way to have a default controller called when a controller doesn't exist, but if some CI pros have advice on a different, better way to handle this, it would be great.

+1  A: 

There are a number of different ways to go about this. Just be warned, both of these solutions require you to edit CI's core files. That means you can't upgrade without breaking these edits. Unfortunately hooks do not suitably address this issue.

The easy way:

line 188-195 in system/vodeigniter/CodeIgniter.php handle the logic for what happens when a controller is not found.

The harder but better way:

There is a hook (http://codeigniter.com/user_guide/general/hooks.html)

pre_controller

But this will not work! The reason is that this is called after the controller has been determined, but before anything is actually executed. In other words, it is too late. The next earlier one

pre_system

is in fact too early, because routing has not been done and anything you do the routing will get overwritten.

So I needed the first controller to look the same, yet end up calling a different controller. The reason was that the page was accessed in a hierarchical way, so that it would be the subsection of a subsection and so on.

What I did was add on line 43 of system/libraries/Controller.php

    $this->_ci_initialize();

Basically I had it autoload the libraries BEFORE the controller was called, because I was finding that the libraries were not loaded before the controller was called and I needed it to be done so because I needed to check user access authentication and hook directly into the routing itself.

After I did that, I extended one of the native core libraries that were autoloaded (in this case session, for applicaiton specific reasons) and then executed the rerouting.

        $RTR        =   & load_class( 'Router' );
    $this->URI  =   & load_class( 'URI' );
    $this->URI->_fetch_uri_string();

I called this code in the start, then put my logic afterwards. This is a sample of what my rerouting logic looks like

    if ( $this->segment( 1 ) == 'institute' )
    {
        if ( ! in_array( $this->segment( 3 ), $course ) )
        {
            $RTR->set_class( 'courseClass' );
            $RTR->set_method( 'index' );

            if ( ! $this->segment( 4 ) )
            {
                $RTR->set_class( 'course' );
                $RTR->set_method( 'index' );                
            }
        else
        {
            $RTR->set_class( 'course' );
            $RTR->set_method( $this->segment( 3 ) );
        }
    }

The original is much longer. I probably should consider writing some sort of plugin or superior way to handle the rewriting rather than silly spagetti logic. However, I needed extremely fine grain control of the controllers being called based on the URLs. This will literally give you god mode control over your controller based on the URLs. Is it a hack? Yes. Is it inelegant? Absolutely. But I needed it done.

Just remember since this edits the core files, you can't easily upgrade after. I think the Kohana framework has a solution to this.

theAlexPoon
This is so much more insanely complex then I had anticipated. I was expecting an "of course, its easy!" sort of answer :P Thank you for your input. At the moment, I'm exploring solving my problem via mod_rewrite, for a possibly simpler solution.
Will
After a lot of reading, I found out that this CAN be done easily, with the [routes.php file](http://codeigniter.com/user_guide/general/routing.html).
Will
Oops sorry I forgot about that. I looked into it when I originally implemented my solution, but I found it was far too simple. I think the reason I didn't use it was because it would only go 3 levels deep at most. In any case I hope maybe my answer will solve somebody else's question.
theAlexPoon
+1  A: 

I kept reading the CI docs after Alex's post and found info on the routes.php file which does exactly what I needed.

It allows you to use regular expressions to rewrite the routes (URLs), much in the same manner as mod_rewrite, so I could strip out the user name and end up passing it as a param.

Will
+1  A: 

Upgrade to CodeIgniter 2.0 and use $route['404_override'] = 'controller'; or install Modular Extensions which does the same thing, but for now they use $route['404'] instead.

Phil Sturgeon