Using static for class default properties I have made a class for generating html form elements:

class input
{
  public $tag = 'input', $type = 'text', $customClass, $name;

  public function __construct(array $cfg){
    if ( isset($cfg['name']) ){
      if ( isset($cfg['tag']){
        $this-&gt;tag = strtolower($cfg['tag']);
      }
      if ( $this-&gt;tag === 'input' &amp;&amp; isset($cfg['type']){
        $this-&gt;type = $cfg['type'];
      }
      if ( isset($cfg['customClass']){
        $this-&gt;customClass= $cfg['customClass'];
      }
      //etc...
    }
  }
}


I would like to be able to set a custom default config for all my fields - without changing the class. For example I want all the fields in a given script to have 'myClass' as customClass. For me, the solution would be to make these default values static, and make a function to change them like this:

class input
{
  static $tag = 'input', $type = 'text', $customClass, $name;

  public static function setDefault(array $cfg){
    if ( isset($cfg['tag']) ){
      self::tag = strtolower($cfg['tag']);
    }
    if ( isset($cfg['type']) ){
      self::type = $cfg['type'];
    }
    if ( isset($cfg['customClass']) ){
      self::customClass= $cfg['customClass'];
    }
    //etc...
  }

  public function __construct(array $cfg){
    if ( isset($cfg['name']) ){
      $this-&gt;tag = isset($cfg['tag']) ? strtolower($cfg['tag']) : self::tag;
      $this-&gt;type = isset($cfg['type']) ? strtolower($cfg['type']) : self::type;
      $this-&gt;customClass = isset($cfg['customClass']) ? $cfg['customClass'] : self::customClass;
      //etc...
    }
  }
}


The problem is that I read everywhere - and particulary here - that static are evil. What other solution would be suitable in the present case? Or can someone tell me "yeah, that's the perfect case to use statics!"? :)
You could either a configuration object or a builder for this. As you probably can see yourself, using static gets complicated quite fast.

Using a builder:



class InputBuilder
{
    private $_defaults = array(
        'tag' =&gt; null,
        'type' =&gt; null,
    );

    private $_current;

    public function __construct(array $defaults = null)
    {
        foreach ($defaults as $key =&gt; $value) {
            if (array_key_exists($this-&gt;_defaults[$key])) {
                $this-&gt;_defaults[$key] = $value;
            }
        }

        $this-&gt;reset();
    }

    public function reset()
    {
        $this-&gt;_current = array();
        foreach ($this-&gt;_defaults as $key =&gt; $value) {
            $this-&gt;_current[$key] = $value;
        }       
    }

    public function setTag($tag)
    {
        if (!is_string($tag)) {
            throw new InvalidArgumentException('...');
        }
        $this-&gt;_current['tag'] = $tag;
    }

    public function setType($type)
    {
        if (!is_string($type)) {
            throw new InvalidArgumentException('...');
        }
        $this-&gt;_current['type'] = $type;    
    }

    public function getInput()
    {
        return new Input($this-&gt;_current);
    }
}


Usage would be:

$builder-&gt;setType('text')
        -&gt;build();  // tag: input, type: text
$builder-&gt;setType('password')
        -&gt;build(); // tag: input, type: password
$builder-&gt;reset(); // reset everything to defaults
$builder-&gt;setTag('textarea') // tag: textarea: type: text
        -&gt;build();


The builder pattern is extremely strong if you want to build the object programmatically. (SQL) Query-builder are a very common use case for this.

Using a configuration object:

class InputConfiguration
{
        private $_init = array(
            'tag' =&gt; null,
            'type' =&gt; null,
        );

        private $_current;

        public function __construct(array $defaults = null)
        {
            foreach ($defaults as $key =&gt; $value) {
                if (array_key_exists($this-&gt;_defaults[$key])) {
                    $this-&gt;_defaults[$key] = $value;
                }
            }
        }

        public function configure(Input $element)
        {
            $config = $this-&gt;_init['tag'];

            if (null !== $config['tag'] &amp;&amp; null !== $element-&gt;getTag()) {
                $element-&gt;setTag($config['tag']);
            }

            if (null !== $config['type'] &amp;&amp; null !== $element-&gt;getType()) {
                $element-&gt;setType($config['type']);
            }
        }
}

class Input 
{
     public function construct(InputConfiguration $config = null)
     {
           if (null !== $config) {
               $config-&gt;configure($this);
           }
     }

     // ...
}


Usage would be: 

$configuration = new InputConfiguration(
    'tag' =&gt; 'input', 
    'type' =&gt; 'text',
);

$newObject = new Input($configuration); // has defaults applied

$newObject2 = new Input(); // we don't want to use defaults
$configuration-&gt;configure($newObject2); // or decide to apply them later on


The configuration object decouples the configuration from your object. Furthermore it makes one configuration reusable and optional.