PHP – Get method definition from object instance

When debugging complex applications you sometimes need to find out where a method of an object instance has been defined. With several levels of inheritance this can sometimes become quite time consuming. This is where PHP’s Reflektion API comes in handy. This API allows you to reverse-engineer classes, functions & methods.

$foo->bar();

If see in your code that an object instance $foo calls a method bar and you want to know in which file bar is defined.

You could use get_class($foo) to find the name of the class, then find the class definition in your code and then go backwards through the classes the class inherited from, to find the method definition. Using the Reflektion API allows you to find the file in one step.

$rc = new ReflectionClass($foo);
$method = $rc->getMethod('bar');
echo $method->getFileName();

Have a look at ReflectionMethod for more details.

PHP – Get method definition from object instance

Mock mail setup for Travis CI

Travis CI offers an excellent and free! continuous integration service. It runs your unit tests after you pushed your code to GitHub and deploys your changes to your staging/production servers if your tests pass.

One of the issues I run into while setting up my application with Travis was that my tests require email to work. By default tests sending emails will fail because the underlying mail system is disabled. In my case testing a ZF2 application, the error message was along those lines:

Configuration read from /home/travis/build/[...]/phpunit.xml
..............................sh: 1: -t: not found
E...........
Time: 5 seconds, Memory: 73.00Mb
There was 1 error:
1) UserTest\Controller\UserControllerTest::testRegisterActionValidUser
Zend\Mail\Exception\RuntimeException: Unable to send mail: Unknown error

To work around this you need to set up a mock mail service. This requires you to set up your .travis.yml according to this example:

language: php

php:
  - 5.3
  - 5.4
  - 5.5

before_install:
  - sudo apt-get update -qq
  - sudo apt-get install -y -qq postfix

before_script:
  - sudo service postfix stop
  - smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
  - echo -e '#!/usr/bin/env bash\nexit 0' | sudo tee /usr/sbin/sendmail
  - echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' | sudo tee "/home/travis/.phpenv/versions/`php -i | grep "PHP Version" | head -n 1 | grep -o -P '\d+\.\d+\.\d+.*'`/etc/conf.d/sendmail.ini"

notifications:
  email: false

This solution is based on the PHPMailer Travis configuration. Thanks!

Mock mail setup for Travis CI

ZF2 Flash Messages

A consistent message and notification implementation is one of the key building stones of modern web apps. ZF2 makes it very easy to implement this with the FlashMessenger controller plugin.

To integrate the flash messenger into your web app you need to follow 3 simple steps.

First, register the FlashMessengers messages as a view variable in your Module.php. The FlashMessenger supports namespaces which is very useful for having different styling for different message contexts. This example uses 3 different namespaces. You are free to implement as many as you want. I’m merging the default namespace with the info namespace which lets you assign general messages without the need to specify a namespace.

public function onBootstrap(MvcEvent $e)
{
    $eventManager = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    // Show flashmessages in the view
    $eventManager->attach(MvcEvent::EVENT_RENDER, function($e) {
        $flashMessenger = new FlashMessenger;

        $messages = array();

        $flashMessenger->setNamespace('success');
        if ($flashMessenger->hasMessages()) {
            $messages['success'] = $flashMessenger->getMessages();
        }
        $flashMessenger->clearMessages();

        $flashMessenger->setNamespace('info');
        if ($flashMessenger->hasMessages()) {
            $messages['info'] = $flashMessenger->getMessages();
        }
        $flashMessenger->clearMessages();

        $flashMessenger->setNamespace('default');
        if ($flashMessenger->hasMessages()) {
            if (isset($messages['info'])) {
                $messages['info'] = array_merge($messages['info'], $flashMessenger->getMessages());
            }
            else {
                $messages['info'] = $flashMessenger->getMessages();
            }
        }
        $flashMessenger->clearMessages();

        $flashMessenger->setNamespace('error');
        if ($flashMessenger->hasMessages()) {
            $messages['error'] = $flashMessenger->getMessages();
        }
        $flashMessenger->clearMessages();

        $e->getViewModel()->setVariable('flashMessages', $messages);
    });
}

To have the messages display consistently throughout your application it is best to add the message HTML to the layout template (in most cases module/Application/view/layout/layout.phtml).

<?php
  if ($this->flashMessages) {
    foreach ($this->flashMessages as $context => $messages) {
      echo '<div class="message-container ' . $context . '"><ul>';
      foreach ($messages as $message) {
        echo '<li>' . $message . '</li>';
      }
      echo '</ul></div>';
    }
  }
?>

Finally you can assign messages in your controller. You don’t need to specify a namespace if you want to assign messages to the info group.

$flashMessenger = $this->flashMessenger();
$flashMessenger->setNamespace('success');
$flashMessenger->addMessage('Foo!');
ZF2 Flash Messages