Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was trying to explain the mediator pattern to a new developer, and ended up writing a simple event mediator. Thoughts?


class EventMediator {
    private $events = array();

    public function attach($event, Closure $callback) {
        if(!is_string($event)) throw new \InvalidArgumentException();

        $event = strtolower(trim($event));
        if(!isset($this->events[$event])) $this->events[$event] = array();

        $this->events[$event][] = $callback;

        return $this;

    public function trigger($event, $data = null) {
        if(!is_string($event)) throw new \InvalidArgumentException();

        $event = strtolower(trim($event));
        if(!isset($this->events[$event])) return false;

        foreach($this->events[$event] as $callback) $callback($event, $data);

        return true;

    public function getEvents() { return $this->events; }


trait EventfulTrait {

    private $eventMediator;

    public function attachEventMediator(EventMediator $eventMediator) {
        $this->eventMediator = $eventMediator;
        return $this;

    public function detachEventMediator() {
        $this->eventMediator = null;
        return $this;

    public function getEventMediator() {
        return $this->eventMediator;

    public function attachEvent($name, $callback) {
        if(!is_null($this->eventMediator)) $this->eventMediator->attach($name, $callback);
        return $this;

    public function triggerEvent($name, $data = null) {
        if(!is_null($this->eventMediator)) return $this->eventMediator->trigger($name, $data);
        return false;


require "EventMediator.php";
require "EventfulTrait.php";

class Log {
    public function write($message) {
        echo "{$message}\n";

class Eventful {
    use EventfulTrait;

    private $log;

    public function __construct() { $this->log = new Log(); }

    public function attachLoadEvent() {
        $self = $this;
        $log  = $this->log;
            "load", function() use($self, $log) {
                $log->write("log message");

    public function doSomething() {

    public function doSomethingElse() {

    public function runOutOfNames() { echo "load\n"; }

$eventMediator = new EventMediator();
$eventMediator->attach("event1", function() { echo "event1\n"; });
$eventMediator->attach("event2", function() { echo "event2\n"; });
$eventMediator->attach("done", function() { echo "done\n"; });

$eventful = new Eventful();


This will echo:

log message
log message
log message
share|improve this question

I think this is a very clean looking code base, so congrats getting that down. I also think that the the way you implemented the pattern worked out very well.

I don't have much to say, it's mostly just formatting.

  • Throughout, you insist on keeping block sections condensed to one line. It's perfectly okay to add the brackets and break apart the code into multiple lines.
  • In attach(), you return the current object. I don't see why you're doing so as in the example you didn't utilize this feature. Don't write code that's not in use yet!
  • You might consider moving strtolower(trim($event)) to a function with the appropriate parameters. Don't repeat yourself.
  • Why is !isset($this->events[$event]) returning false. I would expect an exception to be throw, that way if the code needs to watch for other errors later on, false could mean many things.
  • attachEventMediator I think needs a new name. You're not just attaching a mediator, you're setting it. If you had support for multiple mediators, then attach would be appropriate. Similarly, detach should be remove or delete.
  • Perhaps in replace of echo "{$message}\n";, you could use the sprintf function. I personally think this would clear up the line.
  • To improve your dependency injection in Eventful, pass the Log as a parameter.
  • Will the message always be "log message"? Maybe pass that as an argument.

Overall I think the code is well-written. A couple more comments and better example code could have improved it even more!

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.