## Renderers

Apache log4php can log more than just string messages. If you try to log an object it will be converted to a string and logged. The component which converts Objects to strings in log4php is called a renderer.

### Default renderer

For example, let's say that an application uses a Person object, like this one:

    class Person {
        public $firstName;
        public $lastName;
        public $age;
    }

If you try logging it:

    $person = new Person();
    $person->firstName = 'John';
    $person->lastName = 'Doe';
    $person->age = 37;

    $logger = Logger::getLogger('main');
    $logger->info("Here comes the person:");
    $logger->info($person);

Log4php will render it using the default renderer and you will end the output will look something like:

    INFO - Here comes the person:
    INFO - Person Object
    (
        [firstName] => John
        [lastName] => Doe
        [age] => 37
    )

### Creating a custom renderer

In order to make log4php log the Person object in a more readable format, a custom renderer class can be defined which will convert Person objects to a string suitable for logging.

Let's call this renderer class PersonRenderer.

    /** All renderers must implement the LoggerRenderer interface. */
    class PersonRenderer implements LoggerRenderer {
        public function render($person) {
            return "{$person->firstName} {$person->lastName} ({$person->age})";
        }
    }

Now log4php has to be configured to use PersonRenderer for rendering Person objects. This is done in the configuration file.

- XML
- PHP

    <configuration xmlns="http://logging.apache.org/log4php/">
        <renderer renderedClass="Person" renderingClass="PersonRenderer" />
        <appender name="defualt" class="LoggerAppenderEcho" />
        <root>
            <appender_ref ref="defualt" />
        </root>
    </configuration>

    array(
        'renderers' => array(
            array(
                'renderedClass' => 'Person',
                'renderingClass' => 'PersonRenderer'
            )
        ),
        'appenders' => array(
            'default' => array(
                'class' => 'LoggerAppenderEcho',
            ),
        ),
        'rootLogger' => array(
            'appenders' => array('default'),
        ),
    )

If the same code is run as above, the following output is produced:

    INFO - Here comes the person:
    INFO - John Doe (37)

Which is much more readable than the default rendering.

### Overriding the default renderer

It is possible to set your own custom renderer as the default renderer.

For example, if you're not happy with the way in which the default renderer converts objects, you can create your own renderer:

    class MyRenderer implements LoggerRenderer {
        public function render($input) {
            return var_dump($input);
        }
    }

And set it as the default renderer in the configuration:

- XML
- PHP

    <configuration xmlns="http://logging.apache.org/log4php/">
        <defaultRenderer renderingClass="MyRenderer" />
        <appender name="defualt" class="LoggerAppenderEcho" />
        <root>
            <appender_ref ref="defualt" />
        </root>
    </configuration>

    array(
        'defaultRenderer' => 'MyRenderer',
        'appenders' => array(
            'default' => array(
                'class' => 'LoggerAppenderEcho',
            ),
        ),
        'rootLogger' => array(
            'appenders' => array('default'),
        ),
    )

Logging a Person object using this configuration will make log4php fall back to the newly defined default renderer, which uses `var_dump` instead of `print_r`, and the result will look like:

    INFO - Here comes the person:
    class Person#5 (3) {
      public $firstName =>
      string(4) "John"
      public $lastName =>
      string(3) "Doe"
      public $age =>
      int(37)
    }

### Class hierarchy

Object rendering follows the class hierarchy.

For example, if there is a class named Fruit, and classes Orange, Lemon and Apple all extend Fruit. When FruitRenderer is registered as renderer for the Fruit class, all subclasses of Fruit will also be rendered by FruitRenderer. Of course, it is possible to override this by registering OrangeRenderer as renderer for the Orange class.