Welcome Guest, Not a member yet? Register   Sign In
Hooks on controller methods
#1

(This post was last modified: 10-12-2019, 03:00 AM by milengardev1994.)

Hello,

I have been building RESTful API using CI 3 and I have came to a situation where there is a lot of duplicated code so I was thinking if it's possible to achieve something like a hook on a function inside a controller. As far as my knowledge gets we can add hooks on the controller itself but thats on the actual initialisation and destruction. What I want is to have a hook that is triggered before a call of a function inside the controller. 

Here is some example of my code

PHP Code:
    public function update($id)
    {
        if (!$this->exist($id)) {
            return;
        }
       //Do something

    }

    public function delete($id)
    {
        if (!$this->exist($id)) {
            return;
        }

         //Do something
    }

    public function add_image($id)
    {
        if ( ! $this->exist($id)) {
            return;
        }
        
        
// Do something
    }

    private function exist($id)
    {
        if ( ! $this->Example_model->exist($id)) {
            return false;
        }

        return true;
    

As you can see the private method 'exist' is duplicated couple of times.
I would like to make the code cleaner by extracting this functionality out of the function body so it can be re-used on multiple places.

Maybe there some other solution that are not related with Hooks and I love to hear about it.

I hope I have explained clear enough. 
Regards
Reply
#2

Why not create a MY_Controller and extend all your controllers from it?

Place all your code that is duplicated in to the MY_Controller.

If you are extending the Controller core class, then be sure to extend your new class in your application controller’s constructors.


PHP Code:
class Welcome extends MY_Controller {

        public function index()
        {
                $this->load->view('welcome_message');
        }


Place all your code that you need in every controller into the MY_Controller.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#3

(This post was last modified: 10-12-2019, 06:29 AM by milengardev1994.)

Well I do get your suggestion however my problem is about repeating 'exist' on every function that 'exist' is required.

In other frameworks there is the concept of middleware where you can intercept the request and validate it before you pass it to the controller function.
I don't think CI 3 provides this kind of functionality out of the box.
Maybe there is some possible way to emulate it without huge changes.
Reply
#4

See the pre hooks in the user guide there are also post hooks etc;
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#5

(This post was last modified: 10-12-2019, 01:39 PM by dave friend.)

While it isn't a direct plug-in for your wishes, ion_auth implements an ad-hoc "hook / trigger_events" scheme that could probably be adapted. The ion_auth GitHub repo is here.

Similarly, CI v4 has an Events class that you could maybe use and adapt to CI v3.

But unless the exist() method you show is a stand-in for something a lot more complex it would not be a good candidate for a hook/event system. There is barely more code in exist() than it replaces in the other functions. In fact your version of exist

PHP Code:
private function exist($id)
{
    if ( ! $this->Example_model->exist($id)) {
        return false;
    }
    return true;


could be rewritten as

PHP Code:
private function exist($id)
{
    return $this->Example_model->exist($id));


So, baring complexity you're not showing us, there is no need for the exist() function to... pardon the pun, exist.

This code
 
PHP Code:
public function update($id)
{
    if (!$this->exist($id)) {
        return;
    }
  //Do something


should be rewritten as

PHP Code:
public function update($id)
{
    if ( ! $this->Example_model->exist($id)) {
        return;
    }
   //Do something


Any hook or event system is going to involve executing a lot more code than is shown here. Just to be clear, I'm not against some sort of hook/event system. It's just that your example isn't a good fit.

(10-12-2019, 06:01 AM)milengardev1994 Wrote: ... my problem is about repeating 'exist' on every function that 'exist' is required.

There are other solutions that don't require the overhead of the kind you are seeking.

Assuming all those methods that call exist($id) are in a controller I have to ask, Where does $id come from? Likely it was a GET or POST item - right?

Why not simply verify that the $id is valid the first time you touch it? Maybe even in the controller constructor. Once verified your other methods don't have to worry about whether it exists or not. You could also store the verified $id in a class property that other methods can access. If the property is set then other methods know the $id cleared for use.

There are other possible easy ways to make the code cleaner.
Reply
#6

(This post was last modified: 10-13-2019, 01:45 AM by milengardev1994.)

The example that I give it was to briefly explain what is the issue that I am having.
Of course, there is more logic in the controller but I strip it to make it more clear, apparently not very successfully.

The '$id' indeed comes from HTTP request.

I was looking at something similar to the event system you mentioned. Your proposed solution for executing 'exist' in the constructor is valid and I already have used it when I am dealing with authentication. The only note I have with is that putting a lot of logic in the constructor for me seems a bit messy. Validating the request before actually reaching the controller seems a better option for me.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB