1[[connceting]]
2== Connecting
3
4This page contains the information you need to connect and use the Client with
5{es}.
6
7**On this page**
8
9* <<authentication, Authentication options>>
10* <<client-usage, Using the client>>
11
12
13[discrete]
14[[authentication]]
15=== Authentication
16
17This section contains code snippets to show you how to connect to various {es}
18providers.
19
20[discrete]
21[[auth-ec]]
22==== Elastic Cloud
23
24You can connect to Elastic Cloud using **Basic authentication**:
25
26[source,php]
27----
28$client = ClientBuilder::create()
29   ->setElasticCloudId('<cloud-id>')
30   ->setBasicAuthentication('<username>', '<password>')
31   ->build();
32----
33
34Where <cloud-id> is reported in the Deployment UI, and <username>, <password>
35are generated when you deploy a new cloud instance. You need to store the
36<username> and <password> since they will not be available via UI.
37
38Or using an **API key**:
39
40[source,php]
41----
42$client = ClientBuilder::create()
43   ->setElasticCloudId('<cloud-id>')
44   ->setApiKey('<id>', '<key>')
45   ->build();
46----
47
48Where <id> and <key> are generated when you create a new API key. The API key is
49equivalent to Base64(<id>:<key>). You need to store the API key since it will
50not be available via UI.
51
52
53[discrete]
54[[auth-http]]
55==== HTTP Authentication
56
57If your {es} server is protected by HTTP authentication, you need to provide the
58credentials to ES-PHP so that requests can be authenticated server-side.
59Authentication credentials are provided as part of the host array when
60instantiating the client:
61
62[source,php]
63----
64$hosts = [
65    'http://user:pass@localhost:9200',       // HTTP Basic Authentication
66    'http://user2:pass2@other-host.com:9200' // Different credentials on different host
67];
68
69$client = ClientBuilder::create()
70                    ->setHosts($hosts)
71                    ->build();
72----
73
74Credentials are provided per-host, which allows each host to have their own set
75of credentials. All requests sent to the cluster use the appropriate credentials
76depending on the node being talked to.
77
78
79[discrete]
80[[auth-apikey]]
81==== ApiKey authentication
82
83If your {es} cluster is secured by API keys as described
84{ref-7x}/security-api-create-api-key.html[here], you can use these values to
85connect the client with your cluster, as illustrated in the following code
86snippet.
87
88[source,php]
89----
90$client = ClientBuilder::create()
91                    ->setApiKey('id', 'api_key') <1>
92                    ->build();
93----
94<1> ApiKey pair of `id` and `api_key` from the create API key response.
95
96
97[discrete]
98[[ssl-encryption]]
99==== SSL encryption
100
101Configuring SSL is a little more complex. You need to identify if your
102certificate has been signed by a public Certificate Authority (CA), or if it is
103a self-signed certificate.
104
105[NOTE]
106.A note on libcurl version
107=================
108If you believe the client is configured to correctly use SSL, but it simply is
109not working, check your libcurl version. On certain platforms, various features
110may or may not be available depending on version number of libcurl. For example,
111the `--cacert` option was not added to the OSX version of libcurl until version
1127.37.1. The `--cacert` option is equivalent to PHP's `CURLOPT_CAINFO` constant,
113meaning that custom certificate paths will not work on lower versions.
114
115If you are encountering problems, update your libcurl version and/or check the
116http://curl.haxx.se/changes.html[curl changelog].
117=================
118
119
120[discrete]
121===== Public CA Certificates
122
123If your certificate has been signed by a public Certificate Authority and your
124server has up-to-date root certificates, you only need to use `https` in the
125host path. The client automatically verifies SSL certificates:
126
127[source,php]
128----
129$hosts = [
130    'https://localhost:9200' <1>
131];
132
133$client = ClientBuilder::create()
134                    ->setHosts($hosts)
135                    ->build();
136----
137<1> Note that `https` is used, not `http`
138
139
140If your server has out-dated root certificates, you may need to use a
141certificate bundle. For PHP clients, the best way is to use
142https://github.com/composer/ca-bundle[composer/ca-bundle]. Once installed, you
143need to tell the client to use your certificates instead of the system-wide
144bundle. To do this, specify the path to verify:
145
146[source,php]
147----
148$hosts = ['https://localhost:9200'];
149$caBundle = \Composer\CaBundle\CaBundle::getBundledCaBundlePath();
150
151$client = ClientBuilder::create()
152                    ->setHosts($hosts)
153                    ->setSSLVerification($caBundle)
154                    ->build();
155----
156
157
158[discrete]
159===== Self-signed Certificates
160
161Self-signed certificates are certs that have not been signed by a public CA.
162They are signed by your own organization. Self-signed certificates are often
163used for internal purposes, when you can securely spread the root certificate
164yourself. It should not be used when being exposed to public consumers, since
165this leaves the client vulnerable to man-in-the-middle attacks.
166
167If you are using a self-signed certificate, you need to provide the certificate
168to the client. This is the same syntax as specifying a new root bundle, but
169instead you point to your certificate:
170
171[source,php]
172----
173$hosts = ['https://localhost:9200'];
174$myCert = 'path/to/cacert.pem';
175
176$client = ClientBuilder::create()
177                    ->setHosts($hosts)
178                    ->setSSLVerification($myCert)
179                    ->build();
180----
181
182
183[discrete]
184[[http-ssl]]
185==== Using authentication with SSL
186
187It is possible to use HTTP authentication with SSL. Simply specify `https` in
188the URI, configure SSL settings as required and provide authentication
189credentials. For example, this snippet authenticates using Basic HTTP auth and a
190self-signed certificate:
191
192[source,php]
193----
194$hosts = ['https://user:pass@localhost:9200'];
195$myCert = 'path/to/cacert.pem';
196
197$client = ClientBuilder::create()
198                    ->setHosts($hosts)
199                    ->setSSLVerification($myCert)
200                    ->build();
201----
202
203
204[discrete]
205[[client-comp]]
206=== Enabling the Compatibility Mode
207
208The Elasticsearch server version 8.0 is introducing a new compatibility mode that
209allows you a smoother upgrade experience from 7 to 8. In a nutshell, you can use
210the latest 7.x Elasticsearch client with an 8.x Elasticsearch server, giving more
211room to coordinate the upgrade of your codebase to the next major version.
212
213If you want to leverage this functionality, please make sure that you are using the
214latest 7.x client and set the environment variable `ELASTIC_CLIENT_APIVERSIONING`
215to `true`. The client is handling the rest internally. For every 8.0 and beyond
216client, you're all set! The compatibility mode is enabled by default.
217
218
219[discrete]
220[[client-usage]]
221=== Usage
222
223This section is a crash-course overview of the client and its syntax. If you
224are familiar with {es}, you'll notice that the methods are named just like REST
225endpoints.
226
227You may also notice that the client is configured in a manner that facilitates
228easy discovery via your IDE. All core actions are available under the `$client`
229object (indexing, searching, getting, etc). Index and cluster management are
230located under the `$client->indices()` and `$client->cluster()` objects,
231respectively.
232
233
234[discrete]
235==== Indexing a document
236
237In elasticsearch-php, almost everything is configured by associative arrays. The
238REST endpoint, document and optional parameters - everything is an associative
239array.
240
241To index a document, we need to specify three pieces of information: index, id
242and a document body. This is done by constructing an associative array of
243key:value pairs. The request body is itself an associative array with key:value
244pairs corresponding to the data in your document:
245
246[source,php]
247----------------------------
248$params = [
249    'index' => 'my_index',
250    'id'    => 'my_id',
251    'body'  => ['testField' => 'abc']
252];
253
254$response = $client->index($params);
255print_r($response);
256----------------------------
257
258The response that you get back indicates that the document was created in the
259index that you specified. The response is an associative array containing a
260decoded version of the JSON that {es} returns:
261
262
263[source,php]
264----------------------------
265Array
266(
267    [_index] => my_index
268    [_type] => _doc
269    [_id] => my_id
270    [_version] => 1
271    [created] => 1
272)
273
274----------------------------
275
276
277[discrete]
278==== Getting a document
279
280Let's get the document that we just indexed. This returns the document:
281
282[source,php]
283----------------------------
284$params = [
285    'index' => 'my_index',
286    'id'    => 'my_id'
287];
288
289$response = $client->get($params);
290print_r($response);
291----------------------------
292
293
294The response contains metadata such as index, version, and so on as well as a
295`_source` field, which is the original document you sent to {es}.
296
297[source,php]
298----------------------------
299Array
300(
301    [_index] => my_index
302    [_type] => _doc
303    [_id] => my_id
304    [_version] => 1
305    [found] => 1
306    [_source] => Array
307        (
308            [testField] => abc
309        )
310
311)
312----------------------------
313
314
315[discrete]
316==== Searching for a document
317
318Searching is a hallmark of {es}, so let's perform a search. We are going to use
319the `match` query as a demonstration:
320
321[source,php]
322----------------------------
323$params = [
324    'index' => 'my_index',
325    'body'  => [
326        'query' => [
327            'match' => [
328                'testField' => 'abc'
329            ]
330        ]
331    ]
332];
333
334$response = $client->search($params);
335print_r($response);
336----------------------------
337
338The response here is different from the previous ones. You can see metadata
339(`took`, `timed_out`, etc.) and an array named `hits`. This represents your
340search results. Inside of `hits` is another array named `hits`, which contains
341individual search results:
342
343[source,php]
344----------------------------
345Array
346(
347    [took] => 1
348    [timed_out] =>
349    [_shards] => Array
350        (
351            [total] => 5
352            [successful] => 5
353            [failed] => 0
354        )
355
356    [hits] => Array
357        (
358            [total] => 1
359            [max_score] => 0.30685282
360            [hits] => Array
361                (
362                    [0] => Array
363                        (
364                            [_index] => my_index
365                            [_type] => _doc
366                            [_id] => my_id
367                            [_score] => 0.30685282
368                            [_source] => Array
369                                (
370                                    [testField] => abc
371                                )
372                        )
373                )
374        )
375)
376----------------------------
377
378
379[discrete]
380==== Deleting a document
381
382Alright, let's go ahead and delete the document that we added previously:
383
384[source,php]
385----------------------------
386$params = [
387    'index' => 'my_index',
388    'id'    => 'my_id'
389];
390
391$response = $client->delete($params);
392print_r($response);
393----------------------------
394
395This syntax is identical to the `get` syntax. The only difference is the
396operation: `delete` instead of `get`. The response confirms the document is
397deleted:
398
399[source,php]
400----------------------------
401Array
402(
403    [found] => 1
404    [_index] => my_index
405    [_type] => _doc
406    [_id] => my_id
407    [_version] => 2
408)
409----------------------------
410
411
412[discrete]
413==== Deleting an index
414
415Due to the dynamic nature of {es}, the first document you added automatically
416built an index with some default settings. Delete that index and specify your
417own settings later:
418
419[source,php]
420----------------------------
421$deleteParams = [
422    'index' => 'my_index'
423];
424$response = $client->indices()->delete($deleteParams);
425print_r($response);
426----------------------------
427
428The response:
429
430
431[source,php]
432----------------------------
433Array
434(
435    [acknowledged] => 1
436)
437----------------------------
438
439
440[discrete]
441==== Creating an index
442
443Now that you are starting fresh (no data or index), add a new index with custom
444settings:
445
446[source,php]
447----------------------------
448$params = [
449    'index' => 'my_index',
450    'body' => [
451        'settings' => [
452            'number_of_shards' => 2,
453            'number_of_replicas' => 0
454        ]
455    ]
456];
457
458$response = $client->indices()->create($params);
459print_r($response);
460----------------------------
461
462{es} now creates that index with your chosen settings and return an
463acknowledgement:
464
465[source,php]
466----------------------------
467Array
468(
469    [acknowledged] => 1
470)
471----------------------------
472