<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License. You may obtain a copy of the License at
 
         http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">

	<properties>
		<title>Renderers</title>
	</properties>

	<body>
		<section name="Renderers">
			<p>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 
			<em>renderer</em>.</p>
			
			<subsection name="Default renderer">
			
				<p>For example, let's say that an application uses a Person object, like this one:</p>
				
<pre class="prettyprint linenums"><![CDATA[
class Person {
    public $firstName;
    public $lastName;    
    public $age;
}
]]></pre>

				<p>If you try logging it:</p>
								
<pre class="prettyprint linenums"><![CDATA[
$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);
]]></pre>
				<p>Log4php will render it using the default renderer and you will end the output will look something 
				like:</p>
				
<pre class="prettyprint linenums"><![CDATA[
INFO - Here comes the person:
INFO - Person::__set_state(array(
   'firstName' => 'John',
   'lastName' => 'Doe',
   'age' => 37,
))
]]></pre>
				
			</subsection>
			
			<subsection name="Creating a custom renderer">
				<p>In order to make log4php render our Person object in a more readable format, we need to create a 
				custom renderer class which will convert Person objects to a string suitable for logging.</p>
				
				<p>Let's call our renderer class PersonRenderer.</p>
				
<pre class="prettyprint linenums"><![CDATA[
/** All object renderers must implement the LoggerRendererObject interface. */
class PersonRenderer implements LoggerRendererObject {
    public function render($person) {
        return "{$person->firstName} {$person->lastName} ({$person->age})";
    }
}
]]></pre>

				<p>Now log4php has to be configured to use PersonRenderer for rendering Person objects. This is done 
				in the configuration file.</p>
				
				<p>XML configuration:</p>
				
<pre class="prettyprint linenums"><![CDATA[
<configuration xmlns="http://logging.apache.org/log4php/">
    <renderer renderedClass="Person" renderingClass="PersonRenderer" />
    <appender name="defualt" class="LoggerAppenderEcho" />
    <root>
        <appender_ref ref="defualt" />
    </root>
</configuration>
]]></pre>
				
				<p>Equivalent PHP configuration:</p>
				
<pre class="prettyprint linenums"><![CDATA[
array(
    'renderers' => array(
        'renderedClass' => 'Person',
        'renderingClass' => 'PersonRenderer'
    ),
    'appenders' => array(
        'default' => array(
            'class' => 'LoggerAppenderEcho',
        ),
    ),
    'rootLogger' => array(
        'appenders' => array('default'),
    ),
);
]]></pre>
			
				<p>If the same code is run as above, the following output is produced:</p>
			
<pre class="prettyprint linenums"><![CDATA[
INFO - Here comes the person:
INFO - John Doe (37)
]]></pre>
				<p>Which is much more readable than the default rendering.</p>
			</subsection>
			
			<subsection name="Class hierarchy">
				<p>Object rendering follows the class hierarchy. </p>

				<p>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.</p>
			</subsection>
		</section>
	</body>
</document>
