Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Config Usage in Constructors and Factories Component Proposal

Proposed Component Name Zend_Config Usage in Constructors and Factories
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Config Usage in Constructors and Factories
Proposers Bill Karwin
Revision 1.1 - 9 August 2007: Initial proposal. (wiki revision: 6)

Table of Contents

1. Overview

This is a proposal to establish standards for using Zend_Config to represent parameters for constructors and factories of Zend Framework components.

2. References

  • tbd

3. Component Requirements, Constraints, and Acceptance Criteria

  • Constructors or factory methods that accept arguments of scalars and arrays instead may accept a Zend_Config object containing similar data.
  • A constructor or factory method must not require a Zend_Config object without also accepting ordinary PHP scalars and arrays with similar data.
  • The property names in the Zend_Config object must match the names of arguments of the constructor or factory method.
  • If a constructor or factory method has multiple arguments, and the first argument is a Zend_Config object, then the properties contained in the Zend_Config object alone must be used. Secondary arguments must be ignored if the first argument is a Zend_Config object, even if the secondary arguments specify values for options that are not specified in properties of the Zend_Config object.

4. Dependencies on Other Framework Components

  • Zend_Config

5. Theory of Operation

PHP does not support strong typing or polymorphism like some languages (e.g. Java) do, by overloading methods based on the method signature. Only one implementation of a given method can exist in a given class. However, in PHP argument types can vary at runtime, and runtime code can interrogate an object for its type, whether that is a class type or a PHP native type like string. Using these characteristics of PHP, we may pass objects of different types to a PHP method, and the code in that method may utilize those objects differently based on their types.

We wish to use a Zend_Config object to store multiple values to be used as arguments to a method, and pass the Zend_Config object as a single argument, instead of the common use of PHP native types for multiple arguments.

In this proposal, we are addressing the cases of class constructors and factory methods, and using method arguments to specify attributes of the object we wish to create.

If the first argument is an instance of Zend_Config, the constructor or factory method assumes that it contains properties with names corresponding to the variable names in the traditional usage of the method.

In the example above, if $adapter instanceof Zend_Config is true, then interpret the properties of that object in the following way:

  • If the method argument is expected to be a scalar (e.g. $adapter is expected to be a string), access the config object's property as:
  • If the method argument is expected to be an associative array, access the config object's property as:
  • If the method argument is expected to be a plain integer-indexed array, not an associative array, the property names of the Zend_Config structure may be nonnegative integers, but actually may be anything, as long as they sort in the intended order. Access the config object's property as:
  • If the method argument may be either a scalar or an array, access the property of the Zend_Config object with $adapter->params, and test the type of the result. If the result is another instance of Zend_Config, convert it to an array with toArray(). Otherwise it is a scalar.

We must continue to support PHP native types for method arguments, to avoid creating a dependency of the method on the Zend_Config component. That is, the method still should be usable if Zend_Config is not available. All functionality of the method that is accessible by using a Zend_Config argument should be accessible when using plain argument types.

However, not all functionality is required to be supported by the Zend_Config argument. For example, if the method accepts object arguments or objects in array arguments, this is not supported when invoking the method with a Zend_Config argument. In these cases, if the object is a mandatory part of the method's arguments, it cannot support a Zend_Config argument.

Advantages:

Arguments for constructor and factory methods are easy to store in a file that can be read by Zend_Config and then passed without modification to the constructor or factory method.

Any combination of properties can be set or not set. This is more convenient than defining a long list of optional arguments for a method, because optional arguments are position-dependent, and one must supply default values for unused optional arguments to the left of the one for which you need to specify a value. This is similar to the advantage of using associative arrays.

Disadvantages:

We lose the ability to declare in the method signature that a given argument is mandatory. All arguments after the first must be optional. We must write additional code in the method for mandatory arguments, to check that they are set and throw an exception if they aren't. In standard argument usage, this is done simply by not giving the argument a default value; thus the argument is mandatory and omitting it from the method call results in a PHP error.

We lose the ability to declare in the method signature default values for optional method arguments. We must write additional code in the method to set default values for a given property if that property does not exist in the Zend_Config method argument. In standard argument usage, this is done simply by giving a default value for the argument, to be assigned in cases when the argument is omitted from the method call.

The usage does not support any arguments or values in array arguments that may be objects.

6. Milestones / Tasks

  • Milestone 1: [DONE] Publish proposal.
  • Milestone 2: Revise proposal, approve for incubator development.
  • Milestone 3: Implement support for Zend_Config in constructor and factory methods where appropriate.

7. Class Index

  • Zend_Db (for example)

8. Use Cases

UC01: Using factory method in traditional way
UC02: Using Zend_Config in place of traditional arguments
UC03: Using Zend_Config from a file

config.ini:

PHP code:

UC04: Using Zend_Config overrides any other arguments

9. Class Skeletons

This proposal doesn't require any new classes, but changes argument processing for existing classes. Below is code for use in Zend_Db::factory().

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Sep 04, 2007

    <p>Looks interesting, however for users to figure out which methods can be used with configs and which can't could be a bit confusing. Unless we mandate all factories to work with config. </p>

  2. Sep 14, 2007

    <p>To ensure the most flexibility, I'd augment this with an additional check for the $config variable to test for either an array or an ArrayObject for all self-checks:-</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    if ($config instanceof Zend_Config) {
    $config = $config->toArray();
    }

    if (!(is_array($config) || $config instanceof ArrayAccess)) {
    throw new Exception('Configuration parameters must be supplied as an array');
    }]]></ac:plain-text-body></ac:macro>
    <p>Another vote here from me to enforce the Zend_Config option on all Zend Framework Components where an array would be expected to supply configuration parameters.</p>

  3. Jan 23, 2008

    <p>I have the feeling that this proposal is completely covered by <ac:link><ri:page ri:content-title="Zend_Config_Configurable" /></ac:link>. Also it may be sees as shameless plug <ac:emoticon ac:name="smile" /></p>

  4. Jun 02, 2008

    <p>We can make it independent of Zend_Config and more open/flexible if we cast to objects instead of array. I.e. the Zend_Mail_Storage classes have this in their constructor:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    if (is_array($params)) {
    $params = (object)$params;
    }
    // access parameters as $params->name
    ]]></ac:plain-text-body></ac:macro>

    <p>Their is nothing specific to Zend_Config here, $params can be of any class with public properties or __get(), like SimpleXML, an ArrayObject with ARRAY_AS_PROPS set or if you want to do something crazy a Zend_Mail_Message class with the parameters as headers.</p>

  5. Oct 21, 2010

    <p>Maybe a part of this problem might be addressed by the concept of <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Options+-+Werner+Mollentze">Zend_Options</a>?</p>

  6. Feb 07, 2011

    <p>Archiving this proposal, feel free to recover it when you want to work on it again. For more details see <a href="http://framework.zend.com/wiki/display/ZFDEV/Archiving+of+abandoned+proposals+(Feb+5+2011)">this email</a>.</p>