Ticket #9 (assigned enhancement)

Opened 2 years ago

Last modified 2 years ago

Allow more than one argument in setter method calls

Reported by: mikey Assigned to: schst (accepted)
Priority: major Milestone: 0.3.0
Component: definitions Version: svn-trunk
Keywords: Cc:

Description

Currently it is not possible to use setters this way:

<?php
class Foo { public function setBar($bazName, $bazValue) { ... } }
?>

The only possibility would be to have two seperate setters or to unique both arguments into an array, but this has several drawbacks regarding type safety and the handling of both values if they belong together.

A solution could be:

<defines>
  <tag name="foo" type="Foo" />
  <tag name="bar" type="string">
    <setterMethod name="setBar">
      <attribute name="name" type="string" />
      <value source="CData" />
    </setterMethod>
  </tag>
</defines>

<foo>
  <bar boom="example">This is baz.</bar>
</foo>

This would result to:

<?php
$foo = new Foo();
$foo->setBar('example', 'This is baz');
?>

Change History

02/15/07 21:41:51 changed by schst

  • owner changed from mikey to schst.

I'll implement this.

Instead of <setterMethod/> I'll add a <method/> tag, that allows us to call any method on the created object.

02/15/07 21:41:57 changed by schst

  • status changed from new to assigned.

02/15/07 22:14:28 changed by schst

I propose to use the following syntax:

Tag definitions:

<defines>
  <tag name="props" type="Properties">
    <methodCallTag name="property" method="setProperty">
      <attribute name="prop" type="string"/>
      <cdata type="string"/>
    </methodCall>
  </tag>
</defines>

XML:

<configuration>
  <props>
    <property name="foo">bar</property>
    <property name="argh">tomato</property>
  </props>
</configuration>

PHP:

class Properties {
  private $props = array();

  public function addProperty($propName, $propValue) {
    $this->props[$propName] = $propValue;
  }
}

The following changes need to be made:

  1. Create a new MethodCallTagDefinition
  2. Allow this definition to be added to any TagDefinition
  3. Make the AbstractObjectValueConverter aware of this child element

Implementing this should be possible without breaking backwards compatibility. However, it could be easier to implement by refactoring the addChildrenToTag() method. The following code should be added to the corresponding tag definition, so that they know how to add themselves to the parent tag:

$class = new ReflectionClass(get_class($instance));
foreach ($children as $child) {
  if (in_array($child->getName(), $ignore) == true) {
    continue;
  }
  try {
    $class->getMethod($child->getSetterMethod())->invoke($instance, $child->getConvertedValue());
  } catch (ReflectionException $re) {
    throw new ValueConversionException('Could not add child "' . $child->getKey() . '" to "' . $this->getType() . '" using "' . $child->getSetterMethod() . '()", exception message: "' . $re->getMessage() . '".');
  }
}

Maybe we could even come up for an interface for elements that add themselves to a parent.

02/16/07 17:23:49 changed by mikey

The syntax seems good to me, even if the example has some errors. :) It is not as verbose as my initial proposal is, and is more clear regarding to what the element belongs to.

03/05/07 16:42:34 changed by schst

I just committed an alpha version to SVN. But I keep this ticket open, as I'd like to refactor some things.