Symfony convert entity to json format by looping foreach - php

I have a little REST API in my project. And ofcourse i use json as my return data to work with.
I am using symfony in the backend and angularJs in the frontend. At the moment i convert my entity to json by looping true my result and filling an data array to return as json.
EXAMPLE:
public function getAction($id)
{
$em = $this->getDoctrine()->getManager();
$warehouseId = $this->get('session')->get('warehouse');
$warehouse = $em->getRepository('BubbleMainBundle:Warehouse')->find($warehouseId);
$trip = $em->getRepository('BubbleMainBundle:Trip')->find($id);
$data = array(
'id' => $trip->getId(),
'driver' => $trip->getDriver(),
'status' => $trip->getStatus(),
'date' => $trip->getPlanningDate()->format('Y-m-d')
);
if ( count($trip->getStops()) > 0 ) {
foreach($trip->getStops() as $stop)
{
$data['assignedStops'][] = array(
'id' => $stop->getId(),
'status' => $stop->getStatus(),
'date' => $stop->getDeliveryDate()->format('Y-m-d'),
'sort' => $stop->getSort(),
'company' => array(
'name' => $stop->getToCompany()->getName(),
'lat' => $stop->getToCompany()->getLat(),
'lng' => $stop->getToCompany()->getLng(),
'address' => $stop->getToCompany()->getAddress(),
'zip' => $stop->getToCompany()->getZip()
),
);
}
} else {
$data['assignedStops'][] = '';
}
$response = new jsonResponse();
$response->setData($data);
return $response;
}
This works. But sometimes i have have (google chrome timeline) waiting responses of 6 seconds for just a simple query and json response.
Is looping true the entity to much? Or do i need another approach for converting my entities to json format?
thx anthony,

If you are using PHP 5.4 or above then considering using the JsonSerializable interface with your entities:
http://www.php.net/manual/en/class.jsonserializable.php
This will allow you to control how your entities are converted to JSON which will allow you to call json_encode directly on your entities without having to loop through and convert them to arrays.
As for the performance issue you'd need to profile your script to find out where the performance bottleneck is. From looking at your code one potential issue that you might want to look into is to make sure you are fetching all the data in your original query (i.e stops and companies) and you are not executing additional queries in the foreach loop to fetch the missing stop and company data.

I recommend you (since you are using Symfony2 as a backend and you need an API) to definitely try out this bundle... It's easy to use and to setup and as an extra you can also generate a nice documentation for it.
It will speed up your development and code.

Related

Trying to get multidimensional array to a query string

I am trying to build a multidimensional array to a query string for an API request.
$key = env('GRAPHHOPPER_API_KEY', null);
$baseUrl = "https://graphhopper.com/api/1/route";
$formData = [
'point' => [request()->input('point1'), request()->input('point2')],
'key' => $key,
];
$queryStr = http_build_query($formData);
$url = $baseUrl.'?'.$queryStr;
try {
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', $url, [
\GuzzleHttp\RequestOptions::JSON => $formData
]);
$result = json_decode($response->getBody(), true);
dd('result', $result);
}
catch (\Exception $e)
{
return response()->json([
'status' => 0,
'message' => $e->getMessage(),
'trace' => $e->getTrace()
]);
}
This is what it looks like when I DD out:
The error from API tells me it's expecting two points so I guess I am not building the query string collecting
Docs: https://docs.graphhopper.com/#tag/Routing-API
Error:
resulted in a 400 Bad Request response:\n{\"message\":\"Specify at
least 2 points\"}
The docs page you linked to shows you how to structure the querystring data (see the testbed on the right hand side)
e.g.
?point=51.131,12.414&point=48.224,3.867
So there are two "point" entries, each containing two data items in comma-separated format.
Whereas you've got four separate "point[x][y]" variables in your querystring output. Your dd output suggests that request()->input('point1') and request()->input('point2') are themselves arrays. So what you've got is an array consisting of two further arrays, rather than a flat structure.
I think you need to write it like this:
'point' => [request()->input('point1')[0].",".request()->input('point1')[1], request()->input('point2')[0].","request()->input('point2')[1]]
Try that, I think it should work, or at least get you a lot closer to where you need to be.

Laravel Model Factory - Large JSON Stubs

I am pulling order information from an external API and saving the entire JSON response into a documents table.
I obviously do not want to call this API when testing so I have setup a factory, but I am struggling with how to pull in these JSON stubs. For example:
// factory
$factory->define(App\OrderDocument::class, function (Faker $faker) {
return [
'document_id' => $faker->uuid,
'status' => $faker->randomElement(['open', 'partial', 'processed', 'updating']),
'document' => $faker->text
];
});
// Currently using it like...
foreach ($this->fullDocuments() as $id => $document){
$a = factory(\App\OrderDocument::class)->create([
'document_id' => $id,
'status' => 'full'
]);
$a->setRawAttributes(['document' => $document]);
$a->save();
}
where $this->fullDocuments() contains an array of the document_id and raw JSON response from the API.
I know a better way to do this is to factory the entire JSON document. The JSON contains about 500 lines so it would be very time consuming but also I do not own this data, so I assume I should not be trying to fake it.
Within my test, I would prefer to do something like the below, but am not sure how.
factory(OrderDocument::class, 10)->create([
'document_id' => $this->getDocumentId($i++),
'document' => $this->getDocumentStub($i++),
]);

How to construct a graphql mutation query request in php

I am having the hardest time figuring out how to properly format a graphql api mutation POST request in php.
If I hard code the string and use it as the data in my POST request it works like this:
'{"query":"mutation{addPlay(input: {title: \"two\"}){ properties { title } } }"}'
But if I have a php array of the input values:
$test_data = array(
'title' => 'two'
);
I can't seem to format it correctly. json_encode also puts double quotes around the keys which graphql is rejecting with the error Syntax Error GraphQL request (1:26) Expected Name, found String.
I ultimately need a solution that will convert a larger more complex array to something usable.
Reformatting the query allowed me to use JSON directly.
So my new query looks like this:
$test_data = array(
'title' => 'two'
);
$request_data = array(
'query' => 'mutation ($input: PlayInput) { addPlay(input: $input) { properties { title } }}',
'variables' => array(
'input' => $test_data,
),
);
$request_data_json = json_encode($request_data);
Then the $request_data_json is used in a POST http request.

How To Add Additional Field Mappings To Code Pulling from Third Party API

I am working with the Church Community Builder API (official docs, search for "group profile" to see relevant code) and with CCB Core WordPress Plugin to sync groups data from the API into custom post types (fields, taxonomies).
CCB Core maps a lot of this data automatically, but it doesn't map the group ID value CCB uses to distinguish one group from another and I'd like to sync it.
The relevant code is kept in the functions get_groups_custom_fields_map() and get_groups_taxonomy_map().
I've tried adding something like the following to get_groups_taxonomy_map():
'group_id' => array (
'api_mapping' => 'group',
'data_type' => 'integer',
),
But this doesn't work. Any suggestions on writing code to pull in this field?
UPDATE 9/10/16 7:25 PM:
I think I am wicked close.
I took the XML from the API documentation under Group Profile and ran it through simplexml and generated this output.
I then compared the output with how the get_groups_custom_fields_map and get_groups_custom_taxonomy_map was organized, which led me to believe the following should work:
'group' => array (
'api_mapping' => 'group',
'data_type' => 'object',
'child_object' => array(
'api_mapping' => '#attributes',
'data_type' => 'object',
'child_object' => array(
'group_id' => array(
'api_mapping' => 'id',
'data_type' => 'integer'
)
)
)
),
But it doesn't. What am I missing?
The SimpleXML representation of the response that comes back from CCB just so happens to have a really frustrating way of deserializing the IDs for the entities (Groups, Events, Individuals, etc) that come out of the API. (And it only happens on the IDs).
Even though Group ID looks like a property in the XML response string, it's actually an attribute which is slightly different. In your object response, notice that # symbol in the [#attributes] node. PHP will not allow direct access to that.
See "At sign" # in SimpleXML object?
As a workaround I actually obtain the Group ID like so right here:
https://github.com/jaredcobb/ccb-core/blob/1a6e88b47ad7d5293e88bac277e72cbc4e33a602/admin/class-ccb-core-sync.php#L589-L595
Code snippet of the above reference:
$group_id = 0;
foreach( $group->attributes() as $key => $value ) {
if ( $key == 'id' ) {
$group_id = (int) $value;
break;
}
}
So in general, we do have access to that group id, we just need to now save it as post meta. I'll update the plugin to take advantage of these IDs, but in the mean time you can use the $group_id variable directly and save the post meta in this function.

Write php array in HBase using thrift

I have a Thrift php client and I want to write in a HBase table and I'm doing the following:
$mutations = array(
new Mutation( array(
'column' => 'entry:num',
'value' => array('a','b','c')
) ),
);
$client->mutateRow( $t, $row, $mutations );
The problem is that when inserting in HBase the value, which is an array, gets converted to 'Array' instead of storing the elements of the array.
How can I store the list as an array (or byte array)
A HBase mutation object has required three fields with boolean/text values, not arrays. So you need to turn any structured value into a string, something like.
$mutations = array(
new Mutation( array(
'isDelete' => FALSE,
'column' => 'entry:num',
'value' => serialize(array('a','b','c'))
) ),
);
$client->mutateRow( $t, $row, $mutations );
The definition of the HBase Thrift API is here;
http://svn.apache.org/viewvc/hbase/trunk/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift?view=markup
I haven't tested this.
I must admit that I do not have a clue what you're trying to do (perhaps due to a lack of knowledge regarding Thrift and HBase), but if I understood your question correctly, you're trying to write some PHP data structure (array in this case) to a storage media. To achieve this you have to serialize your data somehow. That could be using a custom XML serialization, a custom binary serialization or, perhaps the most simple solution, the PHP internal serialization mechanism provided by serialize() and the corresponding unserialize().
If you strive for inter-language-interoperability you should use a custom serialization or you have to write a unserialization function that unserializes the PHP serialization format in your target language.
Just a quick example - I don't know where you'd have to put this code, as I don't know exactly what you're doing:
$mutations = array(
new Mutation(array(
'column' => 'entry:num',
'value' => array('a','b','c')
)),
);
$data = serialize($mutations); // $data now is a string
// write $data to storage
// read $readData from storage
$readMutations = unserialize($readData);
// $readMutations == $mutations
// (but the Mutation instances are not the same instances any more)
Please seee
serialize()
unserialize()
Serializing objects - objects in sessions

Categories