Yii2 - how to force response JSON formatter to use objects instead of arrays? - php

I know I can set Yii::$app->response->format = \yii\web\Response::FORMAT_JSON but how I can make it set the JSON encoding flag JSON_FORCE_OBJECT so that all arrays will be encoded as objects instead?

Alright, it wasn't so hard:
Yii::$app->response->formatters[\yii\web\Response::FORMAT_JSON] = [
'class' => 'yii\web\JsonResponseFormatter',
'encodeOptions' => JSON_FORCE_OBJECT,
];
Or even as a one-liner:
Yii::$app->response->formatters[\yii\web\Response::FORMAT_JSON]['encodeOptions'] = JSON_FORCE_OBJECT;

Related

What kind query string format is this [key:value] , and how can I (re)create it?

I work with laravel - guzzle. I am using an api where I need to pass the query string like:
http:://domain.com/WS.php?secret=123123&app=app1&message=[key:value][key2:value][key3:value]
I am using this array to gather the get data:
$query = [
'query' => [
'app' => 'app1',
'secret' => '123123',
'message' => [
'key1' => 'value',
'key2' => 'value',
'key3' => 'value',
]
]
]
I am not sure how I can convert this to the requested query string. Actually I am not familiar with this part [key:value] at all. I could manually create a string by my self(last resort perhaps) but I am looking for a better way than that to this.
The supported query string syntax for PHP arrays is:
variable[key?]=value
So,
message[key]=value&message[key2]=value
Supported doesn't mean the only way, it's just the expected way when dealing with PHP since it doesn't require you to do any additional manipulation.
There's really no limit to how you deal with input in your own application and if they designed it to read the stdin or input this way, that's what you have to send. I doubt there's anything built in to support this, but why can't you just loop through the array to build a string for message:
foreach($message as $key=>$value) {
$str .= "[$key:$value]";
}

Creating json_array objects with Elasticsearch-PHP

I am trying to index where the field i have mapped requires an object.
According to:
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_dealing_with_json_arrays_and_objects_in_php.html
$params['body'] = [
'location' => new \stdClass()
];
should have been sufficient to indicate an empty PHP Object, but it fails on the miss match stating that location is an object mapping and It is wrong.
I have tried the following also:
$params['body'] = [
'location' => new \stdClass(['lat'=>0,'lon'=>0])
];
But that failed with the same reason.
However if I do a raw curl api to elasticsearch:
curl -XPOST 'http://localhost:9200/my_index/my_type/1' -d '{"location":{"lat":0.0,"lon":0.0}}'
this works.
You can also simply try using an associative array, it will work:
$params['body'] = [
'location' => array( 'lat' => 0, 'lon' => 0 )
];

JSON_FORCE_OBJECT in lower version of PHP

My PHP server doesn't accept second parameter for json_encode (and I need JSON_FORCE_OBJECT). Is there any way to achive simmilar effect as JSON_FORCE_OBJECT if server doesn't support it? Mybe you know some custom functions simmilar to json_encode?
This should work, too:
$data = array(
'foo' => (object) array('bar' => 'foo'),
);
echo json_encode($data); // should output {"foo": {"bar": "foo"}}

Using PHP Guzzle HTTP 6 to send JSON with data that is already encoded

I am trying to send a POST request which contains a raw JSON string with the following header: Content-Type: application/json.
From looking at the docs, I can see that I can do something like this...
$data = ['x' => 1, 'y' => 2, 'z' => 3];
$client = new \GuzzleHttp\Client($guzzleConfig);
$options = [
'json' => $data,
];
$client->post('http://example.com', $options);
My problem is that when I get to this point, $data has already been json_encode'd.
I have tried the following but it does not work.
$data = json_encode(['x' => 1, 'y' => 2, 'z' => 3]);
$client = new \GuzzleHttp\Client($guzzleConfig);
$options = [
'body' => $data,
'headers' => ['Content-Type' => 'application/json'],
];
$client->post('http://example.com', $options);
My question is: can I use the json option with an already-encoded array? Or is there a way for me to simply set the Content-Type header?
According to guzzle's docs http://docs.guzzlephp.org/en/latest/request-options.html#json
You can pass the already encoded json directly into the body parameter
Note This request option does not support customizing the Content-Type
header or any of the options from PHP's json_encode() function. If you
need to customize these settings, then you must pass the JSON encoded
data into the request yourself using the body request option and you
must specify the correct Content-Type header using the headers request
option.
This option cannot be used with body, form_params, or multipart
Guzzle also provides the json Request option which will automatically encode your content and set the Content-Type header. More information at the link. In fact the example provided uses a PUT request.
$response = $client->request('PUT', '/put', ['json' => ['foo' => 'bar']]);

Symfony convert entity to json format by looping foreach

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.

Resources