HiveBrain v1.2.0
Get Started
← Back to all entries
snippetphpMinor

How to implement Publish-subscribe pattern in PHP?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
publishimplementphphowsubscribepattern

Problem

I have two classes, Database and Logger. Database is responsible for handling SQL queries, and Logger logs messages to an external file. Whenever the database executes an SQL query, I want Logger to log it. Right now my implementation looks something like this:

class Database {
        public function query($sql) {
            Logger::log($sql); 

            // ...
        }
    }

    class Logger {
        public static function log($msg) {
            // ...
        }
    }


But I feel that this is bad practice because Database shouldn't know about Logger. So instead I was thinking of creating a publisher-subscriber model (or something similar) where Database keeps a list of subscribers and has a method to subscribe to events, then it alerts subscribers when an event is fired (eg: when query is executed). I'm thinking something like this:

class Database {
        $subscribers = array(); 

        public function subscribe($something) {
            $subscribers.push($something);
        }

        private function alert_subscribers($msg, $event_type) {
            foreach ($s as $subscribers) { 
                // Alert all subscribers, somehow
            }
        }

        public function query($sql) {
            alert_subscribers($sql, SQL_QUERY_EXECUTED);

            // ...
        }
    }

    class Logger {
        public static function log($msg) {
            // ...
        }
    }


I want it to have multiple event types, so basically different groups are alerted when different events happen. I also don't know how the Logger should subscribe to Database under this design.

How should I go about implementing this? I'm not sure how to start.

Solution

There is nothing wrong with having the loggers everywhere. If you clutter all your classes with some kind of event notification it would look worst :)

But, Logger should not be called with a static method. You can create a pool of Loggers and your call will look like:

$log=Logger::get("Database");
$log->info("foo");


The big advantage is that you can put a configuration file in your project and define the log level of every logger independently.

According your questions you have really big plans. You want to write a template engine, a logging framework, an ORM and I guess somewhere in between your real application. Trust me when I tell you, you will fail. (I and most likely everybody else here tried it already :) ). For all your components there are mature frameworks out there. Find the one you like!!

Code Snippets

$log=Logger::get("Database");
$log->info("foo");

Context

StackExchange Code Review Q#21452, answer score: 4

Revisions (0)

No revisions yet.