我目前正在学习OOP Method Chaining,但我在使其工作方面遇到了困难。
我创建了setValue方法,它根据参数返回一个值。
然后,我创建了setLabel方法并添加了一个参数,在调用setValue之后使用。
这是我目前的代码: -
class Field
{
public $label;
public function setValue($property, $value)
{
$this->$property = new \stdClass();
$this->$property->value = $value;
$this->$property->label = $this->label;
return $this;
}
public function setLabel($label)
{
return $this->label = $label;
}
}
检索数据的示例代码: -
$field = new Field;
$field->setValue('textfield', 'something to print')->setLabel('Label here');
print $field->textfield->value; // Returns the value
print $field->textfield->label; // Returns an empty string
我无法弄清楚我的代码有什么问题。请帮忙。
答案 0 :(得分:2)
假设您的目标如下:
print $field->textfield->value; // Returns the value
print $field->textfield->label; // Returns the label
如果你想要这个:
$field = new Field;
$field->setValue('textfield', 'something to print')->setLabel('Label here');
然后你需要做这样的事情:
class FieldProperty {
public $label
public $value;
public setValue($value) { $this->value = $value; return $this; }
public setLabel($label) { $this->label = $label; return $this; }
}
class Field
{
public function setValue($property, $value)
{
$this->$property = new FieldProperty();
$this->$property->setValue($value);
return $this->$property;
}
}
进一步思考,我们可以补充:
class Field
{
public function setValue($property, $value)
{
$this->$property = new FieldProperty();
$this->$property->setValue($value);
return $this->$property;
}
public function setProperty($propertyName)
{
$this->$propertyName = new FieldProperty;
return $this->$propertyName;
}
}
现在你可以这样做:
$field->setProperty('textfield')->setLabel('my label')->setValue('some value');
答案 1 :(得分:0)
如果您想在$this->$property->label
和$this->label
之间保持引用,assign the value by reference
$this->$property->label =& $this->label;
请注意,该引用有两种方式,因此如果您为$field->textfield->label
分配新标签,它也会更改$field->label
。
我觉得更好的方法是使用魔术方法自动创建每个属性。然后,您可以在私有字段中跟踪所有内容并相应地更新其标签。
class Field
{
public $label;
private $properties = []; // this will store all your dynamic properties
public function __get($name) {
// lazily create properties on demand
if (!isset($this->properties[$name])) {
$this->properties[$name] = new \stdclass();
}
return $this->properties[$name];
}
public function setValue($property, $value)
{
// this will automatically create "$property" if it's not defined
$this->$property->value = $value;
$this->$property->label = $this->label;
return $this;
}
public function setLabel($label)
{
// Set the field label and any known property labels
$this->label = $label;
foreach($this->properties as $property) {
$property->label = $label;
}
return $label; // ¯\_(ツ)_/¯
}
}
答案 2 :(得分:0)
如果你想OOP方式,我想,我需要像下面这样做。创建基础Field
类:
class Field
{
public $value;
public $label;
public function setValue($value)
{
$this->value = $value;
return $this;
}
public function setLabel($label)
{
$this->label = $label;
return $this;
}
}
也许,即使是abstract。
然后你可以扩展这个类,创建特定的字段:
final class TextField extends Field
{
}
$textField = (new TextField)
->setValue('something to print')
->setLabel('Label here');
这是the demo。
这样,您可以稍后在程序中使用polymorphism。假设你有一个对象,你传递了一堆Field
类型的不同对象(read extend Field
)。然后按照自己的方式操作,此对象无法知道每个$property
具有哪些内容,并且无法访问value
和label
- #39; t共享公共接口。但是,对于共享公共接口的对象(在我们的示例中扩展相同的基类),我们可以简单地遍历一堆字段并检索值和标签。
为了渲染这个字段,一个(读得有点难看)的解决方案是利用get_class
函数:
switch ($class = get_class($field)) {
case 'TextField':
$this->renderTextField($field);
break;
case 'InputField':
$this->renderInputField($field);
break;
// ...
default:
throw new Exception("Cannot render $class.");
}
答案 3 :(得分:0)
您正在更改label
($property
)的'textfield'
属性,而不是$this
。这意味着var_dump($field->textfield->label);
除了var_dump($field->label);
之外不包含任何内容。
说你需要存储$property
的名字,以便以后你可以参考它。一个快速工作的解决方案是:
<?php
class Field
{
public $label;
public $propName;
public function setValue($property, $value)
{
$this->propName = $property;
$this->$property = new \stdClass();
$this->$property->value = $value;
$this->$property->label = $this->label;
return $this;
}
public function setLabel($label)
{
$this->{$this->propName}->label = $label;
}
}
$field = new Field;
$field->setValue('textfield', 'something to print')->setLabel('Label here');
var_dump($field->textfield->value, $field->textfield->label);
答案 4 :(得分:-1)
在您的代码&#34;标签&#34;将值赋入Field Object,而不是textfield对象,如您所见:
Field object {
label => (string) Label here
textfield => stdClass object {
value => (string) something to print
label => null
}
}
你使用$field->label
,因为它们存储在不同的对象中,或者试试这个:
class Field {
public function setValue($value) {
$this->property = new \stdClass();
$this->property->value = $value;
return $this;
}
public function setLabel($label) {
$this->property->label = $label;
return $this->property;
}
}
$field = new Field();
$field->setValue('something to print')->setLabel('Label here');
print $field->property->value;
print $field->property->label;
输出
something to printLabel here