How to implement Observer pattern in CodeIgniter for generic tasks

Viewed 545

I'm building an application in a classic CI mvc setup where the user has a general/generic tasklist. The main purpose of a task is to indicate the user that he has to complete a specific action and will redirect him to the page where he needs to complete this action.

In a very simplistic way the db scheme of the task looks like this: enter image description here

The tasklist it self will be somewhat of a list which redirects the user: enter image description here

My problem is when the user is redirected to the specific page on which the action needs to occur we lose the context of the specific task. So even if the task is completed (in this example for instance the document is uploaded) the task itself doesn't know that and we don't really have a connection to update the task.

After some research the Observer design pattern looks like the one that can handle this need. But through all the examples I fail to make a click on how to actually implement this into our current system.

In a controller handling the upload of the document is the function upload_doc(){} which when is succesfully executed should also update the task that is connected or subscribed to this document upload.

class Dashboard extends MY_Controller{

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

    // Force SSL
    $this->force_ssl();
}

public function upload_doc(){
   //Handle doc upload and update task
}
}

Can anyone help me in a noobfriendly way how I can achieve this setup within the CI framework?

Thanks in advance!

2 Answers

If it comes to design patterns I always try to find a referencing documentation/github repo with design pattern examples for the requested language. For PHP I can warmly recommend this one here:

https://designpatternsphp.readthedocs.io/en/latest/Behavioral/Observer/README.html

An example implementation could look like this. Attention: I have no experience with CodeIgniter. This is just a way to illustrate how you could implement this with the given code example.

class Dashboard extends MY_Controller 
{
    private function makeFile()
    {
        // I would put this method into a file factory within your container.
        // This allows you to extend on a per module-basis.

        $file = new File();        
        $file->attach(new UpdateTask);
        $file->attach(new DeleteFileFromTempStorage);
        $file->attach(new IncrementStorageSize);
        $file->attach(new AddCustomerNotification);
        return $file;
    }

    public function upload_doc() 
    {
        // My expectation is that you have some task-id reference 
        // when uploading a file. This would allow all observers 
        // to "find" the right task to update.
        $file = $this->newFile();

        // enhance your file model with your request parameters
        $file->fill($params);

        // save your file. Either your model has this functionality already
        // or you have a separated repository which handles this for you.
        $fileRepo->persist($file);

        // Finally notify your observers
        $file->notify();  
    }
}

Hope this helps.

If I understand your problem & intentions right (to set a relation between a record created in one place & some action, happening elsewhere), then Observer (if we're referring to the same idea from the same book) won't solve it, it is not even applicable here because of PHP & the generic stateless nature of web, i.e. execution spanning across multiple program invocations. The classic patterns from the GoF book are designed and intended for a single execution within a single program.

You'd need to wire you custom logic which would bind together a task record and user's actions that follow. The simplest approach would be to add a cookie to the user's browser with a task ID so that ID would be accessible to the document upload controller and it would update the rest of the system. And there you can make use of the classic Observer, pretty much as per Christoph's answer or any other example on the internet.

Related