Welcome Guest, Not a member yet? Register   Sign In
How can I simplify this repetitive controller function check?
#1

[eluser]crikey[/eluser]
Hi guys,

I have a whole bunch of controllers, each with various methods, that require that a parameter be an integer to continue processing (otherwise a 404 error is thrown).

Examples are :

www.domain.com/foo/edit/1234
www.domain.com/foo/view/1234
www.domain.com/bar/delete/1234

So for all these methods, '1234' refers to the id of the record in the DB to process. For each method I do the following (to throw a 404 if the value isn't an integer):
Code:
if (!ctype_digit(strval($id))) show_404();

So, this works OK, but is getting repetitive. I'm just wondering, is there a way I could put something in the __construct() method for each class to tell it which methods require the parameter to be an integer?

I guess I'm thinking something like:

Code:
function __construct()
{
     ...
     $this->require_int_param('edit','view','delete');
     ...
}

I'm just not sure how to code this. Any suggestions?

Thanks,
Grant

PS - I know I could just rely on the DB query not returning a result because the id supplied isn't an integer, but I'd rather intercept this before loading the model.
#2

[eluser]richthegeek[/eluser]
Either use a MY_Controller class (add requires as vars then call parent), an autoloaded model that you call in the constructor (call the model function), or a hook which takes requirements form a config file.

User guide explains all
#3

[eluser]crikey[/eluser]
Thanks richthegeek,

You've given me some very broad suggestions, but not quite as specific as I was after. I can't use MY_Controller because the methods that require the integer parameter differ amongst the controllers. And I'm not sure what you mean by the other suggestions.

I guess I'm asking for specific help on how to implement this, on a per-controller basis.

Any further ideas?

Cheers,
Grant
#4

[eluser]richthegeek[/eluser]
I wouldn't have suggested the MY_Controller solution if it wasn't workable.

Your top-level controller constructor code might look like:
Code:
$this->requires->int = array( "edit", "view", "delete" );
parent::__constructor();

Note that the call to the parent constructor comes *after* the call to the parent constructor, so the settings are available to it (assuming requires is setup as a public class-level attribute within MY_Controller)
#5

[eluser]crikey[/eluser]
Thanks for your persistence with me

...but still, I'm not sure what you mean. You said "the call to the parent constructor comes *after* the call to the parent constructor" - what does that mean?

Also, where do I create the function which checks the method being called against those in the array? And how do I do this?

Thanks,
Grant (sorry if this is obvious and I'm just not getting it).
#6

[eluser]n0xie[/eluser]
Here is a part solution. This is raw draft but it should get you started. The bad part is that it relies the id to always be the third segment in your URL. You should probably write some logic which would investigate the segment array to find the right segment to test:

Code:
// application/libraries/MY_Controller.php
class MY_Controller extends Controller {

    protected $require_int_param = array();

    public function __construct()
    {
        parent::__construct();
    }
    
    protected function check_int_param()
    {
        if ( in_array($this->router->method, $this->require_int_param) )
        {
            if ( ! ctype_digit( strval($this->uri->segment(3))) )
            {
                show_404();
            }
        }
    }
}

// application/controllers/test.php
class Test extends MY_Controller {

    protected $require_int_param = array('edit');

    public function __construct()
    {
        parent::__construct();    
        $this->check_int_param();
    }
    
    public function edit($id = NULL)
    {
        echo 'success!';
    }
}
#7

[eluser]crikey[/eluser]
Hey n0xie,

Thanks for your reply, I'll give that a try.

Is $this->router->method documented somewhere? I'm assuming its a variable that's been set (in your example, 'edit') prior to the controller method (based on the URI segment) being called?

Cheers,
Grant
#8

[eluser]n0xie[/eluser]
It's available to the Superobject. In your controller do this:
Code:
var_dump($this);
You can see what you have access to.




Theme © iAndrew 2016 - Forum software by © MyBB