View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFPROP:Proposal Zone Template}

{zone-data:component-name}
Zend_Log
{zone-data}

{zone-data:proposer-list}
[Martin Roest|mailto:martin@ibuildings.nl]
{zone-data}

{zone-data:liaison}
[~matthew]
{zone-data}

{zone-data:revision}
1.0 - 29 september 2008: Initial Draft.
{zone-data}

{zone-data:overview}
This proposition covers a new factory method in Zend_Log that eases the creation and configuration of the Zend_Log object.
{zone-data}

{zone-data:references}
{zone-data}

{zone-data:requirements}
{zone-data}

{zone-data:dependencies}
* zend_Log_Writer_*
* Zend_Log_Filter_*
{zone-data}

{zone-data:operation}
Enable the creation and setup of the Zend_Log object from a Zend_Config object similar the Zend_Db::factory()

A user is able to setup a configuration file with the help of Zend_Config creates the config object and passes the relevant section to the Zend_Log::factory(). The factory method will create the Zend_Log object and adds the configured and enabled log writers.

This allows easy configuration and enable/disable logwriters per config section.
{zone-data}

{zone-data:milestones}
* Milestone 1: Change the log writers to accept a Zend_Config object or Array when constructing the writer
* Milestone 2: Add the factory method
{zone-data}

{zone-data:class-list}
* Zend_Log
* Zend_Log_Writer_*
* Zend_Log_Filter_*
* Zend_Log_Exception
{zone-data}

{zone-data:use-cases}
||UC-01||

config.ini (The namespace property is only to indicate support for namespace prefix. It defaults to Zend_Log_Writer):
{code}
log.file.writerName = "Stream"
log.file.writerNamespace = "Zend_Log_Writer"
log.file.writerParams.stream = "/path/to/application.log"
log.file.filterName = "Priority"
log.file.filterParams.priority = "Zend_Log::CRIT"
log.file.filterParams.operator = "<="
log.firebug.writerName = "Firebug"
log.db.writerName = "Db"
log.db.writerParams.adapter "Mysqli"
log.db.writerParams.params.host = "localhost"
log.db.writerParams.params.username = "user"
log.db.writerParams.params.password = "pass"
log.db.writerParams.params.dbname = "dbname"
{code}

bootstrap/setup
{code}
require 'Zend/Log.php';
$logger = Zend_Log::factory($config->log);
{code}
{zone-data}

{zone-data:skeletons}

Zend_Log
{code}
/**
* Factory to construct the Zend_Log and add writers based on the
* configuration
*
* $config can be an array of an instance of Zend_Config
*
* @param mixed $config Array or instance of Zend_Config
* @return Zend_Log
*/
public static function factory($config = array())
{
if($config instanceof Zend_Config) {
$config = $config->toArray();
}

if(!is_array($config)) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Writer configuration must be an array or instance of Zend_Config!');
}

/** Do we have one or more writers configured? **/
if(!is_array(current($config))) {
$config = array($config);
}

$logger = new Zend_Log();

foreach($config as $writer) {

$writerName = self::getFullClassName($writer['writerName'], 'writerNamespace', $writer, 'Zend_Log_Writer');

/*
* Load the writer class. This throws an exception
* if the specified class cannot be loaded.
*/
@Zend_Loader::loadClass($writerName);

$writerConfig = (isset($writer['writerParams'])) ? $writer['writerParams'] : array();
$writerObj = new $writerName($writerConfig);

if(! $writerObj instanceof Zend_Log_Writer_Abstract) {
/**
* @see Zend_Log_Exception
*/
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("Writer class '$writerName' does not extend Zend_Log_Writer_Abstract");
}

if(isset($writer['filterName'])) {
$filterClassName = self::getFullClassName($writer['filterName'], 'filterNamespace', $writer , 'Zend_Log_Filter');

@Zend_Loader::loadClass($filterClassName);

$filterConfig = (isset($writer['filterParams'])) ? $writer['filterParams'] : array();
$filterObj = new $filterClassName($filterConfig);

if(! $filterObj instanceof Zend_Log_Filter_Interface) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("Filter class '$filterClassName' does not extend Zend_Log_Filter_Interface");
}

$writerObj->addFilter($filterObj);
}

$logger->addWriter($writerObj);
}
return $logger;
}

/**
* Get the full class name which can be used by the Zend_Loader
*
* @param string classname
* @param string namespace to search for
* @param array array with parameters
* @param string default namespace
*/
protected static function getFullClassName($className, $needle, Array $haystack, $defaultNamespace)
{
if(isset($haystack[$needle])) {
$defaultNamespace = $haystack[$needle];
}

$fullClassName = strtolower($defaultNamespace . '_' . $className);
$fullClassName = str_replace(' ', '_', ucwords(str_replace('_', ' ', $fullClassName)));
return $fullClassName;
}

{code}

Example of how to implement it with the Zend_Log_Writer_Db
{code}
/**
* Class constructor
*
* @param mixed $dbOrConfig Zend_Db_Adapter Database adapter instance or config array
* @param string $table Log table in database
* @param array $columnMap
*/
public function __construct($dbOrConfig, $table = null, $columnMap = null)
{
if(count(func_get_args()) == 1) {

if(!is_array($dbOrConfig)) {
throw new Zend_Log_Exception("Unsupported configuration. Pass a configuration array");
}

$this->_table = $dbOrConfig['table'];
unset($dbOrConfig['table']);

$this->_columnMap = $dbOrConfig['columnMap'];
unset($dbOrConfig['columnMap']);

/** Construct Zend_Db **/
require_once 'Zend/Db.php';
$this->_db = Zend_Db::factory($dbOrConfig);

} else {
$this->_db = $dbOrConfig;
$this->_table = $table;
$this->_columnMap = $columnMap;
}
}
{code}
{zone-data}

{zone-template-instance}]]></ac:plain-text-body></ac:macro>