Question

My Codeigniter project has a long list of identical categories, each with many identical methods.

To make it dynamic and cleaner, I have used _remap functions to load the identical methods within the controller. Now I am trying to replicate the controllers

e.g. My controllers Antelope.php Bat.php Cuckoo.php Dog.php Elephant.php... Zebra.php all have this format below (I used _remap to condense all the similar methods into one).

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Antelope extends CI_Controller {

    function __construct() {
        parent::__construct();
    }

    private function _remap($method, $params=array()){
       $this->animal = ucwords($this->router->fetch_class());
       $allowed_methods = array("Tame", "Buy", "Sell", "Gift");
       if (in_array($method, $allowed_methods)):
           // Model zoo has been autoloaded      
           data["foobar"] = $this->zoo->get_data($this->animal, $method);
           // Stuff goes here
       else:
          $this->index();
       endif;
    }

    public function index(){
       // Stuff goes here
    }
}

/** End of file Antelope.php **/

The remapping works fine for Antelope and all its remapped methods, but is there a way for me to apply this same method to all the other files so I can just have a single Animal.php Controller file instead?

I guess I may use routes.php, but the list of Controllers is too long; I'd have hundreds of lines in the routes file if I explicitly list each "animal" routing.

Any way around this?

EDIT: The "animal types" are listed in a database, and will keep increasing over time. I don't want to keep revisiting the project to create new controllers or add new classes for the new elements in the database! This is why I want to use a dynamic routing method. Also, the project is a site redesign, so the URLs like http://www.website.com/antelope/buy/3 need to remain the same.

Was it helpful?

Solution

The trick is to realize that the animal type is variable and you're trying to map it to static files. Don't do this. Just pass the animal as the first argument to the index function. That's what arguments are for: variables.

class Animal extends CI_Controller{
    function __construct(){
        parent::__construct();
    }

    function index($animal){
        echo "I'm the {$animal}!";
    }
}

And set up the single route:

$route['animal/(:any)'] = "animal/index/$1";

Now, if you head to http://localhost/yourapp/animal/antelope

CodeIgniter will echo "I'm the antelope!"

Edit after your comment:

CodeIgniter goes from top to bottom in your routes file and breaks when it finds a valid one. You can place this at the bottom of your config/routes.php file:

$route['(:any)/buy/(:id)'] = "animal/$1/buy/$2";
$route[':any'] = "animal/index/$1";
//etc

You'll need to re-route all other controllers above this.

OTHER TIPS

Just create a class to inherit from

class Animal extends CI_Controller {
   function __construct() {
        parent::__construct();
    }

    public function _remap($method, $params=array()){
       $this->animal = ucwords($this->router->fetch_class());
       $allowed_methods = array("Tame", "Buy", "Sell", "Gift");
       if (in_array($method, $allowed_methods)):
           // Model zoo has been autoloaded      
           data["foobar"] = $this->zoo->get_data($this->animal, $method);
           // Stuff goes here
       else:
          $this->index();
       endif;
    }
}

class Antelope extends Animal {
    public function index(){
       // Stuff goes here
    }
}

A couple of options you could try are:

  1. Have a Animals.php base class and inherit all other categories from that like so

Animal.php

class Animal extends CI_Controller {
    //Your _remap() and other methods
}

Antelope.php Bat.php Cuckoo.php Dog.php Elephant.php... Zebra.php

require_once 'animal.php';

class Antelope extends Animal {
    //Antelope inherits its methods from Animal, so this is blank 
} 

This method would require you to have 100s of almost blank controller files (one per animal/ category) so is and not very dynamic, but would allow you to implement a __init() method in the Animal base class and override it in the sub-classes, allowing you to set-up any deviations in the categories (i.e. number of legs etc)


  1. Use one route for all animals

routes.php

//default index route http://www.sample.com/animal/type
$route['animal/(:any)']  = 'animal/reroute/$1/index';

//method route http://www.sample.com/animal/type/method
$route['animal/(:any)/(:any)']  = 'animal/reroute/$1/$2';

animal.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Animal extends CI_Controller {

    function __construct() {
        parent::__construct();
    }


    public function index(){
       // Stuff goes here
    }

    public function reroute($animal, $method) {
       //Check the $animal is valid
       //Check the $method is valid
       //Do stuff   
    }


}

/** End of file animal.php **/

This is a little more dynamic, as you can then load a list of valid animals from a database, but the URLs will not be as clean http://www.sample.com/bat/sell vs http://www.sample.com/animal/bat/sell

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top