У меня возникла странная проблема, и я не уверен, как ее исправить. У меня есть несколько классов, которые все PHP-реализации объектов JSON. Вот иллюстрация проблемы
class A
{
protected $a;
public function __construct()
{
$this->a = array( new B, new B );
}
public function __toString()
{
return json_encode( $this->a );
}
}
class B
{
protected $b = array( 'foo' => 'bar' );
public function __toString()
{
return json_encode( $this->b );
}
}
$a = new A();
echo $a;
Выход из этого
[{},{}]
Когда желаемый выход равен
[{"foo":"bar"},{"foo":"bar"}]
Проблема в том, что я полагался на хук __toString (), чтобы выполнить свою работу за меня. Но это невозможно, потому что сериализация, которую использует json_encode (), не вызовет __toString (). Когда он встречает вложенный объект, он просто сериализует только общедоступные свойства.
Итак, возникает вопрос: есть ли способ, которым я могу разработать управляемый интерфейс для классов JSON, который одновременно позволяет мне использовать установщики и получатели для свойств, но также позволяет мне получить желаемое поведение сериализации JSON?
Если это неясно, вот пример реализации, которая не будет работать , так как хук __set () вызывается только для начального присваивания
class a
{
public function __set( $prop, $value )
{
echo __METHOD__, PHP_EOL;
$this->$prop = $value;
}
public function __toString()
{
return json_encode( $this );
}
}
$a = new a;
$a->foo = 'bar';
$a->foo = 'baz';
echo $a;
Полагаю, я мог бы сделать что-то подобное
class a
{
public $foo;
public function setFoo( $value )
{
$this->foo = $value;
}
public function __toString()
{
return json_encode( $this );
}
}
$a = new a;
$a->setFoo( 'bar' );
echo $a;
Но тогда мне пришлось бы полагаться на усердие других разработчиков в использовании сеттеров - я не могу программно придерживаться этого решения.
---> РЕДАКТИРОВАТЬ <--- </strong>
Теперь с проверкой ответа Роба Эльснера
<?php
class a implements IteratorAggregate
{
public $foo = 'bar';
protected $bar = 'baz';
public function getIterator()
{
echo __METHOD__;
}
}
echo json_encode( new a );
Когда вы выполните это, вы увидите, что метод getIterator () никогда не вызывается.