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