thephpleague / fractal

Output complex, flexible, AJAX/RESTful data structures.

Home Page:fractal.thephpleague.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

XML Support

judos opened this issue · comments

I read this issue: #178
And it is mentioned that it should be possible to output xml somehow with a custom serializer.
However I don't get yet how this should work exactly.
Can anyone help with some more details?

I use the following endpoint in element-api.php

// Sitemap
'sitemap' => function() {
	return [
		'criteria' => [
			'section' => 'pages',
		],
		'transformer' => new SitemapTransformer(),
		'serializer' => new XmlSerializer()
	];
},

But then i'm unsure how to write the XmlSerializer. As I see almost all methods from SerializerAbstract should return an array so how can I make it return xml?

/edit1:
As I see now the DefaultController uses the Scope class which does this:

public function toArray() {
 ...
 return $data + $meta;
}

And besides the DefaultController also uses a JSON Formatter:

public function actionIndex(string $pattern): Response {
 ...
 $formatter = new JsonResponseFormatter([ ... ]);
}

So basically that makes it look impossible to actually have an xml response. Did this change over time of why was it possible before?

So up to now i'm still pretty sure that xml is impossible, because fractal/element-api is pretty much coded only for json.
So in the meantime I wrote myself a module to return xml myself. The controller uses this code to return xml:

public function actionIndex() {
  $response = Craft::$app->getResponse();
  $response->content = '<myxml>...</myxml>';
  $response->format = Response::FORMAT_XML;
  return $response;
}

Why did you close this? It's still a very valid issue if true? I was just about to start down this journey.

Here is the docs on the Serializers: https://fractal.thephpleague.com/serializers/

If you have an XML serializer you built, it needs to implement the SerializerAbstract class for Fractal to pick it up.

This is actually a valid point, the serializer returns arrays of data which then gets converted into JSON by the scope, with the toJson method, so the serializer only ever returns array data.

Rather than the scope returning JSON, you can use toArray and do something like this

$data = $fractal->createData()->toArray();

$sxml = new SimpleXMLElement('<root />');
array_walk_recursive($data, [$sxml, 'addChild']);

return $xml = $sxml->asXML();

this is obviously not ideal. when theSerializer could build the SimpleXML object on the fly, and return the XML, so maybe we need to change the burden of where the conversion (not serialization) to JSON / XML happens.

Im going to close this for now as it seems like we found a good solution and no follow up. If this is still an issue please reopen.