View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFDEV:Zend Proposal Zone Template}
{composition-setup}
{zone-data:component-name}
Zend_Factory_Abstract
{zone-data}

{zone-data:proposer-list}
[~mikaelkael]
[Matthew Weier O'Phinney (Zend Liaison)|~matthew]
{zone-data}

{zone-data:revision}
0.1 - 17 March 2008: Initial proposal creation.
0.2 - 20 March 2008: Corrections and comments.
0.3 - 24 September 2008 : Corrections
{zone-data}

{zone-data:overview}
Zend_Factory_Abstract helps to create components by centralizing the code of creation which can apply to several components
{zone-data}

{zone-data:references}
* Zend_Db source code
* [Zend_Image_Barcode proposal|http://framework.zend.com/wiki/display/ZFPROP/Zend_Image_Barcode+-+Mickael+PERRAUD]
{zone-data}

{zone-data:requirements}
* This component *must not* break backward compatibility
* This component *will* create new element
{zone-data}

{zone-data:dependencies}
* Zend_Exception
* Zend_Loader
{zone-data}

{zone-data:operation}
When I began to write the code proposed in Zend_Image_Barcode, I looked Zend_Db and Zend_Form:
* Zend_Db for factory() method
* Zend_Form for __construct(), setOptions() and setConfig() methods.

And I saw that I entirely copied the code of Zend_Db factory() method with just strings changements.
So I propose to extract this code into Zend_Factory_Abstract and that the Zend_Db class and other components extend Zend_Factory_Abstract.

This proposal is just an extraction of the code of factory method of Zend_Db to be able to use for other components.
{zone-data}

{zone-data:milestones}
* Milestone 1: [design notes will be published here|http://framework.zend.com/wiki/display/ZFPROP/Zend_Factory]
* Milestone 2: Working prototype checked into the incubator supporting use cases #1, #2, ...
* Milestone 3: Working prototype checked into the incubator supporting use cases #3 and #4.
* Milestone 4: Unit tests exist, work, and are checked into SVN.
* Milestone 5: Initial documentation exists.
{zone-data}

{zone-data:class-list}
* Zend_Factory
{zone-data}

{zone-data:use-cases}
{zone-data}

{zone-data:skeletons}
{deck:id=Skeletons}
{card:label=Zend_Factory_Abstract}
{code:php}
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Loader
*/
require_once 'Zend/Loader.php';

/**
* Class for create component based on configuration
*
* @category Zend
* @package Zend
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Factory_Abstract
{

/**
* Factory for Zend_* classes
* (ex: 'Zend_Db' or 'Zend_Image_Barcode')
*
* First element is the type of element you want to create
* (ex: an 'adapter' or 'barcode')
*
* Second element is base class name of the element
* (ex: 'Zend_Db_Adapter' or 'Zend_Image_Barcode')
*
* Third argument is the name of the class that the element extends
* (ex: 'Zend_Db_Adapter_Abstract' or 'Zend_Image_Barcode_Abstract')
*
* Fourth argument may be a string containing the base of the element
* class name. This is case-insensitive.
* (ex: 'Mysqli' for 'Zend_Db_Adapter_Mysqli' or 'code39' for 'Zend_Image_Barcode_Code39')
*
* Fourth argument may alternatively be an object of type Zend_Config.
* The element class base name is read from the '$element_type' property.
* The element config parameters are read from the 'params' property.
*
* Fifth argument is optional and may be an associative array of key-value
* pairs. This is used as the argument to the element constructor.
*
* If the fourth argument is of type Zend_Config, it is assumed to contain
* all parameters, and the second argument is ignored.
*
* @param string $element_type Type of element you want to create
* @param string $element_namespace Base class name of the element
* @param string $instanceof Name of the class that the element extends
* @param mixed $adapter String name of base element class, or Zend_Config object.
* @param mixed $config OPTIONAL; an array or Zend_Config object with element parameters.
* @return object
* @throws Zend_Exception
*/
protected static function _factory ($element_type, $element_namespace, $instanceof, $element, $config = array(), $exception = null)
{
/*
* Convert Zend_Config argument to plain string
* adapter name and separate config object.
*/
if ($element instanceof Zend_Config) {
if (isset($element->params)) {
$config = $element->params->toArray();
}
if (isset($element->$element_type)) {
$type = $element_type;
$element = (string) $element->$type;
} else {
$element = null;
}
}
if ($exception === null) {
$exception = $element_namespace . '_Exception';
}
/*
* Verify that element parameters are in an array.
*/
if (! is_array($config)) {
Zend_Loader::loadClass($exception);
throw new $exception(ucfirst($element_type) . ' parameters must be in an array or a Zend_Config object');
}
/*
* Verify that an element name has been specified.
*/
if (! is_string($element) || empty($element)) {
Zend_Loader::loadClass($exception);
throw new $exception(ucfirst($this->element_type) . ' name must be specified in a string');
}
/*
* Form full element class name
*/
if (isset($config[$element_type . 'Namespace'])) {
$element_namespace = $config[$element_type . 'Namespace'];
unset($config[$element_type . 'Namespace']);
}
$elementName = strtolower($element_namespace . '_' . $element);
$elementName = str_replace(' ', '_', ucwords(str_replace('_', ' ', $elementName)));
/*
* Load the element class. This throws an exception
* if the specified class cannot be loaded.
*/
@Zend_Loader::loadClass($elementName);
/*
* Create an instance of the element class.
* Pass the config to the element class constructor.
*/
$elementObj = new $elementName($config);
/*
* Verify that the object created is a descendent of the abstract element type.
*/
if (! $elementObj instanceof $instanceof) {
Zend_Loader::loadClass($exception);
throw new $exception(ucfirst($element_type) . " class '$elementName' does not extend " . $instanceof);
}
return $elementObj;
}
}
{code}
{card}
{card:label=Zend_Db}
{code:php}
<?php

/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Db
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/


/**
* @see Zend_Loader
*/
require_once 'Zend/Factory/Abstract.php';


/**
* Class for connecting to SQL databases and performing common operations.
*
* @category Zend
* @package Zend_Db
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db extends Zend_Factory_Abstract
{
/**
* Use the PROFILER constant in the config of a Zend_Db_Adapter.
*/
const PROFILER = 'profiler';

/**
* Use the CASE_FOLDING constant in the config of a Zend_Db_Adapter.
*/
const CASE_FOLDING = 'caseFolding';

/**
* Use the AUTO_QUOTE_IDENTIFIERS constant in the config of a Zend_Db_Adapter.
*/
const AUTO_QUOTE_IDENTIFIERS = 'autoQuoteIdentifiers';

/**
* Use the INT_TYPE, BIGINT_TYPE, and FLOAT_TYPE with the quote() method.
*/
const INT_TYPE = 0;
const BIGINT_TYPE = 1;
const FLOAT_TYPE = 2;

/**
* PDO constant values discovered by this script result:
*
* $list = array(
* 'PARAM_BOOL', 'PARAM_NULL', 'PARAM_INT', 'PARAM_STR', 'PARAM_LOB',
* 'PARAM_STMT', 'PARAM_INPUT_OUTPUT', 'FETCH_LAZY', 'FETCH_ASSOC',
* 'FETCH_NUM', 'FETCH_BOTH', 'FETCH_OBJ', 'FETCH_BOUND',
* 'FETCH_COLUMN', 'FETCH_CLASS', 'FETCH_INTO', 'FETCH_FUNC',
* 'FETCH_GROUP', 'FETCH_UNIQUE', 'FETCH_CLASSTYPE', 'FETCH_SERIALIZE',
* 'FETCH_NAMED', 'ATTR_AUTOCOMMIT', 'ATTR_PREFETCH', 'ATTR_TIMEOUT',
* 'ATTR_ERRMODE', 'ATTR_SERVER_VERSION', 'ATTR_CLIENT_VERSION',
* 'ATTR_SERVER_INFO', 'ATTR_CONNECTION_STATUS', 'ATTR_CASE',
* 'ATTR_CURSOR_NAME', 'ATTR_CURSOR', 'ATTR_ORACLE_NULLS',
* 'ATTR_PERSISTENT', 'ATTR_STATEMENT_CLASS', 'ATTR_FETCH_TABLE_NAMES',
* 'ATTR_FETCH_CATALOG_NAMES', 'ATTR_DRIVER_NAME',
* 'ATTR_STRINGIFY_FETCHES', 'ATTR_MAX_COLUMN_LEN', 'ERRMODE_SILENT',
* 'ERRMODE_WARNING', 'ERRMODE_EXCEPTION', 'CASE_NATURAL',
* 'CASE_LOWER', 'CASE_UPPER', 'NULL_NATURAL', 'NULL_EMPTY_STRING',
* 'NULL_TO_STRING', 'ERR_NONE', 'FETCH_ORI_NEXT',
* 'FETCH_ORI_PRIOR', 'FETCH_ORI_FIRST', 'FETCH_ORI_LAST',
* 'FETCH_ORI_ABS', 'FETCH_ORI_REL', 'CURSOR_FWDONLY', 'CURSOR_SCROLL',
* 'ERR_CANT_MAP', 'ERR_SYNTAX', 'ERR_CONSTRAINT', 'ERR_NOT_FOUND',
* 'ERR_ALREADY_EXISTS', 'ERR_NOT_IMPLEMENTED', 'ERR_MISMATCH',
* 'ERR_TRUNCATED', 'ERR_DISCONNECTED', 'ERR_NO_PERM',
* );
*
* $const = array();
* foreach ($list as $name) {
* $const[$name] = constant("PDO::$name");
* }
* var_export($const);
*/
const ATTR_AUTOCOMMIT = 0;
const ATTR_CASE = 8;
const ATTR_CLIENT_VERSION = 5;
const ATTR_CONNECTION_STATUS = 7;
const ATTR_CURSOR = 10;
const ATTR_CURSOR_NAME = 9;
const ATTR_DRIVER_NAME = 16;
const ATTR_ERRMODE = 3;
const ATTR_FETCH_CATALOG_NAMES = 15;
const ATTR_FETCH_TABLE_NAMES = 14;
const ATTR_MAX_COLUMN_LEN = 18;
const ATTR_ORACLE_NULLS = 11;
const ATTR_PERSISTENT = 12;
const ATTR_PREFETCH = 1;
const ATTR_SERVER_INFO = 6;
const ATTR_SERVER_VERSION = 4;
const ATTR_STATEMENT_CLASS = 13;
const ATTR_STRINGIFY_FETCHES = 17;
const ATTR_TIMEOUT = 2;
const CASE_LOWER = 2;
const CASE_NATURAL = 0;
const CASE_UPPER = 1;
const CURSOR_FWDONLY = 0;
const CURSOR_SCROLL = 1;
const ERR_ALREADY_EXISTS = NULL;
const ERR_CANT_MAP = NULL;
const ERR_CONSTRAINT = NULL;
const ERR_DISCONNECTED = NULL;
const ERR_MISMATCH = NULL;
const ERR_NO_PERM = NULL;
const ERR_NONE = '00000';
const ERR_NOT_FOUND = NULL;
const ERR_NOT_IMPLEMENTED = NULL;
const ERR_SYNTAX = NULL;
const ERR_TRUNCATED = NULL;
const ERRMODE_EXCEPTION = 2;
const ERRMODE_SILENT = 0;
const ERRMODE_WARNING = 1;
const FETCH_ASSOC = 2;
const FETCH_BOTH = 4;
const FETCH_BOUND = 6;
const FETCH_CLASS = 8;
const FETCH_CLASSTYPE = 262144;
const FETCH_COLUMN = 7;
const FETCH_FUNC = 10;
const FETCH_GROUP = 65536;
const FETCH_INTO = 9;
const FETCH_LAZY = 1;
const FETCH_NAMED = 11;
const FETCH_NUM = 3;
const FETCH_OBJ = 5;
const FETCH_ORI_ABS = 4;
const FETCH_ORI_FIRST = 2;
const FETCH_ORI_LAST = 3;
const FETCH_ORI_NEXT = 0;
const FETCH_ORI_PRIOR = 1;
const FETCH_ORI_REL = 5;
const FETCH_SERIALIZE = 524288;
const FETCH_UNIQUE = 196608;
const NULL_EMPTY_STRING = 1;
const NULL_NATURAL = 0;
const NULL_TO_STRING = NULL;
const PARAM_BOOL = 5;
const PARAM_INPUT_OUTPUT = -2147483648;
const PARAM_INT = 1;
const PARAM_LOB = 3;
const PARAM_NULL = 0;
const PARAM_STMT = 4;
const PARAM_STR = 2;

public static function factory ($adapter, $config = array ()) {
return self::_factory('adapter', 'Zend_Db_Adapter', 'Zend_Db_Adapter_Abstract', $adapter, $config);
}
}

{code}
{card}

{card:label=Zend_Image_Barcode}
{code:php}
<?php
class Zend_Image_Barcode extends Zend_Factory_Abstract
{
public static function factory ($barcode, $config = array ()) {
return self::_factory('barcode','Zend_Image_Barcode','Zend_Image_Barcode_Abstract',$barcode, $config);
}
}
{code}
{card}
{deck}
{zone-data}

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