Welcome Guest, Not a member yet? Register   Sign In
Calling actions in another controller?
#1

[eluser]oscaralexander[/eluser]
I'm starting a new CI project this evening and I want to get it right from the ground up. Now there's one particular issue I'm wondering about and would like to know what the guru's approach is to this.

I have this website that will feature the 10 best places in different cities accross the world. The URL structure will be like this (for the sake of readability, guessability and SEO):

domain.com/united-kingdom < list of cities + 10 best places in the UK
domain.com/united-kingdom/london < list of boroughs + 10 best places in London
domain.com/united-kingdom/london/shoreditch < 10 best places in Shoreditch, London

Since *every* bit after domain.com is variable (except for some basic stuff like /contact, /about etc.) I decided to subclass the Router class and make every 404 point to the index action of my default controller (Core::index), where I perform further 404 checking/handling.

Still with me? Smile Now, since the above approach would be an awful lot of code for a single controller, I was wondering if I could delegate to other, specialized actions in other controllers. For instance, if a visitor requests domain.com/united-kingdom/london I would like to:

1. Verify if this record exists in the Core::index action
2. Delegate to a specialized controller, i.e. City::place

Is this at all possible? Thanks guys!
#2

[eluser]fesweb[/eluser]
First, can't you just _remap your core:index.php and not do anything weird with the router class?

Regardless of how you handle the urls, you can put your working parts into a library, or libraries.

core:index.php code...
Code:
function _remap($method)
    {
        if (method_exists($this, $method))
        {
            $this->$method();
        }
        else
        {
            $this->handler();
        }
    }

function about() { // do your about stuff }
function contact() { // do your contact stuff }

function handler()
       {
             // do whatever you need to do here
             if($this->uri->segment(3)) {
                // do location stuff
                $this->load->library(location);
                $this->location->get_info($this->uri->segment(3));
             }
             elseif($this->uri->segment(2)
             {
                // do city stuff
                $this->load->library(city);
                $this->city->get_info($this->uri->segment(2));
             }
             elseif($this->uri->segment(1)
             {
                // do city stuff
                $this->load->library(country);
                $this->country->get_info($this->uri->segment(1));
             }
            
       }
Your libraries can always return FALSE if the location or city or country is not valid. Then you could show them a 404...
Code:
$this->load->library(city);
$my_info = $this->city->get_info($this->uri->segment(2));

if( ! $my_info)
show_404();
else
$this->load->view('city', $my_info);
#3

[eluser]oscaralexander[/eluser]
Fesweb, thanks, that makes total sense! I just figured that if the method did not exist, it would always be directed to a 404 action unless the Router class is subclassed/hacked in some way.

I'll def look into this, thanks again!
#4

[eluser]fesweb[/eluser]
Well, you can do whichever technique offers the most advantages for your specific project.

Using the MVC traditionally, would mean loading a model instead of the library, and then pushing the returned data into a view.

Using libraries means that you can have the library return the html directly, but I still bring it back and the put it into a template through the controller.

I use libraries to grab a chunk of content from any section of a site and drop it into any controller, so I make the libraries do most of the work.

Example: a relationships library, which I can call from any type of page, and bring back lists of related people, or pages, or tags. The library creates a list of html links, and the controller just drops them into whatever part of the page you want.
#5

[eluser]oscaralexander[/eluser]
@Fesweb: Hmm, I've just tried implementing the _remap function, but failed. The Router class checks the /contollers folder for a file named after segment[0] (/controllers/united-kingdom.php, in this case) and calls show_404($segments[0]) when the file isn't found. It doesn't even get to the _remap function, as it does not resort to the default_controller.

Am I missing something here?
#6

[eluser]fesweb[/eluser]
I can't spend too much time on it right now, but I might well have been wrong, since it's your default controller.

Sorry.

You might need to do something simple in the config/routes, like this (this means that you could have an 'about' controller, and a 'contact' controller, etc.; and then you could have controllers for your dynamic content needs...):
Code:
$route['([a-zA-Z]+)/([a-zA-Z]+)/([a-zA-Z]+)'] = "location_handler/$1/$2/$3";
$route['([a-zA-Z]+)/([a-zA-Z]+)'] = "city_handler/$1/$2";
$route['([a-zA-Z]+)'] = "country_handler/$1";
Otherwise, I would search the forums for solutions to the domain.com/username1, domain.com/username2 problem -- which comes up from time to time.




Theme © iAndrew 2016 - Forum software by © MyBB