Observer Design Pattern: Others Apps Are Following You

In this tutorial, we are going to discuss how to implement the Observer Pattern into your PHP applications.

What Is The Observer Pattern

The observer design pattern is defined as “one to many relationship between objects such that when the state changes, all dependents are notified.” That’s a mouthful, here is something a little more relatable.

I like to think of the observer patterns in terms of social media. Other people can subscribe to you. You are an object in an application with followers — the followers are other dependent objects. When you post something, you are telling all your followers an action you just completed. You have no clue who is actually listening and no one responds (life is lonely).

The Observer Design Pattern is well known and utilized in languages Javascript but not as much in PHP. The ProdigyView Toolkit makes it very easy to integrate the pattern into your applications and allow other developers to build code that “follows you”.

I would also suggest reading codeburst.io staff account post on https://codeburst.io/observer-pattern-object-oriented-php-4e669431bcb9 to get another perspective on the pattern before we integrate into your application.

How To Implement Observers with ProdigyView

Like all the Patterns from ProdigyView’s toolkit, we start by extending PVPattern. Like our other examples, we are going to be building a messenger app.

<?php
class Messenger extends PVPatterns {
}
?>

Our application is going to have a send function that is responsible for sending a message, and we want to log all messages that have been sent regardless if they succeed or fail. In our example below, we are going to pretend our application sends a message to Slack.

class Messenger extends PVPatterns {
  public function send($message, $user) {

$data = array(
‘message’ => $message,
‘first_name’ => $user -> first_name,
‘last_name’ => $user -> last_name
);

Slack::sendMessage($data);
}
}

Slack knows the status of our message, but we do not. But we can an add observer that will execute every time we call our function by adding in the following:

class Messenger extends PVPatterns {
    public function send($message, $user) {

$data = array(
‘message’ => $message,
‘first_name’ => $user -> first_name,
‘last_name’ => $user -> last_name
);

$result = Slack::sendMessage($data);
     //Call observers that are instances
self::_notify(get_class() . ‘::’ . __FUNCTION__, $this,$message, $user, $result);
     //Calls observers that are static
self::_notify(get_called_class() . ‘::’ . __FUNCTION__, $this, $message, $user, $result);
}
}

That’s it! A little explanation on what we did. The bottom two functions:

self::_notify(get_class() . ‘::’ . __FUNCTION__, $this, $message, $user, $result);
self::_notify(get_class() . ‘::’ . __FUNCTION__, $this, $message, $user, $result);

are both tools in ProdigyView Toolkit from the PVPatterns class, give the ability for others to subscribe to your function. We will show how both are used in the next section. To our _notify functions, we are passing the variables $this, which is an instance of the current class, the $message passed in, the $user and the $result from the slack message to any other applications that are listening. Now its time to listen.

How To Listen

Our next step is to write an application that is going to listen to the observer _notify function, which can be accomplished in a few ways.

Closures

The easiest way to listen is with closures, are PHP anonymous functions.

<?php
//Observer to be executed after CRUD create operation
Messenger:addObserver(‘Messenger::create’, ‘read_closure’, function($object, $messeng, $user, $slackResponse) {

echo ‘The message just sent:’. $message;
    if($slackResponse) {
echo ‘Successful’;
} else {
echo ‘Unsuccessful’;
}

}, array(‘type’ => ‘closure’));

In the above example, we attached an observer to our Messenger class with Messenger:addObserver. Notice that the function is accepting all the arguments from the _notify function, $object, $messeng, $user, $slackResponse. Now each time a message is sent, we get the result from slack and make decisions based on the response.

More Examples

There are more ways of implementing observers, for example having an observer directly call a function of another class. To get into actually coding it yourself I would recommend heading over to:

Look in the Artheciture section. There are more dynamic examples of the observers implemented there.

When To Use Observers

It starts with understanding “separation of concerns”. Observers should be used when we want to create an application that can have interchangeable parts of execution that the parent class knows nothing about nor should it.

For example, if we are building a message board. The message board should be responsible for posting a message — that’s it. Other actions like sending emails for when people reply vs sending a notification is not the responsibility of the message board.

We can attach an observer to the message board that checks if the users want to receive emails first and if they do then sends the request off to an EmailService. We can then add applications that send notifications of new messages via Slack, Facebook, Desktop Notifications etc — none of these are the responsibility of the message board.

Observers allow us to build highly extendable applications without having to rewrite parts of our code.