# 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->tag = strtolower($cfg['tag']); } if ($this->tag === 'input' && isset($cfg['type']){$this->type = $cfg['type']; } if ( isset($cfg['customClass']){
$this->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->tag = isset($cfg['tag']) ? strtolower($cfg['tag']) : self::tag;
$this->type = isset($cfg['type']) ? strtolower($cfg['type']) : self::type;$this->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!"? :)

-
some further information on how the class is used / in which context / which other components you do have regarding configuration etc... would be helpful. AFAIK there are many very clean solutions. However they highly depend on the available infrastructure and use-cases. –  Fge Dec 12 '12 at 14:13
I'm using a custom MVC framework, but I'd like this class to work as stand-alone, although I plan to use it with another class generating form from database table structure. –  Nabab Dec 12 '12 at 14:16

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' => null, 'type' => null, ); private$_current;

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

public function reset()
{
$this->_current = array(); foreach ($this->_defaults as $key =>$value) {
$this->_current[$key] = $value; } } public function setTag($tag)
{
if (!is_string($tag)) { throw new InvalidArgumentException('...'); }$this->_current['tag'] = $tag; } public function setType($type)
{
if (!is_string($type)) { throw new InvalidArgumentException('...'); }$this->_current['type'] = $type; } public function getInput() { return new Input($this->_current);
}
}


Usage would be:

$builder->setType('text') ->build(); // tag: input, type: text$builder->setType('password')
->build(); // tag: input, type: password
$builder->reset(); // reset everything to defaults$builder->setTag('textarea') // tag: textarea: type: text
->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' => null, 'type' => null, ); private$_current;

public function __construct(array $defaults = null) { foreach ($defaults as $key =>$value) {
if (array_key_exists($this->_defaults[$key])) {
$this->_defaults[$key] = $value; } } } public function configure(Input$element)
{
$config =$this->_init['tag'];

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

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

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

// ...
}


Usage would be:

$configuration = new InputConfiguration( 'tag' => 'input', 'type' => 'text', );$newObject = new Input($configuration); // has defaults applied$newObject2 = new Input(); // we don't want to use defaults
$configuration->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.

-
Thanks, that looks like a good implementation. What I prefered in mine is there was only one class - so 1 file included but that's detail. Yes, I think a builder would be the solution for me. Still, why do you say "using static gets complicated quite fast"? –  Nabab Dec 12 '12 at 18:34
because you maintain almost the same information twice within the class + the class is responsible for knowing two thinks: the defaults and the current data. Look at your code above - in my opinion it's already overly complicated ;) –  Fge Dec 12 '12 at 20:25