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