NotionCommotion Posted May 30, 2018 Share Posted May 30, 2018 I have an entity object which contains other entity objects which in turn contain other entity objects. Of of these entity object implements ArrayAccess and contains a collection of entity objects. All the properties in these objects are protected. To get the applicable data, all of these objects implement JsonSerializable and include a jsonSerialize() method which cascade and to my amazement provide my exact desired stdClass which I convert to JSON and send to the client. But now I need a different view of the object. By different view, I mean a different sub-set of properties and potentially calling them different names. How should this be accomplished? I can obviously manually iterate over the object and manipulate it, but I am sure that doing so is the wrong approach. Or maybe extend all of the objects and override jsonSerialize() in each? This seems like a lot of work. Ideally, I would have some public method on the top object like $topObject->getView1() which would return one stdClass, and $topObject->getView2() which would return another. But I don't understand how this cascading of nested objects into their parents would work as I can only have one jsonSerialize() in each class. Maybe passing jsonSerialize() a value somehow gets passed to its children objects? Sounds prone to error, but maybe not. Any thoughts? Thank you Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted May 30, 2018 Author Share Posted May 30, 2018 This post at http://php.net/manual/en/jsonserializable.jsonserialize.php#121377 describes what I am doing, but not how to get multiple views of the object. Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted May 30, 2018 Author Share Posted May 30, 2018 (edited) The following will not work as the injected view doesn't have viability. Maybe some derivative of this approach? <?php class ParentClass implements \JsonSerializable { private $collection, $node1, $node2, $view; public function __construct($collection, $serializable1, $serializable2, $view=false) { $this->collection = $collection; $this->serializable1 = $serializable1; $this->serializable2 = $serializable2; $this->view = $view; } public function jsonSerialize() { return $this->view?$this->view->view($this):[ 'serialized' => $this->collection, 'serializable1' => $this->serializable1 ]; } } class NestedSerializable implements \JsonSerializable { private $serializable1, $serializable2, $serializable3, $view; public function __construct($serializable1, $serializable2, $serializable3, $view=false) { $this->serializable1 = $serializable1; $this->serializable2 = $serializable2; $this->serializable3 = $serializable3; $this->view = $view; } public function jsonSerialize() { return $this->view?$this->view->view($this):[ 'serialized1' => $this->serializable1, 'bla' => $this->serializable3, ]; } } class SerializableCollection implements \JsonSerializable { private $elements; public function __construct(array $elements, $view=false) { $this->elements = $elements; $this->view = $view; } public function jsonSerialize() { return $this->elements; } } $obj=new ParentClass( new SerializableCollection([ new NestedSerializable(null,null,null), new NestedSerializable(null,null,null), new NestedSerializable(new NestedSerializable(null,null,null),null,null) ]), new NestedSerializable(null,null,null), new NestedSerializable(new NestedSerializable(null,null,null),null,null) ); echo json_encode($obj).PHP_EOL.PHP_EOL;// Outputs: {"serialized":[{"serialized1":null,"bla":null},{"serialized1":null,"bla":null},{"serialized1":{"serialized1":null,"bla":null},"bla":null}],"serializable1":null} class View1 { //public function __construct($that){$this->that = $that;} public function view($that) { return [ 'serialized1' => $that->serializable2, 'blabla' => $that->serializable3, ]; } } $obj=new ParentClass( new SerializableCollection([ new NestedSerializable(null,null,null, new View1), new NestedSerializable(null,null,null, new View1), new NestedSerializable(new NestedSerializable(null,null,null, new View1),null,null, new View1) ]), new NestedSerializable(null,null,null, new View1), new NestedSerializable(new NestedSerializable(null,null,null, new View1),null,null, new View1) ); echo json_encode($obj); Edited May 30, 2018 by NotionCommotion Quote Link to comment Share on other sites More sharing options...
ignace Posted June 1, 2018 Share Posted June 1, 2018 Move the logic of serializing out of your entities. It does not belong there, nor should your properties be protected, they should be private. Only if absolutely necessary, can they be protected. And even then you can still create a protected getter/setter of some sort. I already posted how to do the serializing in your other thread. <?php interface NodeSerializer { function serialize(Node $node); function unserialize($input, Node $node); } With this you can create as many 'views' as you need. Quote Link to comment Share on other sites More sharing options...
ignace Posted June 1, 2018 Share Posted June 1, 2018 With that said, perhaps you don't want to expose all properties. In that case you can also resort to using a Visitor <?php interface NodeVisitor { function visitNode(Node $node); function visitCategory(CategoryNode $node); // ... } final class Node { function accept(NodeVisitor $nodeVisitor) { $nodeVisitor->vistNode($this); foreach ($this->categories as $category) { $nodeVistor->visitCategory($category); } } } $node->accept($myNodeVisitor); $json = $myNodeVisitor->getResult(); This is of course a little more difficult then using a simple serializer. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.