Quantcast

'Centralized option loader' component proposal

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

'Centralized option loader' component proposal

Mihai Bojin
Hello Everyone,

I'll get right to the point.
I had the idea of building a centralized option loader component for ZF.
Below I will describe 5 use cases of current ZF classes that load options from config objects.
At the end of this email I will describe what I think the centralized option loader component should do.

1. I noticed throughout the Zend Framework that a number of classes support loading options passed by Zend_Config, but nearly all convert the received object to an array using something like:

        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        }

2. Also a common pattern I observed is that the method definition accepts a number of options, for example an array or a Zend_Config object and then throws an exception if the passed parameter was neither of the two like for example in Zend/Cache/Core.php, this is handled like this:

        if (!is_array($options)) {
            Zend_Cache::throwException("Options passed were not an array"
            . " or Zend_Config instance.");
        }


3. Another possibility that is sometimes found is that like in Zend/Barcode.php

        if ($barcode instanceof Zend_Config) {
            if (isset($barcode->rendererParams)) {
                $rendererConfig = $barcode->rendererParams->toArray();
            }
            if (isset($barcode->renderer)) {
                $renderer = (string) $barcode->renderer;
            }
            if (isset($barcode->barcodeParams)) {
                $barcodeConfig = $barcode->barcodeParams->toArray();
            }
            if (isset($barcode->barcode)) {
                $barcode = (string) $barcode->barcode;
            } else {
                $barcode = null;
            }
        }

where the config object is separated into multiple parameters and then each one is processed differently.


4. Some components check for required values that should have been passed in the config object, see Zend/Db/Adapter/Abstract.php:function _checkRequiredOptions(array $config)

    protected function _checkRequiredOptions(array $config)
    {
        // we need at least a dbname
        if (! array_key_exists('dbname', $config)) {
            /** @see Zend_Db_Adapter_Exception */
            require_once 'Zend/Db/Adapter/Exception.php';
            throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
        }

        if (! array_key_exists('password', $config)) {
        ...
        }

        if (! array_key_exists('username', $config)) {
        ...
        }
    }

and throw an Exception if a certain parameter was not set in the config object.

5. And finally there is the possibility of setting default values of behaviours that is now handled by hardcoding different constants and/or private or protected class properties.


My idea is why not centralize all these behaviours into an Loader class that would be able to handle some or all of the following:

- passed parameter identification (is it an array, a Zend_Config object, ...)
- conversion to array (which is the generally accepted way in ZF of working with config options)
- default options (init the config array with some default values that get overwritten by the actual passed parameters)
- required options (if one or more of the required params is not set, throw an Exception)
- exception handling (set which exceptions and messages to throw for different use cases, or use default messages for the few standard cases, for ease of debugging, smaller footprint of the framework and other benefits)
- parameter splitting (return an array of options, or multiple options and/or arrays of options)

Do you think this is a good idea?
Would the framework be easier to understand if the option loading would be the same for all classes?

If you have other ideas of what this component might do, please share your thoughts!


Have a good Sunday and a good week,

Best regards,

Mihai Bojin
PHP Developer
Y!: mihai.bojin
GTalk: mihai.bojin
Skype: mihai.bojin
Linkedin: http://ro.linkedin.com/in/mihaibojin
Facebook: http://www.facebook.com/MihaiBojin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

umpirsky
I like your idea.

Not that this will be useful for the framework itself, but also for code
written in our apps.
---
Regards,
Saša Stamenković


On Sun, Feb 6, 2011 at 2:26 PM, Mihai Bojin <[hidden email]> wrote:

> Hello Everyone,
>
> I'll get right to the point.
> I had the idea of building a centralized option loader component for ZF.
> Below I will describe 5 use cases of current ZF classes that load options
> from config objects.
> At the end of this email I will describe what I think the centralized
> option loader component should do.
>
> 1. I noticed throughout the Zend Framework that a number of classes support
> loading options passed by Zend_Config, but nearly all convert the received
> object to an array using something like:
>
>        if ($options instanceof Zend_Config) {
>            $options = $options->toArray();
>        }
>
> 2. Also a common pattern I observed is that the method definition accepts a
> number of options, for example an array or a Zend_Config object and then
> throws an exception if the passed parameter was neither of the two like for
> example in Zend/Cache/Core.php, this is handled like this:
>
>        if (!is_array($options)) {
>            Zend_Cache::throwException("Options passed were not an array"
>            . " or Zend_Config instance.");
>        }
>
>
> 3. Another possibility that is sometimes found is that like in
> Zend/Barcode.php
>
>        if ($barcode instanceof Zend_Config) {
>            if (isset($barcode->rendererParams)) {
>                $rendererConfig = $barcode->rendererParams->toArray();
>            }
>            if (isset($barcode->renderer)) {
>                $renderer = (string) $barcode->renderer;
>            }
>            if (isset($barcode->barcodeParams)) {
>                $barcodeConfig = $barcode->barcodeParams->toArray();
>            }
>            if (isset($barcode->barcode)) {
>                $barcode = (string) $barcode->barcode;
>            } else {
>                $barcode = null;
>            }
>        }
>
> where the config object is separated into multiple parameters and then each
> one is processed differently.
>
>
> 4. Some components check for required values that should have been passed
> in the config object, see Zend/Db/Adapter/Abstract.php:function
> _checkRequiredOptions(array $config)
>
>    protected function _checkRequiredOptions(array $config)
>    {
>        // we need at least a dbname
>        if (! array_key_exists('dbname', $config)) {
>            /** @see Zend_Db_Adapter_Exception */
>            require_once 'Zend/Db/Adapter/Exception.php';
>            throw new Zend_Db_Adapter_Exception("Configuration array must
> have a key for 'dbname' that names the database instance");
>        }
>
>        if (! array_key_exists('password', $config)) {
>        ...
>        }
>
>        if (! array_key_exists('username', $config)) {
>        ...
>        }
>    }
>
> and throw an Exception if a certain parameter was not set in the config
> object.
>
> 5. And finally there is the possibility of setting default values of
> behaviours that is now handled by hardcoding different constants and/or
> private or protected class properties.
>
>
> My idea is why not centralize all these behaviours into an Loader class
> that would be able to handle some or all of the following:
>
> - passed parameter identification (is it an array, a Zend_Config object,
> ...)
> - conversion to array (which is the generally accepted way in ZF of working
> with config options)
> - default options (init the config array with some default values that get
> overwritten by the actual passed parameters)
> - required options (if one or more of the required params is not set, throw
> an Exception)
> - exception handling (set which exceptions and messages to throw for
> different use cases, or use default messages for the few standard cases, for
> ease of debugging, smaller footprint of the framework and other benefits)
> - parameter splitting (return an array of options, or multiple options
> and/or arrays of options)
>
> Do you think this is a good idea?
> Would the framework be easier to understand if the option loading would be
> the same for all classes?
>
> If you have other ideas of what this component might do, please share your
> thoughts!
>
>
> Have a good Sunday and a good week,
>
> Best regards,
>
> Mihai Bojin
> PHP Developer
> Y!: mihai.bojin
> GTalk: mihai.bojin
> Skype: mihai.bojin
> Linkedin: http://ro.linkedin.com/in/mihaibojin
> Facebook: http://www.facebook.com/MihaiBojin
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Mihai Bojin
Good point!

We now need to find use cases that I missed.
What do you think other use cases would be for this component. What about it's name? I'm thinking of something under Zend_Loader_,
maybe Zend_Loader_Config...

Best regards,
Mihai


On Feb 7, 2011, at 11:21 AM, Саша Стаменковић wrote:

> I like your idea.
>
> Not that this will be useful for the framework itself, but also for code written in our apps.
> ---
> Regards,
> Saša Stamenković
>
>
> On Sun, Feb 6, 2011 at 2:26 PM, Mihai Bojin <[hidden email]> wrote:
> Hello Everyone,
>
> I'll get right to the point.
> I had the idea of building a centralized option loader component for ZF.
> Below I will describe 5 use cases of current ZF classes that load options from config objects.
> At the end of this email I will describe what I think the centralized option loader component should do.
>
> 1. I noticed throughout the Zend Framework that a number of classes support loading options passed by Zend_Config, but nearly all convert the received object to an array using something like:
>
>        if ($options instanceof Zend_Config) {
>            $options = $options->toArray();
>        }
>
> 2. Also a common pattern I observed is that the method definition accepts a number of options, for example an array or a Zend_Config object and then throws an exception if the passed parameter was neither of the two like for example in Zend/Cache/Core.php, this is handled like this:
>
>        if (!is_array($options)) {
>            Zend_Cache::throwException("Options passed were not an array"
>            . " or Zend_Config instance.");
>        }
>
>
> 3. Another possibility that is sometimes found is that like in Zend/Barcode.php
>
>        if ($barcode instanceof Zend_Config) {
>            if (isset($barcode->rendererParams)) {
>                $rendererConfig = $barcode->rendererParams->toArray();
>            }
>            if (isset($barcode->renderer)) {
>                $renderer = (string) $barcode->renderer;
>            }
>            if (isset($barcode->barcodeParams)) {
>                $barcodeConfig = $barcode->barcodeParams->toArray();
>            }
>            if (isset($barcode->barcode)) {
>                $barcode = (string) $barcode->barcode;
>            } else {
>                $barcode = null;
>            }
>        }
>
> where the config object is separated into multiple parameters and then each one is processed differently.
>
>
> 4. Some components check for required values that should have been passed in the config object, see Zend/Db/Adapter/Abstract.php:function _checkRequiredOptions(array $config)
>
>    protected function _checkRequiredOptions(array $config)
>    {
>        // we need at least a dbname
>        if (! array_key_exists('dbname', $config)) {
>            /** @see Zend_Db_Adapter_Exception */
>            require_once 'Zend/Db/Adapter/Exception.php';
>            throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
>        }
>
>        if (! array_key_exists('password', $config)) {
>        ...
>        }
>
>        if (! array_key_exists('username', $config)) {
>        ...
>        }
>    }
>
> and throw an Exception if a certain parameter was not set in the config object.
>
> 5. And finally there is the possibility of setting default values of behaviours that is now handled by hardcoding different constants and/or private or protected class properties.
>
>
> My idea is why not centralize all these behaviours into an Loader class that would be able to handle some or all of the following:
>
> - passed parameter identification (is it an array, a Zend_Config object, ...)
> - conversion to array (which is the generally accepted way in ZF of working with config options)
> - default options (init the config array with some default values that get overwritten by the actual passed parameters)
> - required options (if one or more of the required params is not set, throw an Exception)
> - exception handling (set which exceptions and messages to throw for different use cases, or use default messages for the few standard cases, for ease of debugging, smaller footprint of the framework and other benefits)
> - parameter splitting (return an array of options, or multiple options and/or arrays of options)
>
> Do you think this is a good idea?
> Would the framework be easier to understand if the option loading would be the same for all classes?
>
> If you have other ideas of what this component might do, please share your thoughts!
>
>
> Have a good Sunday and a good week,
>
> Best regards,
>
> Mihai Bojin
> PHP Developer
> Y!: mihai.bojin
> GTalk: mihai.bojin
> Skype: mihai.bojin
> Linkedin: http://ro.linkedin.com/in/mihaibojin
> Facebook: http://www.facebook.com/MihaiBojin
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

weierophinney
Administrator
In reply to this post by Mihai Bojin
-- Mihai Bojin <[hidden email]> wrote
(on Sunday, 06 February 2011, 03:26 PM +0200):
> I'll get right to the point.
>
> I had the idea of building a centralized option loader component for
> ZF.  Below I will describe 5 use cases of current ZF classes that load
> options from config objects.  At the end of this email I will describe
> what I think the centralized option loader component should do.

<snip - analysis of a number of patterns>

One thing I've realized with ZF2 development is that we shouldn't be
testing on Zend_Config, but simply Traversable. The reason is that this
opens us up to using other

> My idea is why not centralize all these behaviours into an Loader
> class that would be able to handle some or all of the following:

"Loader" is a namespace dealing with class and plugin loading. I'd argue
this should be under the "Config" namespace, or a new "Options"
namespace. And note the word "namespace" -- this could only be
considered for ZF2.

One issue with such an approach, however, is it introduces a dependency
for every class that has options parsing. This has a lot of
implications:

 * Is it possible to inject the options handler? If so, how? (This is a
   question that the more fanatic folks of loose coupling and/or
   dependency injection will ask.)
 * How do you document the dependency? (Probably an import statement is
   enough.)
 * Additional dependencies == harder to install individual components in
   a standalone configuration.

That said, I'm not completely against the idea. I noticed with
Zend\Session (ZF2's session component) that it was far easier to have a
base configuration object and interface as it simplified my code -- I
could assume that both standard keys and defaults were present. The
system is still extensible and injectible as well.

> - passed parameter identification (is it an array, a Zend_Config
>   object, ...)
> - conversion to array (which is the generally accepted way in ZF of
>   working with config options)
> - default options (init the config array with some default values that
>   get overwritten by the actual passed parameters)
> - required options (if one or more of the required params is not set,
>   throw an Exception)
> - exception handling (set which exceptions and messages to throw for
>   different use cases, or use default messages for the few standard
>   cases, for ease of debugging, smaller footprint of the framework and
>   other benefits)
> - parameter splitting (return an array of options, or multiple options
>   and/or arrays of options)

One idea that has been brought up by a few contributors, and which I've
seen in ez/Zeta Components, is the idea of having a "config object" per
component (and/or subcomponent). The idea is that doing so helps
document the available options. (ez/Zeta does so by having "struct"
objects with public members for available options (and defaults).)

The main drawback I see to this is it makes usage slightly more verbose:

    $options = new Component\Options($config);
    $object  = new Component($options);

That said, I think there are some easy ways to approach this. Instead of
type-hinting on the options object in the constructor, the constructor
can do some checks:

    public function __construct($options = null)
    {
        if (null !== $options) {
            if (!$options instanceof Options) {
                $options = new Options($options);
            }
            $this->setOptions($options);
        }
    }

The "Options" class for each component could then be either a standalone
class with its own handling, or we could provide a base "Options" class
with default behavior (and potentially a PHP 5.4 trait to mix-in).

I'm personally of the mind that the component should fulfill your fourth
(and possibly fifth) point above, however: the Options object should
only aggregate the options; the component decides what it needs, and how
to deal with missing options.

Thoughts?

> Do you think this is a good idea?
> Would the framework be easier to understand if the option loading
> would be the same for all classes?
>
> If you have other ideas of what this component might do, please share
> your thoughts!

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Renan de Lima
On 7 February 2011 14:24, Matthew Weier O'Phinney <[hidden email]> wrote:

> -- Mihai Bojin <[hidden email]> wrote
> (on Sunday, 06 February 2011, 03:26 PM +0200):
>> I'll get right to the point.
>>
>> I had the idea of building a centralized option loader component for
>> ZF.  Below I will describe 5 use cases of current ZF classes that load
>> options from config objects.  At the end of this email I will describe
>> what I think the centralized option loader component should do.
>
> <snip - analysis of a number of patterns>
>
> One thing I've realized with ZF2 development is that we shouldn't be
> testing on Zend_Config, but simply Traversable. The reason is that this
> opens us up to using other

agreed, centralized options loader should not depends of any class,
Zend\Config should implements Traversable

configuration container != centralized options loader

> about extendibility and injectability

Again, i think there is no way to centralized everything, it could be
no good, especially because we should avoid super-hero-class to solve
everything. Option container, required options, default options,
initialization setting. Tthose are not the same, maybe we should
implement some basic abstract classes to make easer handling every
issue and interfaces to decide what to do with objects.

Mihai Bojin give us a good point, i think we can talk more about this
and achieve some code for that, i hope

about object configuration there is a proposal
http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
there is a "Configurable" interface in discussion there, maybe this
could be a seed for this discussion
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Mihai Bojin
In reply to this post by weierophinney
Hello everyone,

On Feb 7, 2011, at 6:24 PM, Matthew Weier O'Phinney wrote:

> -- Mihai Bojin <[hidden email]> wrote
> (on Sunday, 06 February 2011, 03:26 PM +0200):
>> I'll get right to the point.
>>
>> I had the idea of building a centralized option loader component for
>> ZF.  Below I will describe 5 use cases of current ZF classes that load
>> options from config objects.  At the end of this email I will describe
>> what I think the centralized option loader component should do.
>
> <snip - analysis of a number of patterns>
>
> One thing I've realized with ZF2 development is that we shouldn't be
> testing on Zend_Config, but simply Traversable. The reason is that this
> opens us up to using other
>
>> My idea is why not centralize all these behaviours into an Loader
>> class that would be able to handle some or all of the following:
>
> "Loader" is a namespace dealing with class and plugin loading. I'd argue
> this should be under the "Config" namespace, or a new "Options"
> namespace. And note the word "namespace" -- this could only be
> considered for ZF2.
>
> One issue with such an approach, however, is it introduces a dependency
> for every class that has options parsing. This has a lot of
> implications:
>
> * Is it possible to inject the options handler? If so, how? (This is a
>   question that the more fanatic folks of loose coupling and/or
>   dependency injection will ask.)
> * How do you document the dependency? (Probably an import statement is
>   enough.)
> * Additional dependencies == harder to install individual components in
>   a standalone configuration.
>
> That said, I'm not completely against the idea. I noticed with
> Zend\Session (ZF2's session component) that it was far easier to have a
> base configuration object and interface as it simplified my code -- I
> could assume that both standard keys and defaults were present. The
> system is still extensible and injectible as well.

The dependency injection point is a good one, haven't thought of it yesterday...

Considering all said below, I think Zend_Options would be a better choice, because
this class should not be directly related to Zend_Config, nor for that matter be limited to working
only with Zend_Config objects.

A trait could be implemented in Zend_Config, to allow other objects implementing a common
interface to be type-casted into a Zend_Config.
 

>
>> - passed parameter identification (is it an array, a Zend_Config
>>  object, ...)
>> - conversion to array (which is the generally accepted way in ZF of
>>  working with config options)
>> - default options (init the config array with some default values that
>>  get overwritten by the actual passed parameters)
>> - required options (if one or more of the required params is not set,
>>  throw an Exception)
>> - exception handling (set which exceptions and messages to throw for
>>  different use cases, or use default messages for the few standard
>>  cases, for ease of debugging, smaller footprint of the framework and
>>  other benefits)
>> - parameter splitting (return an array of options, or multiple options
>>  and/or arrays of options)
>
> One idea that has been brought up by a few contributors, and which I've
> seen in ez/Zeta Components, is the idea of having a "config object" per
> component (and/or subcomponent). The idea is that doing so helps
> document the available options. (ez/Zeta does so by having "struct"
> objects with public members for available options (and defaults).)
>
> The main drawback I see to this is it makes usage slightly more verbose:
>
>    $options = new Component\Options($config);
>    $object  = new Component($options);
>
> That said, I think there are some easy ways to approach this. Instead of
> type-hinting on the options object in the constructor, the constructor
> can do some checks:
>
>    public function __construct($options = null)
>    {
>        if (null !== $options) {
>            if (!$options instanceof Options) {
>                $options = new Options($options);
>            }
>            $this->setOptions($options);
>        }
>    }
>

How do you feel about initializing all components with a Zend_Config object, that will be able to cast itself to
an Options object. That would of course mean coupling between Zend_Config and Zend_Options and it's children.

My personal opinion is that people rely too much on arrays in PHP (also throughout the Zend Framework),
and that could change by allowing only initialization through Zend Config objects.

class Component
{
        const DEFAULT_OPTIONS_CLASS = 'Component\Options';
        private $_options = null;
       
        public function __construct(Zend_Config $config = null)
        {
                if (null !== $config) {
                        $this->_options = $config->toOptions(self::DEFAULT_OPTIONS_CLASS);
                }
        }
}

// usage example
$component = new Component(new Zend_Config_Ini('/path/to/filename'));



> The "Options" class for each component could then be either a standalone
> class with its own handling, or we could provide a base "Options" class
> with default behavior (and potentially a PHP 5.4 trait to mix-in).

Providing one or more traits to implement, would be helpful and would allow some flexibility for anyone who requires it.

> I'm personally of the mind that the component should fulfill your fourth
> (and possibly fifth) point above, however: the Options object should
> only aggregate the options; the component decides what it needs, and how
> to deal with missing options.

One of these traits could be to specify:
- a required set of options/parameters that need to be set in the Options object at one point (when calling a trigger method)
- a list of Exceptions to throw for each missing option


>
> Thoughts?
>
>> Do you think this is a good idea?
>> Would the framework be easier to understand if the option loading
>> would be the same for all classes?
>>
>> If you have other ideas of what this component might do, please share
>> your thoughts!
>
> --
> Matthew Weier O'Phinney
> Project Lead            | [hidden email]
> Zend Framework          | http://framework.zend.com/
> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Ralph Schindler-2

>
> My personal opinion is that people rely too much on arrays in PHP (also throughout the Zend Framework),
> and that could change by allowing only initialization through Zend Config objects.

I am not sure why this is a bad thing.  In all my years, I've never
really needed anything more than a nested array to model my
configuration data.  What behavior would you need inside your "config"
object that is not already possible with an array.

The array ("structure") is one of those things that defines PHP.  We use
PHP's b/c they are an important idiom in all the work we do with PHP.
I'd be interested to hear why you think relying on array's is a bad thing.


>> The "Options" class for each component could then be either a standalone
>> class with its own handling, or we could provide a base "Options" class
>> with default behavior (and potentially a PHP 5.4 trait to mix-in).
>
> Providing one or more traits to implement, would be helpful and would allow some flexibility for anyone who requires it.
>
>> I'm personally of the mind that the component should fulfill your fourth
>> (and possibly fifth) point above, however: the Options object should
>> only aggregate the options; the component decides what it needs, and how
>> to deal with missing options.
>
> One of these traits could be to specify:
> - a required set of options/parameters that need to be set in the Options object at one point (when calling a trigger method)
> - a list of Exceptions to throw for each missing option

PHP 5.4 is a LONG way out.  While traits might be in the distribution,
ZF2 is targeting 5.3 usage patterns.  That's not to say things cannot be
architectured now in a way that in the future they can easily be
refactored out into a trait.

-ralph
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Mihai Bojin

On Feb 7, 2011, at 7:41 PM, Ralph Schindler wrote:

>
>>
>> My personal opinion is that people rely too much on arrays in PHP (also throughout the Zend Framework),
>> and that could change by allowing only initialization through Zend Config objects.
>
> I am not sure why this is a bad thing.  In all my years, I've never really needed anything more than a nested array to model my configuration data.  What behavior would you need inside your "config" object that is not already possible with an array.
>
> The array ("structure") is one of those things that defines PHP.  We use PHP's b/c they are an important idiom in all the work we do with PHP. I'd be interested to hear why you think relying on array's is a bad thing.
>
Don't get me wrong. I love PHP arrays and the flexibility they provide.
However it is easy for programmers to code in an "I'll just use some n-level array to store that data" fashion.

Using objects means controlling what data goes in and what data comes out (and in what format).
You can control the allowed set of options that can go in, and how they are stored in the object.
You can also do some processing on the passed in data, it all depends what you will do with it next.

I think the most important aspect is what that configuration data will be used for and how will it happen.
If we think on Zend_Db::factory() where some basic configuration is passed in order to start a connection to a database,
probably an array would be best.

If however you think about Zend_Paginator::factory(), where initialization data can be passed in a number of ways and formats,
and then it creates a new adapter to which it passes some of the configuration data, I think a smart object would be better.
It could, for example, help the component by lazy loading some of it's options, or doing some automatic processing only
on actual component runtime.

Mihai

>
>>> The "Options" class for each component could then be either a standalone
>>> class with its own handling, or we could provide a base "Options" class
>>> with default behavior (and potentially a PHP 5.4 trait to mix-in).
>>
>> Providing one or more traits to implement, would be helpful and would allow some flexibility for anyone who requires it.
>>
>>> I'm personally of the mind that the component should fulfill your fourth
>>> (and possibly fifth) point above, however: the Options object should
>>> only aggregate the options; the component decides what it needs, and how
>>> to deal with missing options.
>>
>> One of these traits could be to specify:
>> - a required set of options/parameters that need to be set in the Options object at one point (when calling a trigger method)
>> - a list of Exceptions to throw for each missing option
>
> PHP 5.4 is a LONG way out.  While traits might be in the distribution, ZF2 is targeting 5.3 usage patterns.  That's not to say things cannot be architectured now in a way that in the future they can easily be refactored out into a trait.
>
> -ralph

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Wil Moore III
This post has NOT been accepted by the mailing list yet.
In reply to this post by weierophinney
weierophinney wrote
...we shouldn't be testing on Zend_Config, but simply Traversable.
I agree 100%.

weierophinney wrote
The main drawback I see to this is it makes usage slightly more verbose:

    $options = new Component\Options($config);
    $object  = new Component($options);
I'd love to see this adopted here. Yes, it is slightly more verbose, but I believe the benefits outweigh that minor inconvenience.

weierophinney wrote
I'm personally of the mind that the component should fulfill your fourth (and possibly fifth) point above, however: the Options object should only aggregate the options; the component decides what it needs, and how to deal with missing options.
+1

--
Wil Moore III

Best Practices for Working with Open-Source Developers
http://www.faqs.org/docs/artu/ch19s02.html

Why is Bottom-posting better than Top-posting:
http://www.caliburn.nl/topposting.html

DO NOT TOP-POST and DO trim your replies:
http://linux.sgms-centre.com/misc/netiquette.php#toppost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Wil Moore III
This post has NOT been accepted by the mailing list yet.
In reply to this post by Ralph Schindler-2
Ralph Schindler-2 wrote
I am not sure why this is a bad thing.  In all my years, I've never really needed anything more than a nested array to model my configuration data.  What behavior would you need inside your "config"
object that is not already possible with an array.
I wouldn't go so far as to call associative arrays bad. They have many uses.

That being said, there is functionality that you can wrap into an object that you can't wrap into a plain associative array.

If you need to look-up a value via Regex, you'll want an object. For example, lets say you want to write a quick and dirty MVC router (route container). So, the common might be to write route/uri patterns into an associative array value. This means that the matching logic is written outside of the container. I like seeing the matching logic built into the container. If you have an object that extends RegexIterator, you can use it's features to find your matches.

From a consumer point of view, in the end, this is a simpler API to have to deal with. You put in some options, and you get back a container that knows how to handle itself.

With a plain associative array, you are stuck writing a lot more procedural code than you might like.

Ralph Schindler-2 wrote
The array ("structure") is one of those things that defines PHP.  We use PHP's b/c they are an important idiom in all the work we do with PHP. I'd be interested to hear why you think relying on array's is a bad thing.
True; however, I think it is that same idiom or staple if you will, of the language that is a liability. It is a security blanket that causes us to forget that there are likely better ways to solve a particular problem.

I don't hate associative arrays (hashes elsewhere). In fact, I think they are the right thing to use 70% of the time. I just think that the 30% of the time where they are less useful, we are forgetting to look elsewhere.
--
Wil Moore III

Best Practices for Working with Open-Source Developers
http://www.faqs.org/docs/artu/ch19s02.html

Why is Bottom-posting better than Top-posting:
http://www.caliburn.nl/topposting.html

DO NOT TOP-POST and DO trim your replies:
http://linux.sgms-centre.com/misc/netiquette.php#toppost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

weierophinney
Administrator
In reply to this post by Ralph Schindler-2
-- Ralph Schindler <[hidden email]> wrote
(on Monday, 07 February 2011, 11:41 AM -0600):

> > My personal opinion is that people rely too much on arrays in PHP
> > (also throughout the Zend Framework), and that could change by
> > allowing only initialization through Zend Config objects.
>
> I am not sure why this is a bad thing.  In all my years, I've never
> really needed anything more than a nested array to model my
> configuration data.  What behavior would you need inside your
> "config" object that is not already possible with an array.
>
> The array ("structure") is one of those things that defines PHP.  We
> use PHP's b/c they are an important idiom in all the work we do with
> PHP. I'd be interested to hear why you think relying on array's is a
> bad thing.

The main arguments are:

* Typos. If you mis-spell a key, debugging is difficult. This wouldn't
  necessarily go away with the proposed functionality, as throwing
  exceptions on unknown options is not a good idea, either.

  (As an example, Zend_Cache used to do this. When we created the
  Cache_Manager class, we quickly discovered a problem: in situations
  where you use Zend_Config inheritance, it's not uncommon to merge in
  options from a different adapter -- and Zend_Cache was then throwing
  exceptions. The lesson learned is that throwing exceptions on unknown
  options led to inflexible designs.)

* IDE hinting. No IDEs I'm aware of define a standard format for
  documenting expected array keys via docblock annotations -- which
  means you get no help from your IDE when passing an array of options.

* Expectations within your options-aware code. We create a lot of
  boiler-plate code for generating default arguments, testing for
  existence of options, etc. Having an object representing your
  configuration options can actually simplify a lot of code, letting you
  focus instead on the functionality it exposes, and not on the
  mechanics of optional behavior.

Don't get me wrong -- I love arrays, too -- and particularly how
flexible and fast they are. However, when dealing with object oriented
code, they can often create _more_ work.

> >>The "Options" class for each component could then be either a standalone
> >>class with its own handling, or we could provide a base "Options" class
> >>with default behavior (and potentially a PHP 5.4 trait to mix-in).
> >
> >Providing one or more traits to implement, would be helpful and would
> >allow some flexibility for anyone who requires it.
> >
> >>I'm personally of the mind that the component should fulfill your fourth
> >>(and possibly fifth) point above, however: the Options object should
> >>only aggregate the options; the component decides what it needs, and how
> >>to deal with missing options.
> >
> >One of these traits could be to specify:
> >- a required set of options/parameters that need to be set in the
> >  Options object at one point (when calling a trigger method)
> >- a list of Exceptions to throw for each missing option
>
> PHP 5.4 is a LONG way out.  While traits might be in the
> distribution, ZF2 is targeting 5.3 usage patterns.  That's not to
> say things cannot be architectured now in a way that in the future
> they can easily be refactored out into a trait.

Yes and no -- traits are already accepted, and while they'll undergo a
few modifications in the coming weeks and months, the basic
functionality is known at this time -- and we can certainly start
providing some forward-compatible features such as traits for folks to
mix into their own code.

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Wil Moore III
This post has NOT been accepted by the mailing list yet.
weierophinney wrote
...throwing exceptions on unknown options is not a good idea, either.
I recall hearing this argument a few times and I do see the logic, yet I do feel like there could be some middle-ground. The reason I bring this up is that while I like the flexibility, I can see a scenario where you have multiple adapters configured across configuration environments (e.g. SQLITE in test vs MySQL everywhere else). Suppose this is the case and those adapter have an option named the same, but in actuality, are very different. By blindly accepting the left over option, you may be inadvertently configuring something you didn't want. That could be quite a pain to debug as it is super subtle.

Of course, this isn't a problem in most cases as a component usually does nothing with extra options. It is only in cases where the names are exactly the same. I suppose that is quite an edge case, but I wanted to put it out there as I don't believe it is as unlikely as one would like to believe.

I do agree with your other bullet items.
--
Wil Moore III

Best Practices for Working with Open-Source Developers
http://www.faqs.org/docs/artu/ch19s02.html

Why is Bottom-posting better than Top-posting:
http://www.caliburn.nl/topposting.html

DO NOT TOP-POST and DO trim your replies:
http://linux.sgms-centre.com/misc/netiquette.php#toppost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Goran Jurić
In reply to this post by weierophinney
On 7.2.2011. 20:14, Matthew Weier O'Phinney wrote:

> * Expectations within your options-aware code. We create a lot of
>    boiler-plate code for generating default arguments, testing for
>    existence of options, etc. Having an object representing your
>    configuration options can actually simplify a lot of code, letting you
>    focus instead on the functionality it exposes, and not on the
>    mechanics of optional behavior.
>
> Don't get me wrong -- I love arrays, too -- and particularly how
> flexible and fast they are. However, when dealing with object oriented
> code, they can often create _more_ work.

Exactly and I really like your suggestion on using ezComponents style of
component-aware
options. Presence of must have options can then be moved from the
component into the
option objects getter methods. This alone would make the rest of the
code much cleaner, not
to mention the added bonus of IDE autocompletion and discovery of options.

>> PHP 5.4 is a LONG way out.  While traits might be in the
>> distribution, ZF2 is targeting 5.3 usage patterns.  That's not to
>> say things cannot be architectured now in a way that in the future
>> they can easily be refactored out into a trait.
> Yes and no -- traits are already accepted, and while they'll undergo a
> few modifications in the coming weeks and months, the basic
> functionality is known at this time -- and we can certainly start
> providing some forward-compatible features such as traits for folks to
> mix into their own code.

I do not know much about the 5.4 release date, but with Debian Squeeze
being release just this
weekend (with PHP 5.3), that is at least 2 more year till the next
version of Debian that can push
new versions of PHP. CentOS is yet to release version 6 which moves from
5.1.6 to 5.3. But I
guess some planning ahead wouldn't heart.

Regards,

Goran Juric
http://gogs.info/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

weierophinney
Administrator
-- Goran Juric <[hidden email]> wrote
(on Monday, 07 February 2011, 10:55 PM +0100):

> On 7.2.2011. 20:14, Matthew Weier O'Phinney wrote:
> > > distribution, ZF2 is targeting 5.3 usage patterns.  That's not to
> > > PHP 5.4 is a LONG way out.  While traits might be in the
> > > say things cannot be architectured now in a way that in the future
> > > they can easily be refactored out into a trait.
> > Yes and no -- traits are already accepted, and while they'll undergo a
> > few modifications in the coming weeks and months, the basic
> > functionality is known at this time -- and we can certainly start
> > providing some forward-compatible features such as traits for folks to
> > mix into their own code.
>
> I do not know much about the 5.4 release date, but with Debian Squeeze
> being release just this weekend (with PHP 5.3), that is at least 2
> more year till the next version of Debian that can push new versions
> of PHP. CentOS is yet to release version 6 which moves from 5.1.6 to
> 5.3. But I guess some planning ahead wouldn't heart.

Clarification: we wouldn't utilize traits *within* ZF code yet, but we
could offer some ready-made traits for *consumption* by ZF users. As
such, the framework would be compatible with 5.3, while giving some
forwards-compatibility features for 5.4.

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Wil Moore III
This post has NOT been accepted by the mailing list yet.
This post was updated on .
weierophinney wrote
Clarification: we wouldn't utilize traits *within* ZF code yet, but we could offer some ready-made traits for *consumption* by ZF users. As such, the framework would be compatible with 5.3, while giving some forwards-compatibility features for 5.4.
I love the way current ZF allows helpers/plug-ins to be overridden with user implementations. Assuming there will be more of the same going forward, traits can be used for further augmentation of provided components. In other words, even without ZF directly utilizing traits, just having them available in PHP 5.3.x will be useful in conjunction with ZF usage patterns.
--
Wil Moore III

Best Practices for Working with Open-Source Developers
http://www.faqs.org/docs/artu/ch19s02.html

Why is Bottom-posting better than Top-posting:
http://www.caliburn.nl/topposting.html

DO NOT TOP-POST and DO trim your replies:
http://linux.sgms-centre.com/misc/netiquette.php#toppost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

keith Pope-4
In reply to this post by weierophinney
On 7 February 2011 22:05, Matthew Weier O'Phinney <[hidden email]> wrote:

> -- Goran Juric <[hidden email]> wrote
> (on Monday, 07 February 2011, 10:55 PM +0100):
>> On 7.2.2011. 20:14, Matthew Weier O'Phinney wrote:
>> > > distribution, ZF2 is targeting 5.3 usage patterns.  That's not to
>> > > PHP 5.4 is a LONG way out.  While traits might be in the
>> > > say things cannot be architectured now in a way that in the future
>> > > they can easily be refactored out into a trait.
>> > Yes and no -- traits are already accepted, and while they'll undergo a
>> > few modifications in the coming weeks and months, the basic
>> > functionality is known at this time -- and we can certainly start
>> > providing some forward-compatible features such as traits for folks to
>> > mix into their own code.
>>
>> I do not know much about the 5.4 release date, but with Debian Squeeze
>> being release just this weekend (with PHP 5.3), that is at least 2
>> more year till the next version of Debian that can push new versions
>> of PHP. CentOS is yet to release version 6 which moves from 5.1.6 to
>> 5.3. But I guess some planning ahead wouldn't heart.
>
> Clarification: we wouldn't utilize traits *within* ZF code yet, but we
> could offer some ready-made traits for *consumption* by ZF users. As
> such, the framework would be compatible with 5.3, while giving some
> forwards-compatibility features for 5.4.

I would put my vote on component level options objects, for me I see
too main advantages:

1. IDE autocompletion, this should ease our learning curve
2. API documentation, as long as the options classes were explicit the
generated API docs would make it easy to see all available options.

Both of these deal with good documentation and learning curve, one of
the most common complaints about ZF, though personally I have always
found the reference + source code more than enough :)

How were we thinking of handling defaults, I am leaning toward the
fact that the component should be responsible for its defaults, this
way we can make use of lazy injection etc.

>
> --
> Matthew Weier O'Phinney
> Project Lead            | [hidden email]
> Zend Framework          | http://framework.zend.com/
> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>



--
------------
http://www.thepopeisdead.com
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

set class on DT with default form decorators

Matthieu Larcher
Hi,

I'm not sure it's the right adress to send to, but here comes :

I found out there is no way to set a class on the DT html element
created by the default form decorators.
This can be seen in Zend_Form_Decorator_Label on line 319 : no class
option is passed to the HtmlTag decorator.

I've altered this file so that it accepts a "tagClass" option to go
along with the "tag" option and be used when calling HtmlTag.

I'd like to submit this small enhancement to the code.

I've issue a ticker in the zf issue tracker (
http://framework.zend.com/issues/browse/ZF-11035 ), signed the CLA and
got it approved.

Now I'd just like to know how to submit the altered
Zend_Form_Decorator_Label so that it gets included in future versions.

Anyone can tell me where to go from there ? (I just want to know where
and how to post the file, please don't tell me I need to read the whole
wiki about contributing)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Mihai Bojin
In reply to this post by Mihai Bojin
Hello Matthew,

Do you think it would be better to refactor all components into using only Zend_Config + type hinting in each constructor,
or allowing any type in the constructor and then creating the Options objects around this data ?

I am interested in writing up a proposal and the code for this component for ZF2, so naturally I seek your advice!


Thank you,
Mihai


On Feb 7, 2011, at 7:26 PM, Mihai Bojin wrote:

> Hello everyone,
>
> On Feb 7, 2011, at 6:24 PM, Matthew Weier O'Phinney wrote:
>
>> -- Mihai Bojin <[hidden email]> wrote
>> (on Sunday, 06 February 2011, 03:26 PM +0200):
>>> I'll get right to the point.
>>>
>>> I had the idea of building a centralized option loader component for
>>> ZF.  Below I will describe 5 use cases of current ZF classes that load
>>> options from config objects.  At the end of this email I will describe
>>> what I think the centralized option loader component should do.
>>
>> <snip - analysis of a number of patterns>
>>
>> One thing I've realized with ZF2 development is that we shouldn't be
>> testing on Zend_Config, but simply Traversable. The reason is that this
>> opens us up to using other
>>
>>> My idea is why not centralize all these behaviours into an Loader
>>> class that would be able to handle some or all of the following:
>>
>> "Loader" is a namespace dealing with class and plugin loading. I'd argue
>> this should be under the "Config" namespace, or a new "Options"
>> namespace. And note the word "namespace" -- this could only be
>> considered for ZF2.
>>
>> One issue with such an approach, however, is it introduces a dependency
>> for every class that has options parsing. This has a lot of
>> implications:
>>
>> * Is it possible to inject the options handler? If so, how? (This is a
>>   question that the more fanatic folks of loose coupling and/or
>>   dependency injection will ask.)
>> * How do you document the dependency? (Probably an import statement is
>>   enough.)
>> * Additional dependencies == harder to install individual components in
>>   a standalone configuration.
>>
>> That said, I'm not completely against the idea. I noticed with
>> Zend\Session (ZF2's session component) that it was far easier to have a
>> base configuration object and interface as it simplified my code -- I
>> could assume that both standard keys and defaults were present. The
>> system is still extensible and injectible as well.
>
> The dependency injection point is a good one, haven't thought of it yesterday...
>
> Considering all said below, I think Zend_Options would be a better choice, because
> this class should not be directly related to Zend_Config, nor for that matter be limited to working
> only with Zend_Config objects.
>
> A trait could be implemented in Zend_Config, to allow other objects implementing a common
> interface to be type-casted into a Zend_Config.
>  
>>
>>> - passed parameter identification (is it an array, a Zend_Config
>>>  object, ...)
>>> - conversion to array (which is the generally accepted way in ZF of
>>>  working with config options)
>>> - default options (init the config array with some default values that
>>>  get overwritten by the actual passed parameters)
>>> - required options (if one or more of the required params is not set,
>>>  throw an Exception)
>>> - exception handling (set which exceptions and messages to throw for
>>>  different use cases, or use default messages for the few standard
>>>  cases, for ease of debugging, smaller footprint of the framework and
>>>  other benefits)
>>> - parameter splitting (return an array of options, or multiple options
>>>  and/or arrays of options)
>>
>> One idea that has been brought up by a few contributors, and which I've
>> seen in ez/Zeta Components, is the idea of having a "config object" per
>> component (and/or subcomponent). The idea is that doing so helps
>> document the available options. (ez/Zeta does so by having "struct"
>> objects with public members for available options (and defaults).)
>>
>> The main drawback I see to this is it makes usage slightly more verbose:
>>
>>    $options = new Component\Options($config);
>>    $object  = new Component($options);
>>
>> That said, I think there are some easy ways to approach this. Instead of
>> type-hinting on the options object in the constructor, the constructor
>> can do some checks:
>>
>>    public function __construct($options = null)
>>    {
>>        if (null !== $options) {
>>            if (!$options instanceof Options) {
>>                $options = new Options($options);
>>            }
>>            $this->setOptions($options);
>>        }
>>    }
>>
>
> How do you feel about initializing all components with a Zend_Config object, that will be able to cast itself to
> an Options object. That would of course mean coupling between Zend_Config and Zend_Options and it's children.
>
> My personal opinion is that people rely too much on arrays in PHP (also throughout the Zend Framework),
> and that could change by allowing only initialization through Zend Config objects.
>
> class Component
> {
> const DEFAULT_OPTIONS_CLASS = 'Component\Options';
> private $_options = null;
>
> public function __construct(Zend_Config $config = null)
> {
> if (null !== $config) {
> $this->_options = $config->toOptions(self::DEFAULT_OPTIONS_CLASS);
> }
> }
> }
>
> // usage example
> $component = new Component(new Zend_Config_Ini('/path/to/filename'));
>
>
>
>> The "Options" class for each component could then be either a standalone
>> class with its own handling, or we could provide a base "Options" class
>> with default behavior (and potentially a PHP 5.4 trait to mix-in).
>
> Providing one or more traits to implement, would be helpful and would allow some flexibility for anyone who requires it.
>
>> I'm personally of the mind that the component should fulfill your fourth
>> (and possibly fifth) point above, however: the Options object should
>> only aggregate the options; the component decides what it needs, and how
>> to deal with missing options.
>
> One of these traits could be to specify:
> - a required set of options/parameters that need to be set in the Options object at one point (when calling a trigger method)
> - a list of Exceptions to throw for each missing option
>
>
>>
>> Thoughts?
>>
>>> Do you think this is a good idea?
>>> Would the framework be easier to understand if the option loading
>>> would be the same for all classes?
>>>
>>> If you have other ideas of what this component might do, please share
>>> your thoughts!
>>
>> --
>> Matthew Weier O'Phinney
>> Project Lead            | [hidden email]
>> Zend Framework          | http://framework.zend.com/
>> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

weierophinney
Administrator
-- Mihai Bojin <[hidden email]> wrote
(on Tuesday, 08 February 2011, 08:28 PM +0200):
> Do you think it would be better to refactor all components into using only
> Zend_Config + type hinting in each constructor,
> or allowing any type in the constructor and then creating the Options objects
> around this data ?

Allowing any type, and then creating the options objects. The rationale
is that will allow systems such as Symfony2's DI container or other such
systems to interact with the ZF code, without needing to change their
functionality (or require a wrapper around them to support ZF code).

> I am interested in writing up a proposal and the code for this component for
> ZF2, so naturally I seek your advice!
>
>
> Thank you,
> Mihai
>
>
> On Feb 7, 2011, at 7:26 PM, Mihai Bojin wrote:
>
>
>     Hello everyone,
>
>     On Feb 7, 2011, at 6:24 PM, Matthew Weier O'Phinney wrote:
>
>
>         -- Mihai Bojin <[hidden email]> wrote
>         (on Sunday, 06 February 2011, 03:26 PM +0200):
>
>             I'll get right to the point.
>
>
>
>             I had the idea of building a centralized option loader component
>             for
>
>             ZF.  Below I will describe 5 use cases of current ZF classes that
>             load
>
>             options from config objects.  At the end of this email I will
>             describe
>
>             what I think the centralized option loader component should do.
>
>
>         <snip - analysis of a number of patterns>
>
>         One thing I've realized with ZF2 development is that we shouldn't be
>         testing on Zend_Config, but simply Traversable. The reason is that this
>         opens us up to using other
>
>
>             My idea is why not centralize all these behaviours into an Loader
>
>             class that would be able to handle some or all of the following:
>
>
>         "Loader" is a namespace dealing with class and plugin loading. I'd
>         argue
>         this should be under the "Config" namespace, or a new "Options"
>         namespace. And note the word "namespace" -- this could only be
>         considered for ZF2.
>
>         One issue with such an approach, however, is it introduces a dependency
>         for every class that has options parsing. This has a lot of
>         implications:
>
>         * Is it possible to inject the options handler? If so, how? (This is a
>           question that the more fanatic folks of loose coupling and/or
>           dependency injection will ask.)
>         * How do you document the dependency? (Probably an import statement is
>           enough.)
>         * Additional dependencies == harder to install individual components in
>           a standalone configuration.
>
>         That said, I'm not completely against the idea. I noticed with
>         Zend\Session (ZF2's session component) that it was far easier to have a
>         base configuration object and interface as it simplified my code -- I
>         could assume that both standard keys and defaults were present. The
>         system is still extensible and injectible as well.
>
>
>     The dependency injection point is a good one, haven't thought of it
>     yesterday...
>
>     Considering all said below, I think Zend_Options would be a better choice,
>     because
>     this class should not be directly related to Zend_Config, nor for that
>     matter be limited to working
>     only with Zend_Config objects.
>
>     A trait could be implemented in Zend_Config, to allow other objects
>     implementing a common
>     interface to be type-casted into a Zend_Config.
>      
>
>
>
>             - passed parameter identification (is it an array, a Zend_Config
>
>              object, ...)
>
>             - conversion to array (which is the generally accepted way in ZF of
>
>              working with config options)
>
>             - default options (init the config array with some default values
>             that
>
>              get overwritten by the actual passed parameters)
>
>             - required options (if one or more of the required params is not
>             set,
>
>              throw an Exception)
>
>             - exception handling (set which exceptions and messages to throw
>             for
>
>              different use cases, or use default messages for the few standard
>
>              cases, for ease of debugging, smaller footprint of the framework
>             and
>
>              other benefits)
>
>             - parameter splitting (return an array of options, or multiple
>             options
>
>              and/or arrays of options)
>
>
>         One idea that has been brought up by a few contributors, and which I've
>         seen in ez/Zeta Components, is the idea of having a "config object" per
>         component (and/or subcomponent). The idea is that doing so helps
>         document the available options. (ez/Zeta does so by having "struct"
>         objects with public members for available options (and defaults).)
>
>         The main drawback I see to this is it makes usage slightly more
>         verbose:
>
>            $options = new Component\Options($config);
>            $object  = new Component($options);
>
>         That said, I think there are some easy ways to approach this. Instead
>         of
>         type-hinting on the options object in the constructor, the constructor
>         can do some checks:
>
>            public function __construct($options = null)
>            {
>                if (null !== $options) {
>                    if (!$options instanceof Options) {
>                        $options = new Options($options);
>                    }
>                    $this->setOptions($options);
>                }
>            }
>
>
>
>     How do you feel about initializing all components with a Zend_Config
>     object, that will be able to cast itself to
>     an Options object. That would of course mean coupling between Zend_Config
>     and Zend_Options and it's children.
>
>     My personal opinion is that people rely too much on arrays in PHP (also
>     throughout the Zend Framework),
>     and that could change by allowing only initialization through Zend Config
>     objects.
>
>     class Component
>     {
>     const DEFAULT_OPTIONS_CLASS = 'Component\Options';
>     private $_options = null;
>
>     public function __construct(Zend_Config $config = null)
>     {
>     if (null !== $config) {
>     $this->_options = $config->toOptions(self::DEFAULT_OPTIONS_CLASS);
>     }
>     }
>     }
>
>     // usage example
>     $component = new Component(new Zend_Config_Ini('/path/to/filename'));
>
>
>
>
>         The "Options" class for each component could then be either a
>         standalone
>         class with its own handling, or we could provide a base "Options" class
>         with default behavior (and potentially a PHP 5.4 trait to mix-in).
>
>
>     Providing one or more traits to implement, would be helpful and would allow
>     some flexibility for anyone who requires it.
>
>
>         I'm personally of the mind that the component should fulfill your
>         fourth
>         (and possibly fifth) point above, however: the Options object should
>         only aggregate the options; the component decides what it needs, and
>         how
>         to deal with missing options.
>
>
>     One of these traits could be to specify:
>     - a required set of options/parameters that need to be set in the Options
>     object at one point (when calling a trigger method)
>     - a list of Exceptions to throw for each missing option
>
>
>
>
>         Thoughts?
>
>
>             Do you think this is a good idea?
>
>             Would the framework be easier to understand if the option loading
>
>             would be the same for all classes?
>
>
>
>             If you have other ideas of what this component might do, please
>             share
>
>             your thoughts!
>
>
>         --
>         Matthew Weier O'Phinney
>         Project Lead            | [hidden email]
>         Zend Framework          | http://framework.zend.com/
>         PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>
>
>
>

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: 'Centralized option loader' component proposal

Mihai Bojin
Ok great, thanks for the quick response!

On Feb 8, 2011, at 8:34 PM, Matthew Weier O'Phinney wrote:

> -- Mihai Bojin <[hidden email]> wrote
> (on Tuesday, 08 February 2011, 08:28 PM +0200):
>> Do you think it would be better to refactor all components into using only
>> Zend_Config + type hinting in each constructor,
>> or allowing any type in the constructor and then creating the Options objects
>> around this data ?
>
> Allowing any type, and then creating the options objects. The rationale
> is that will allow systems such as Symfony2's DI container or other such
> systems to interact with the ZF code, without needing to change their
> functionality (or require a wrapper around them to support ZF code).
>
>> I am interested in writing up a proposal and the code for this component for
>> ZF2, so naturally I seek your advice!
>>
>>
>> Thank you,
>> Mihai
>>
>>
>> On Feb 7, 2011, at 7:26 PM, Mihai Bojin wrote:
>>
>>
>>    Hello everyone,
>>
>>    On Feb 7, 2011, at 6:24 PM, Matthew Weier O'Phinney wrote:
>>
>>
>>        -- Mihai Bojin <[hidden email]> wrote
>>        (on Sunday, 06 February 2011, 03:26 PM +0200):
>>
>>            I'll get right to the point.
>>
>>
>>
>>            I had the idea of building a centralized option loader component
>>            for
>>
>>            ZF.  Below I will describe 5 use cases of current ZF classes that
>>            load
>>
>>            options from config objects.  At the end of this email I will
>>            describe
>>
>>            what I think the centralized option loader component should do.
>>
>>
>>        <snip - analysis of a number of patterns>
>>
>>        One thing I've realized with ZF2 development is that we shouldn't be
>>        testing on Zend_Config, but simply Traversable. The reason is that this
>>        opens us up to using other
>>
>>
>>            My idea is why not centralize all these behaviours into an Loader
>>
>>            class that would be able to handle some or all of the following:
>>
>>
>>        "Loader" is a namespace dealing with class and plugin loading. I'd
>>        argue
>>        this should be under the "Config" namespace, or a new "Options"
>>        namespace. And note the word "namespace" -- this could only be
>>        considered for ZF2.
>>
>>        One issue with such an approach, however, is it introduces a dependency
>>        for every class that has options parsing. This has a lot of
>>        implications:
>>
>>        * Is it possible to inject the options handler? If so, how? (This is a
>>          question that the more fanatic folks of loose coupling and/or
>>          dependency injection will ask.)
>>        * How do you document the dependency? (Probably an import statement is
>>          enough.)
>>        * Additional dependencies == harder to install individual components in
>>          a standalone configuration.
>>
>>        That said, I'm not completely against the idea. I noticed with
>>        Zend\Session (ZF2's session component) that it was far easier to have a
>>        base configuration object and interface as it simplified my code -- I
>>        could assume that both standard keys and defaults were present. The
>>        system is still extensible and injectible as well.
>>
>>
>>    The dependency injection point is a good one, haven't thought of it
>>    yesterday...
>>
>>    Considering all said below, I think Zend_Options would be a better choice,
>>    because
>>    this class should not be directly related to Zend_Config, nor for that
>>    matter be limited to working
>>    only with Zend_Config objects.
>>
>>    A trait could be implemented in Zend_Config, to allow other objects
>>    implementing a common
>>    interface to be type-casted into a Zend_Config.
>>
>>
>>
>>
>>            - passed parameter identification (is it an array, a Zend_Config
>>
>>             object, ...)
>>
>>            - conversion to array (which is the generally accepted way in ZF of
>>
>>             working with config options)
>>
>>            - default options (init the config array with some default values
>>            that
>>
>>             get overwritten by the actual passed parameters)
>>
>>            - required options (if one or more of the required params is not
>>            set,
>>
>>             throw an Exception)
>>
>>            - exception handling (set which exceptions and messages to throw
>>            for
>>
>>             different use cases, or use default messages for the few standard
>>
>>             cases, for ease of debugging, smaller footprint of the framework
>>            and
>>
>>             other benefits)
>>
>>            - parameter splitting (return an array of options, or multiple
>>            options
>>
>>             and/or arrays of options)
>>
>>
>>        One idea that has been brought up by a few contributors, and which I've
>>        seen in ez/Zeta Components, is the idea of having a "config object" per
>>        component (and/or subcomponent). The idea is that doing so helps
>>        document the available options. (ez/Zeta does so by having "struct"
>>        objects with public members for available options (and defaults).)
>>
>>        The main drawback I see to this is it makes usage slightly more
>>        verbose:
>>
>>           $options = new Component\Options($config);
>>           $object  = new Component($options);
>>
>>        That said, I think there are some easy ways to approach this. Instead
>>        of
>>        type-hinting on the options object in the constructor, the constructor
>>        can do some checks:
>>
>>           public function __construct($options = null)
>>           {
>>               if (null !== $options) {
>>                   if (!$options instanceof Options) {
>>                       $options = new Options($options);
>>                   }
>>                   $this->setOptions($options);
>>               }
>>           }
>>
>>
>>
>>    How do you feel about initializing all components with a Zend_Config
>>    object, that will be able to cast itself to
>>    an Options object. That would of course mean coupling between Zend_Config
>>    and Zend_Options and it's children.
>>
>>    My personal opinion is that people rely too much on arrays in PHP (also
>>    throughout the Zend Framework),
>>    and that could change by allowing only initialization through Zend Config
>>    objects.
>>
>>    class Component
>>    {
>>    const DEFAULT_OPTIONS_CLASS = 'Component\Options';
>>    private $_options = null;
>>
>>    public function __construct(Zend_Config $config = null)
>>    {
>>    if (null !== $config) {
>>    $this->_options = $config->toOptions(self::DEFAULT_OPTIONS_CLASS);
>>    }
>>    }
>>    }
>>
>>    // usage example
>>    $component = new Component(new Zend_Config_Ini('/path/to/filename'));
>>
>>
>>
>>
>>        The "Options" class for each component could then be either a
>>        standalone
>>        class with its own handling, or we could provide a base "Options" class
>>        with default behavior (and potentially a PHP 5.4 trait to mix-in).
>>
>>
>>    Providing one or more traits to implement, would be helpful and would allow
>>    some flexibility for anyone who requires it.
>>
>>
>>        I'm personally of the mind that the component should fulfill your
>>        fourth
>>        (and possibly fifth) point above, however: the Options object should
>>        only aggregate the options; the component decides what it needs, and
>>        how
>>        to deal with missing options.
>>
>>
>>    One of these traits could be to specify:
>>    - a required set of options/parameters that need to be set in the Options
>>    object at one point (when calling a trigger method)
>>    - a list of Exceptions to throw for each missing option
>>
>>
>>
>>
>>        Thoughts?
>>
>>
>>            Do you think this is a good idea?
>>
>>            Would the framework be easier to understand if the option loading
>>
>>            would be the same for all classes?
>>
>>
>>
>>            If you have other ideas of what this component might do, please
>>            share
>>
>>            your thoughts!
>>
>>
>>        --
>>        Matthew Weier O'Phinney
>>        Project Lead            | [hidden email]
>>        Zend Framework          | http://framework.zend.com/
>>        PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>>
>>
>>
>>
>
> --
> Matthew Weier O'Phinney
> Project Lead            | [hidden email]
> Zend Framework          | http://framework.zend.com/
> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

12
Loading...