Observe! Notify! With The Observer Design Pattern In PHP

Observe! Notify! With The Observer Design Pattern In PHP

In this article i will talk about one of the behavioral patterns which is the observer design pattern what it’s components and how to implement it in PHP.

 

 

Many open source php frameworks have already built in support for firing and listening to events such as symfony and laravel. Despite this all these frameworks use the observer pattern behind the scenes and each framework implement it in a different way but the concept is the same, let’s take a look at the observer pattern and it’s components.

 

The simplest model of the observer pattern has three main components:

  • Subject: It’s the main object responsible for attaching and detaching observers, also is the main object who notify all observers if there is any data update.
  • Abstract Observer: This is an abstract class or interface which takes a subject as a reference and an update() method which is called by the subject in case of any update.
  • Concrete observers: Each observer extends from abstract observer and implement the update() method according to each one.

Observer Pattern Illustration In PHP

As you see in the above diagram the main components of the observer pattern can be described with one to many relationship with the fact with one subject can notify multiple observers. But how the observers notified? The answer is it must be some kind of state change which means when i update the state the observers notified of this state update. This is already applied in some technologies like angular 2 rxjs.

 

Now lets see the three components in action, in this example i demonstrate observer pattern to send notification using various ways like email, sms and push notification so if the user making any updates the three observer notified i remove the actual code for sending emails, sms and push notification to focus only on the idea.

Subject.php

AbstractObserver.php

EmailObserver.php

SMSObserver.php

PushNotificationObserver.php

In the code above the Subject class contains methods getState(), setState(), attach(), detach(), notify(). The attach() and detach() methods used to add or remove observers respectively, here i use the observer object hash as a key obtained by calling spl_object_hash() function. The notify() method loops through all the observers and call the update() method on each of them.

The AbstractObserver class is the skeleton class that all observers inherit from, in the constructor we inject the subject this observer assigned to and call attach() method passing “$this” as an instance of the current observer. The update() method is an abstract method so that we can implement it according to each observer.

Then i created three observer classes, which are EmailObserver, SMSObserver, PushNotificationObserver. All of these classes extend from AbstractObserver. Next i implemented the update() method with an echo statement just for the purposes of demonstration.

To test this example i create a simple class Client.php like this:

Client.php

I created one subject and then added three observers passing the $subject to each observer constructor, then i called setState() in the subject which in turn update the state and notify all the observers. This is why the observer pattern applies one to many relationships from one subject to many observers.

 

 

SPLObserver

Since PHP 5.1 The spl extension contains dedicated interfaces for dealing with observer pattern instead of writing classes from scratch which are SplObserver and SplSubject. Those interfaces contains to some extent the same methods we saw earlier.

SplSubject Structure:

SplObserver Structure:

 

So to use the splobserver we need to implement those interfaces and implement their methods, let’s rewrite the previous example using the splobserver.

Subject.php

EmailObserver.php

SMSObserver.php

Client.php

As you see the code is pretty similar to the custom observer classes we saw earlier, I used SplObjectStorage in our subject constructor this is another spl utility class that can map objects to data, this class contains methods attach() and detach() to attach or remove objects.

Real world example

A real world usage for the observer pattern is to display real time graphs for certain activity especially i you have multiple graphs updated simultaneous according to some value sent to server. Let’s see this example which i use CanvasJS, socket io and php observer pattern to render real time graphs, you have to be fimiliar with using socket io, i will display only some snippets, you will find the full source code in bitbucket repository at the bottom of the article.

 

Dependencies needed:

  • Canvasjs library
  • phpsocket.io: for handling socket io with php
  • socket io js client
  • jquery

 

Create a new folder with any name with this file structure in your server root:

  • js/ folder: contains javascript files
  • observer/ folder: contains observer and subject classes
  • composer.json
  • index.html
  • server.php

 

Next install phpsocketio with:

 

Then prepare observer classes located in observer/ directory:

observer/Subject.php

Suppose we have three types of graphs (line, column, pie) so create observer class for each type

observer/LineGraphObserver.php

observer/ColumnGraphObserver.php

observer/PieGraphObserver.php

As you see each observer update() method emit the data points required to render the graph to the client side, you may ask yourself where the variable $io comes from, it comes from server.php as you see in a moment.

server.php

The above code initializes the subject, attach the observers to the subject then we create a new instance of SocketIO passing in the port number “2020”, this the port number that socket io server will listen to, we will use that number also when listenting to socket events from client side, you can use a different port number if that is not available.

The most important method on socket io is the on() method which takes an event name and a callback function and executes that function when that event fires. In this case when i say $io->on(‘connection’) means when sockets is active and connected then fire $subject->notify().

The same also when i say $socket->on() inside $io->on(‘connection’) means when this event occurs inside active socket connection. To learn more about phpsocketio refer to this github link.

index.html

js/main.js

Here i displayed the three chart types and in main.js rendered them using the element id, then i invoked socket io from javascript using io() function passing the url which is “http://localhost:2020”. Note that this is the same port we mentioned earlier in server.php.

Using this socket instance i listened to events emitted from the server using io.on() function thereby renderd the graph using the response coming from the server.

To make the graphs refreshing we have to emit event to the server every particular seconds this is done with:

The server will catch this event and call notify observers again.

Running the example

In your project root folder start the socket server with:

This will display success started, if an error happened try to check the change the port number.

Then in the browser go to http://localhost/project-folder/ you will see the graphs running and updated every 2 seconds.

 

Download

 

 

 

Share this: