Welcome Guest, Not a member yet? Register   Sign In
Question regarding routing controllers
#1

[eluser]crises[/eluser]
Hi all! First of all, in english im not as good as i would like to be, so my apologies if any mistake is done.

Well my question is kind of simple, but after some hours of research i wasn't able to find any answer out there, so here i come. I think i know how "default" url routing works (domain.com/controller/method/params) and all that stuff, but now im developing a new app and my needs are a little bit diferent. Let me explain with some examples.

Basically what im developing is a business directory, and my first approach to a routing would be this:

- domain.com/cats_controller/category for a "root" category
- domain.com/cats_controller/subcategory for a child category

Here comes my first trouble... my desire is to have an url structure like this:

-domain.com/category/subcategory

If i had only one controller in my app i know this could be resolved easily by passing the whole url to this specific controller, but how do i know to which controller should i pass the url if i have two or more of them?

So if i had a second controller to show the listings, supose this:

- domain.com/listings_controller/busines_name

I would like it to be something like:

- domain.com/category/subcategory/busines_name

Including all the "path", like a breadcrumb navigation but in the URL itself.

Well thats my problem right now, i dont know if i have explained myself in the correct way, i hope you people could understand and give me some help.

Thank you!
#2

[eluser]Zorancho[/eluser]
I would keep specific url for every category, subcategory, business_name in the database together with specific controller and action, then would extend the CI's core Router class with my own and will override the _set_routing() method so i can add my dynamic custom routes.
Code:
//$items is array from database with (id, url controller, action)
foreach($items as $item)
{
   //url segments = routed segments
   $this->routes[$item->url] = $item->controller.'/'.$item->action.'/'.$item->id;

   //output:
   //$this->routes['category1'] = 'cats_controller/category/1'
   //$this->routes['category1/subcategory1'] = 'cats_controller/subcategory/1'
   //etc...
}

//Then you can get the id in your controller
function category($id=0)
{
  echo 'Category ID: '.$id;
}

//To get current url passed use the uri class in your controllers for generating breadcrumbs.
$this->uri->segment_array(); //returns array of all url segments
$this->uri->rsegment_array(); //returns array of all routed segments.

I hope this helps
#3

[eluser]crises[/eluser]
Thanks, but with this solution i will have a huge array ($item) obtained directly from the database. I dont know exactly how CIs core route class works, but doesn't this implies a big query to the database everytime some new url is typed?

This morning when i woke up i thought that maybe a solution could be a larger controller than the ones i usually work with. I mean i like to work with small specific controllers, as i said in my first post, in example one controller for the categories listings, another for the business listings, etc.

But what if i do this (so simplified)? Maybe is an stupidity :S

- Controller:
Code:
class main_controller extends Controller {
    
    function main_controller()
    {
        parent::Controller();
        //needed stuff, etc.
        $this->load->model('Main_model');
    }
    
    function index()
    {
        $uri_segments = $this->uri->segment_array();
        $total_segments = $this->uri->total_segments();
        
        //check last url segment
        if ($this->Main_model->check_slug($uri_segments[$total_segments]) == 'business')
        {
            $this->_listing($uri_segments($total_segments));
        }
        elseif ($this->Main_model->check_slug($uri_segments[$total_segments]) == 'category')
        {
            $this->_category($uri_segments($total_segments));
        }
    }
    
    function _listing($business_slug)
    {
        $data['business'] = $this->Main_model->get_business($business_slug);
        $this->load->view('business_page', $data);
    }
    
    function _category($category_slug)
    {
        $data['category'] = $this->Main_model->get_category($category_slug);
        $this->load->view('category_page', $data);
    }
    
}

- Model:
Code:
class Main_model extends Model
{
    function check_slug($slug = null)
    {
        if($this->is_category($slug))
        {
            return 'category';
        }
        elseif($this->is_business($slug))
        {
            return 'business';
        }
    }
    
    function is_category($slug = null)
    {
        //database queries to chek if $slug is some category url
        // return TRUE;
        // return FALSE;
    }
    
    function is_business($slug = null)
    {
        //database queries to chek if $slug is some business name url
        // return TRUE;
        // return FALSE;
    }
}

Also if this solution could work i'm wondering what will happen with other controllers or the pagination for example... my God maybe i will stand for the default routing and forget all this stuff ¬¬
#4

[eluser]Zorancho[/eluser]
Yes, you need the database queries cause you must match the url since each is unique.
Good thing about this approach is that you can cache the pairs of keys => values:
[some-category/some-subcategory] => category_controller/subcategory_action
You will need only one controller like this and it's kinda like white list approach to urls.
Your solution is okay i think, also when you want to override some of the core classes, just create MY_Router.php file in your (application/libraries in CI < 2.0) (application/core in CI 2.0 if you are overriding core class) and extend the CI class.
Code:
class MY_Router extends CI_Router{
...
}
copy any of the methods that you want to override and insert your logic.
To understand the flow of every request in CI have a look at the system/codeigniter/CoddeIgniter.php file.




Theme © iAndrew 2016 - Forum software by © MyBB