1[[php_json_objects]]
2=== Dealing with JSON arrays and objects in PHP
3
4A common source of confusion with the client revolves around JSON arrays and
5objects, and how to specify them in PHP. In particular, problems are caused by
6empty objects and arrays of objects. This page shows you some common patterns
7used in {es} JSON API and how to convert that to a PHP representation.
8
9[discrete]
10==== Empty Objects
11
12The {es} API uses empty JSON objects in several locations which can cause
13problems for PHP. Unlike other languages, PHP does not have a "short" notation
14for empty objects and many developers are unaware how to specify an empty
15object.
16
17Consider adding a highlight to a query:
18
19[source,json]
20----
21{
22    "query" : {
23        "match" : {
24            "content" : "quick brown fox"
25        }
26    },
27    "highlight" : {
28        "fields" : {
29            "content" : {} <1>
30        }
31    }
32}
33----
34<1> This empty JSON object is what causes problems.
35
36The problem is that PHP will automatically convert `"content" : {}` into
37`"content" : []`, which is no longer valid {es} DSL. We need to tell PHP that
38the empty object is explicitly an object, not an array. To define this query in
39PHP, you would do:
40
41[source,json]
42----
43$params['body'] = array(
44    'query' => array(
45        'match' => array(
46            'content' => 'quick brown fox'
47        )
48    ),
49    'highlight' => array(
50        'fields' => array(
51            'content' => new \stdClass() <1>
52        )
53    )
54);
55$results = $client->search($params);
56----
57<1> We use the generic PHP stdClass object to represent an empty object. The
58JSON now encodes correctly.
59
60By using an explicit stdClass object, we can force the `json_encode` parser to
61correctly output an empty object, instead of an empty array. This verbose
62solution is the only way to acomplish the goal in PHP... there is no "short"
63version of an empty object.
64
65[discrete]
66==== Arrays of Objects
67
68Another common pattern in {es} DSL is an array of objects. For example, consider
69adding a sort to your query:
70
71[source,json]
72----
73{
74    "query" : {
75        "match" : { "content" : "quick brown fox" }
76    },
77    "sort" : [  <1>
78        {"time" : {"order" : "desc"}},
79        {"popularity" : {"order" : "desc"}}
80    ]
81}
82----
83<1> "sort" contains an array of JSON objects.
84
85This arrangement is very common, but the construction in PHP can be tricky since
86it requires nesting arrays. The verbosity of PHP tends to obscure what is
87actually going on. To construct an array of objects, you actually need an array
88of arrays:
89
90[source,json]
91----
92$params['body'] = array(
93    'query' => array(
94        'match' => array(
95            'content' => 'quick brown fox'
96        )
97    ),
98    'sort' => array(    <1>
99        array('time' => array('order' => 'desc')),  <2>
100        array('popularity' => array('order' => 'desc')) <3>
101    )
102);
103$results = $client->search($params);
104----
105<1> This array encodes the `"sort" : []` array
106<2> This array encodes the `{"time" : {"order" : "desc"}}` object
107<3> This array encodes the `{"popularity" : {"order" : "desc"}}` object
108
109If you are on PHP 5.4+, we strongly encourage you to use the short array syntax.
110It makes these nested arrays much simpler to read:
111
112[source,json]
113----
114$params['body'] = [
115    'query' => [
116        'match' => [
117            'content' => 'quick brown fox'
118        ]
119    ],
120    'sort' => [
121        ['time' => ['order' => 'desc']],
122        ['popularity' => ['order' => 'desc']]
123    ]
124];
125$results = $client->search($params);
126----
127
128[discrete]
129==== Arrays of empty objects
130
131Occasionally, you'll encounter DSL that requires both of the previous patterns.
132The function score query is a good example, it sometimes requires an array of
133objects, and some of those objects might be empty JSON objects.
134
135Given this query:
136
137[source,json]
138----
139{
140   "query":{
141      "function_score":{
142         "functions":[
143            {
144               "random_score":{}
145            }
146         ],
147         "boost_mode":"replace"
148      }
149   }
150}
151----
152
153We can build it using the following PHP code:
154
155
156[source,json]
157----
158$params['body'] = array(
159    'query' => array(
160        'function_score' => array(
161            'functions' => array(  <1>
162                array(  <2>
163                    'random_score' => new \stdClass() <3>
164                )
165            )
166        )
167    )
168);
169$results = $client->search($params);
170----
171<1> This encodes the array of objects: `"functions" : []`
172<2> This encodes an object inside the array: `{ "random_score": {} }`
173<3> This encodes the empty JSON object: `"random_score": {}`