PHP
  Home arrow PHP arrow Page 4 - An Introduction to the Observer Patter...
Dev Shed Forums 
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Sun Developer Network 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Mobile Linux 
App Generation ROI 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

An Introduction to the Observer Pattern in PHP
By: Alejandro Gervasio
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 13
    2006-07-17

    Table of Contents:
  • An Introduction to the Observer Pattern in PHP
  • Building a practical example
  • Adding a basic error logger
  • Applying the Observer design pattern

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    An Introduction to the Observer Pattern in PHP - Applying the Observer design pattern


    (Page 4 of 4 )

    As I explained in the previous section, when a basic error login class was added to the message handling application, the independence of their objects was compromised; therefore, an alternative approach should be implemented to avoid this issue. For this reason, I’ll apply the Observer pattern, thus the application can retain the objects’ independence without sacrificing functionality.

    Here’s how he application now looks, after implementing the Observer pattern:

      // define the abstract 'MessageObserver' interface
      interface MessageObserver{
        function displayStatus(MessageSaver $obj,$notifMsg);
      }
      // define 'ErrorLogger' class
      class ErrorLogger implements MessageObserver{
        function displayStatus(MessageSaver $obj,$notifMsg){
            echo __CLASS__.' notified the following error message:
    '.$notifMsg;
        }
      }
      // define 'MessageConverter' class
      class MessageConverter{
        private $message;
        public function __construct($message){
            if(!is_string($message)){
                throw new Exception('Input message must be a
    string!');
            }
            $this->message=strtoupper($message);
        }
        // return uppercased message
        public function getMessage(){
            return $this->message;
        }
      }
      // define 'MessageSaver' class
      class MessageSaver{
        const LENGTH_ERROR='Invalid length of message.';
        const WORD_ERROR='Message contains invalid words.';
        private $msgPath='defaultPath/messages.txt';
        private $badWords=array('BAD WORD1','BAD WORD2','BAD WORD3');
        private $observers=array();
        private $msgConv;
        public function __construct(MessageConverter $msgConv){
            $this->msgConv=$msgConv;
        }
        // add new observer
        public function addObserver(MessageObserver $obj){
            $this->observers["$obj"]=$obj;
        }
        // remove existent observer
        public function removeObserver(MessageObserver $obj){
            delete($this->observers["$obj"]);
        }
        // notify to all the observers that an error occurred
        protected function notifyObservers($notifMsg){
            foreach($this->observers as $observer){
                $observer->displayStatus($this,$notifMsg);
            }
        }
        public function save(){
            // check for message length
            if(strlen($this->msgConv->getMessage())>255){
                // notify length error to all the observers
                $this->notifyObservers(self::LENGTH_ERROR);
            }
            // check for bad words
            if(in_array($this->msgConv->getMessage(),$this-
    >badWords)){
                // notify word error to all the observers
                $this->notifyObservers(self::WORD_ERROR);
            }
            // checking was passed, then save message to file
            if(!$fp=fopen($this->msgPath,'a+')){
                throw new Exception('Error opening messages file.');
            }
            fwrite($fp,$this->msgConv->getMessage()."n");
            fclose($fp);
        }
      }

    As you can see, the above application looks slightly different when compared to the previous incarnation. All the changes that I introduced are minor yet significant, therefore pay close attention to the following explanation.

    In order to apply the Observer pattern, first I defined a “MessageObserver” interface, which exposes only an abstract “displayStatus()” method. Next, I created a basic “ErrorLogger” class, which implements this interface and also inherits the previous method.

    Here’s where you can spot the first difference. This class actually won’t log any errors, but instead will display notices from the respective “MessageSaver” objects. So, where’s the advantage in defining the logger class like this? Well, by doing so, all the objects of type “MessageSaver” will be responsible only for saving messages to a text file, period. Any eventual errors will be sent to the observer object (in this case the “ErrorLogger” class), and only this object will decide the course of action to take. Do you now see how all the involved objects are decoupled from the whole application? I hope you do.

    Once the observer class was created, I redefined the “MessageSaver” class, in order to add the “addObserver()”,“removeObserver()” and “notifyObserver()” methods to it. As you may have guessed, the first two methods simply add and remove observer objects from the class in question, assuming that the application will implement eventually other observers.

    The “notifyObserver()” method loops over all the observers (for this example, I have only one) and calls their “displayStatus()” method, in this way showing all the notices that were sent by the “MessageSaver” object when trying to save an offending message. This condition is demonstrated by the “save()” method, which is listed below:

      public function save(){
        // check for message length
        if(strlen($this->msgConv->getMessage())>255){
            // notify length error to all the observers
            $this->notifyObservers(self::LENGTH_ERROR);
        }
        // check for bad words
        if(in_array($this->msgConv->getMessage(),$this->badWords)){
            // notify word error to all the observers
            $this->notifyObservers(self::WORD_ERROR);
        }
        // checking was passed, then save message to file
        if(!$fp=fopen($this->msgPath,'a+')){
            throw new Exception('Error opening messages file.');
        }
        fwrite($fp,$this->msgConv->getMessage()."n");
        fclose($fp);
      }

    At this point, the previous example allowed me to apply the Observer pattern, which results in the decoupling of all the pertinent objects. It also results in the implementation of a handy mechanism for reflecting all the objects' changes at the application’s core level, and without having to write convoluted code!

    Want to see how the application works, after coding the respective observer class? Right, here’s an example:

      try{
        // instantiate 'MessageConverter' object
        $msgConv=new MessageConverter('bad word1');
        // instantiate 'MessageSaver' object
        $msgSaver=new MessageSaver($msgConv);
        // add 'MessageObserver'
        $msgSaver->addObserver(new ErrorLogger());
        // save message to file
        $msgSaver->save();
      }
      catch(Exception $e){
        echo $e->getMessage();
        exit();
      }

    The above script displays the following message:

    ErrorLogger notified the following error message: Message
    contains invalid words.

    As you can see, the “MessageObserver” class displays the above notification, since I passed an invalid message to the “MessageConverter” class. This demonstrates the power of the Observer pattern.

    As homework, try adding more observers to the “ErrorLogger” class, and see what happens in each case, so you gain a solid grasp of this pattern. It’s really fun!

    To wrap up

    In this first article, you learned how to apply the Observer pattern inside a simple PHP application. Of course, feel free to treat the source code like a starting example and introduce some improvements to it. It’s the best way to grasp the concepts for how this pattern works.

    In the next tutorial, I’ll show you how to apply the Observer pattern in a real-world case: server-side data validation. See you there! 


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · If you're a PHP developer that wishes to learn how to implement the observer pattern...
     

       

    PHP ARTICLES

    - Authentication Scripts for a User Management...
    - Utilizing the Use Keyword for Namespaces in ...
    - Building a User Management Application
    - Working With Different Namespaces in PHP 5
    - User Management Explained: Overview
    - Using Namespaces in PHP 5
    - Database Security: Guarding Against SQL Inje...
    - Building a Modular Exception Class in PHP 5
    - Database and Password Security for Web Appli...
    - Handling MySQL Data Set Failures in PHP 5
    - Building Site Registration for Web Applicati...
    - Intercepting Customized Exceptions in PHP 5
    - Securing Your Web Application Against Attacks
    - Sub Classing Exceptions in PHP 5
    - Authentication for Web Application Security





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT