我的问题基本上与标题所说的完全相同。
我现在玩TypeScript已经有一段时间了,这是一种定义Object结构的简单方法,它定义了Interface中的属性。我知道PHP不支持Interfaces中的属性,但有没有办法以某种方式定义Object的结构(不使用一些抽象类)我传递或至少是数组(需要呈现哪些键)内侧)。
我的意思是:
// I already sanitized that this method returns the exact same structure every time
$data = $this->storage->get($some);
// here I'm passing the data I obtained to my Builder
Builder::createFromArray($data);
// or
Builder::create($data);
class Builder {
public static function createFromArray(\ArrayOfSomeType $array) {}
public static function create(\ObjectOfSomeTypeWithPropertiesSpecified $obj) {}
}
希望我解释得很清楚。
答案 0 :(得分:1)
正如你所说,PHP中没有概念,它完全符合你的要求。有一个ArrayObject
类,可以满足您对具有大量成员的对象的需求。
class Builder {
public function create(iterable $data) : \ArrayObject {
$object = (new \ArrayObject())->setFlags(\ArrayObject::ARRAY_AS_PROPS);
foreach ($data as $key => $value) {
$object->offsetSet($key, $value);
}
return $object;
}
}
}
示例1:使用数组填充对象
$object = Builder::create([ 'bla' => 'blubb', 'yadda' => 'blubb' ]);
var_dump($object->bla);
构建器返回一个与数组具有完全相同属性的对象。所有属性都包含数组所具有的值。您可以使用foreach
或Iterator
对象迭代新对象。
示例2:使用其他对象填充对象
$class = new \stdClass();
$class->propertyA = 'B';
$class->propertyB = 'B';
$object = Builder::Create($class);
var_dump($object->propertyA);
使用PHP几乎所有对象都是可迭代的。这意味着您可以迭代一个对象的属性并将它们传递给我们的ArrayObject
实例。
使用PHP进行水合作用的常用方法
PHP中还有另一种称为水合作用的方法。它比显示的示例稍微复杂一些,但是非常方便,如果你得到它。
// your entity / data model
class Car implements EntityInterface {
protected $horsepower;
public function getHorsepower() : int
{
if ($this->horsepower === null) {
$this->horsepower = 0;
}
return $this->horsepower;
}
public function setHorsepower(int $horsepower) : self
{
$this->horsepower = $horsepower;
return $this;
}
}
这是我们的汽车类型的数据模型(实体)。我们的汽车继承了一个界面。这仅用于水化器中的类型提示原因。我们的车有一个名为马力的房产。当然,汽车可以拥有更多的属性。但这仅仅是例如。 ;)
class ClassMethodsHydrator
{
public function hydrate(array $data, EntityInterface $entity) : EntityInterface {
foreach ($data as $key => $value) {
$methodName = 'set' . ucwords(strtolower($key));
if (method_exists($entity, $methodName) {
$entity->{$methodName}($value);
}
}
return $entity;
}
}
这是我们的小型水化器示例。这个类确实是你的构建器所做的。但是以更具体的方式。它需要一个实体并使用给定的数据对其进行水合,如果它与实体的方法匹配。
$entity = (new Hydrator())->hydrate(
[
'horsepower' => 172,
'notexistingproperty' => 'bla',
],
new Car()
);
var_dump($entity->getHorsepower()); // 172
水合作用的优点很简单。您只有具有已知属性的模型。这非常安全,您随时都知道,您的模型可以为您做什么。例如,汽车有方向舵是没有意义的。在这种情况下,汽车只能得到一辆汽车。就像在示例中一样,汽车只接受阵列的马力成员。
答案 1 :(得分:0)
我认为你可以通过在界面中创建getter和setter来强制使用。而不是
$item->something;
你可以使用
$item->getSomething();