6

I'm attempting to open up data from a PHP Object (as shown below) but I'd like to be able to access this data within JavaScript to use in a graphing library.

Object in question:

http://puu.sh/eP3QZ/e4289eb0d8.png

What I need to be able to do is convert that into a JSON encoded object for use within Javascript.

I tried using twig within Symfony to do this via:

{% set playerStats = match.getStatsPlayers().getValues() }%
{% dump(playerStats) %} // This is what you see above

var playerStats = {{ playerStats|json_encode }};

console.log(playerStats);

The console shows this:

http://puu.sh/eP4aX/adf6c9978f.png

Which is where I'm banging my head against the wall. Where can I access the values of these properties?

As an inefficient way, I've managed to get it into a JavaScript object by doing:

{% for p in playerStats %}
    playerStats.push({ 'id': {{p.playerID}}, 'playerName': '{{p.playerName}}', 'playerOutfit': {{p.playerOutfit}}, 'playerFaction': {{p.playerFaction}}, 'playerKills': {{p.playerKills}}, 'playerDeaths': {{p.playerDeaths}}, 'playerTeamKills': {{p.playerTeamKills}}, 'playerSuicides': {{p.playerSuicides}} });
{% endfor %}

I feel kinda dirty for doing that. There must be a better way to do this surely?

Thanks in advance!

Veve
  • 6,643
  • 5
  • 39
  • 58
Matt Cavanagh
  • 518
  • 5
  • 19

1 Answers1

8

You can use the Symfony Serializer. http://symfony.com/doc/current/components/serializer.html

You might want to write your own Twig extension to do this from within your template.

Your code will look something like this:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;

$encoders = array(new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());

$serializer = new Serializer($normalizers, $encoders);

$jsonContent = $serializer->serialize($object, 'json');

When you put that string into your javascript, you should have a normal JS object where you can find everything you want.

You might want to use the JMSSerializerBundle, as it already has a Twig extension, and is easier to use in general.

https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Resources/doc/index.rst


An update to give a quick overview of what is in the comments.

Both the Symfony Serializer as the JMSSerializerBundle seem to have a hard time coping with Bi-directional relations (most likely Doctrine). This will result in errors like "Out of memory" or something mentioning "Self-referencing" objects / infinite loops.

To solve this, you can ignore the attribute with the Normalizer. Which will look something like:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;

$normalizer = new GetSetMethodNormalizer();
$normalizer->setIgnoredAttributes(array('match')); //Replace match with the parent attribute
$encoder = new JsonEncoder();

$serializer = new Serializer(array($normalizer), array($encoder));
$serializer->serialize($object, 'json');
Nico Kaag
  • 1,876
  • 12
  • 12
  • Thanks for the reply. I tried using the JMSSerializerBundle, using the following: `var playerStats2 = {{ match.getStatsPlayers().getValues() | serialize('json') }}` `console.log(playerStats2);` All I get unfortunately is a nginx error saying that the app ran out of memory. – Matt Cavanagh Jan 21 '15 at 14:07
  • Also tried using the symfony serializer. Got "A circular reference has been detected (configured limit: 1)." when trying to seralize this: `$em = $this->getDoctrine()->getManager(); $match = $em->getRepository('PSBAdminBundle:Matches')->find($matchID); $statsPlayers = $match->getStatsPlayers()->getValues(); $encoders = array(new JsonEncoder()); $normalizers = array(new GetSetMethodNormalizer()); $serializer = new Serializer($normalizers, $encoders); $jsonContent = $serializer->serialize($statsPlayers, 'json');` – Matt Cavanagh Jan 21 '15 at 14:20
  • What is your ->getValues() actually returning? You might want to ignore entity references to the parent, to see if that solves anything? $normalizer = new GetSetMethodNormalizer(); $normalizer->setIgnoredAttributes(array('match')); Also check the documentation for the setIgnoredAttributes. – Nico Kaag Jan 21 '15 at 14:31
  • The getValues() returns an ArrayCollection, (http://puu.sh/eP3QZ/e4289eb0d8.png). Would that change anything? – Matt Cavanagh Jan 21 '15 at 14:33
  • I think it might work when you ignore the 'match' attribute on each StatsPlayer when serializing it. (So you would have to serialize each object on it's own.) It might very well be that the serializer is trying to serialize the match object, which then will try to serialize all the StatsPlayer objects, creating in infinite loop. – Nico Kaag Jan 21 '15 at 14:38
  • Ok, I gave that a go. Although I got a error: `Catchable Fatal Error: Argument 1 passed to Symfony\Component\Serializer\Serializer::__construct() must be of the type array, object given, called in /var/www/planetsidebattles.org/dev/src/PSB/AdminBundle/Controller/StreamingController.php on line 57 and defined` Heres the code currently: http://puu.sh/ePdyt/235873e8aa.png – Matt Cavanagh Jan 21 '15 at 14:51
  • According to the documentation, your last line should be: $serializer = new Serializer(array($normalizer), $encoders); – Nico Kaag Jan 21 '15 at 15:05
  • Ahh that worked! So I take it now that the data is JSON encoded, I could just do `$.JSON.parse($data["key"]);` in order to have it accessible by javascript? – Matt Cavanagh Jan 21 '15 at 15:20
  • Oh actually theres a slight snag. The output is including HTML entities in there, e.g. `{"id":3868,"playerID":"5428245075223380049","playerName":"Maelstrome26Jaeger"}` Any way round that? – Matt Cavanagh Jan 21 '15 at 15:29
  • Actually never mind, I forgot Twig had |raw filters. Looks like everything is working now, thanks very much dude! – Matt Cavanagh Jan 21 '15 at 15:31
  • Perfect! The "$normalizer->setIgnoredAttributes(array('match'));" solution works for me. Thanks! – Marcelo Rodovalho Oct 27 '15 at 18:29