## File: README.md

# Elasticsearch PHP client

[](https://github.com/elastic/elasticsearch-php/actions) [](https://packagist.org/packages/elasticsearch/elasticsearch) [](https://packagist.org/packages/elasticsearch/elasticsearch)

This is the official PHP client for
[Elasticsearch](https://www.elastic.co/elasticsearch/).

You can run [Elasticsearch](https://www.elastic.co/elasticsearch) and [Kibana](https://www.elastic.co/kibana) on your local machine using this command:

```bash
curl -fsSL https://elastic.co/start-local | sh
```
or **[sign-up](https://cloud.elastic.co/registration?elektra=en-ess-sign-up-page)**
**for a free trial of Elastic Cloud**.

## Contents

- [Installation](#installation)
- [Connecting](#connecting)
- [Usage](#usage)
- [Versioning](#versioning)
- [Backward Incompatible Changes](#backward-incompatible-changes-boom)
- [Mock the Elasticsearch client](#mock-the-elasticsearch-client)
- [FAQ](#faq-)
- [Contribute](#contribute-)
- [License](#license-)

***

## Installation

Refer to the [Installation section](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_installation)
of the getting started documentation.

## Connecting

Refer to the [Connecting section](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_connecting)
of the getting started documentation.

## Usage

The `elasticsearch-php` client offers 500+ endpoints for interacting with
Elasticsearch. A list of all these endpoints is available in the
[official documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html)
of Elasticsearch APIs.

Here we reported the basic operation that you can perform with the client:
index, search and delete.

- [Creating an index](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_creating_an_index)
- [Indexing a document](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_indexing_documents)
- [Getting documents](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_getting_documents)
- [Searching documents](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_searching_documents)
- [Updating documents](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_updating_documents)
- [Deleting documents](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_deleting_documents)
- [Deleting an index](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html#_deleting_an_index)

### Versioning

This client is versioned and released alongside Elasticsearch server.

To guarantee compatibility, use the most recent version of this library within
the major version of the corresponding Enterprise Search implementation.

For example, for Elasticsearch `8.16`, use `8.16` of this library or above, but
not `9.0`.

## Compatibility

The Elasticsearch client is compatible with currently maintained PHP versions.

Language clients are forward compatible; meaning that clients support
communicating with greater or equal minor versions of Elasticsearch without
breaking. It does not mean that the client automatically supports new features
of newer Elasticsearch versions; it is only possible after a release of a new
client version. For example, a 8.12 client version won't automatically support
the new features of the 8.13 version of Elasticsearch, the 8.13 client version
is required for that. Elasticsearch language clients are only backwards
compatible with default distributions and without guarantees made.

| Elasticsearch Version | Elasticsearch-PHP Branch | Supported |
| --------------------- | ------------------------ | --------- |
| main                  | main                     |           |
| 9.x                   | 9.x                      | 9.x       |
| 8.x                   | 8.x                      | 8.x       |

## Backward Incompatible Changes :boom:

The 9.0.0 version of `elasticsearch-php` contains the same architecture of 8.x.
It supports [PSR-7](https://www.php-fig.org/psr/psr-7/) for HTTP messages and
[PSR-18](https://www.php-fig.org/psr/psr-18/) for HTTP client communications.

We tried to avoid BC breaks for `9.x`, here the main changes:

- **Compatibility with Elasticsearch 9.0:** All changes and additions to Elasticsearch APIs for its 9.0 release are reflected in this release.
- **Serverless client merged in:** the `elastic/elasticsearch-serverless` client is being deprecated, and its functionality has been merged back into this client. This should have zero impact on the way the client works by default. If an endpoint is available in serverless, the PHP function will contains a `@group serverless` phpdoc attribute.
If you try to use an endpoint that is not available in serverless you will get a `410` HTTP error with a message as follows:
"this endpoint exists but is not available when running in serverless mode".
The 9.0.0 client can recognize that it is communicating with a serverless instance if you are using a URL managed by Elastic (e.g. `*.elastic.cloud`).
If you are using a proxy, the client will be able to recognize that the host is serverless from the first response. Alternatively, you can explicitly indicate that the host is serverless using the `Client::setServerless(true)` function (`false` by default).
- **New transport library with PSR-18 cURL client as default:** we've removed the Guzzle dependency from the client. By default, the built-in cURL-based HTTP client will be used if no other PSR-18 compatible clients are detected. See release [9.0.0](https://github.com/elastic/elastic-transport-php/releases/tag/v9.0.0) of elastic-transport-php.

You can have a look at the [BREAKING_CHANGES](BREAKING_CHANGES.md) file for more
information.

## Mock the Elasticsearch client

If you need to mock the Elasticsearch client you just need to mock a
[PSR-18](https://www.php-fig.org/psr/psr-18/) HTTP Client.

For instance, you can use the
[php-http/mock-client](https://github.com/php-http/mock-client) as follows:

```php
use Elastic\Elasticsearch\ClientBuilder;
use Elastic\Elasticsearch\Response\Elasticsearch;
use Http\Mock\Client;
use Nyholm\Psr7\Response;

$mock = new Client(); // This is the mock client

$client = ClientBuilder::create()
    ->setHttpClient($mock)
    ->build();

// This is a PSR-7 response
$response = new Response(
    200, 
    [Elasticsearch::HEADER_CHECK => Elasticsearch::PRODUCT_NAME],
    'This is the body!'
);
$mock->addResponse($response);

$result = $client->info(); // Just calling an Elasticsearch endpoint

echo $result->asString(); // This is the body!
```

We are using the `ClientBuilder::setHttpClient()` to set the mock client.
You can specify the response that you want to have using the
`addResponse($response)` function. As you can see the `$response` is a PSR-7
response object. In this example we used the `Nyholm\Psr7\Response` object from
the [nyholm/psr7](https://github.com/Nyholm/psr7) project. If you are using
[PHPUnit](https://phpunit.de/) you can even mock the `ResponseInterface` as
follows:

```php
$response = $this->createMock('Psr\Http\Message\ResponseInterface');
```

**Notice**: we added a special header in the HTTP response. This is the product
check header, and it is required for guarantee that `elasticsearch-php` is
communicating with an Elasticsearch server 8.0+.

For more information you can read the
[Mock client](https://docs.php-http.org/en/latest/clients/mock-client.html)
section of PHP-HTTP documentation.

## FAQ 🔮

### Where do I report issues with the client?

If something is not working as expected, please open an
[issue](https://github.com/elastic/elasticsearch-php/issues/new).

### Where else can I go to get help?

You can checkout the
[Elastic community discuss forums](https://discuss.elastic.co/).

## Contribute 🚀

We welcome contributors to the project. You can refer to the [CONTRIBUTING](CONTRIBUTING.md)
guide for more information.

Thanks in advance for your contribution! :heart:

## License 📗

[MIT](LICENSE) © [Elastic](https://www.elastic.co/)

---

## File: docs/reference/client-helpers.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/client-helpers.html
---

# Client helpers [client-helpers]

The PHP client comes with the following helpers:

* [Iterators](/reference/iterators.md)
* [ES|QL](/reference/esql.md)
* [Bulk ingest](/reference/bulk.md)

---

## File: docs/reference/configuration.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/configuration.html
---

# Configuration [configuration]

Almost every aspect of the client is configurable. Most users only need to configure a few parameters to suit their needs, but it is possible to completely replace much of the internals if required.

Custom configuration is accomplished before the client is instantiated, through the `ClientBuilder` class. You can find all the configuration options and check sample code that helps you replace the various components.

To learn more about JSON in PHP, read [Dealing with JSON arrays and objects in PHP](/reference/php_json_objects.md).

* [Host Configuration](/reference/host-config.md)
* [Set retries](/reference/set-retries.md)
* [HTTP Meta Data](/reference/http-meta-data.md)
* [Enabling the Logger](/reference/enabling_logger.md)
* [Configure the HTTP client](/reference/http-client.md)
* [Namespaces](/reference/namespaces.md)
* [Node Pool](/reference/node_pool.md)
* [Building the client from a configuration hash](/reference/node_pool.md#config-hash)

---

## File: docs/reference/connecting.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/connecting.html
---

# Connecting [connecting]

This page contains the information you need to connect and use the Client with {{es}}.

## Elastic Cloud [auth-ec]

You can connect to [Elastic Cloud](https://www.elastic.co/cloud/) using an ***API key*** and a ***Cloud ID***:

```php
$client = ClientBuilder::create()
   ->setElasticCloudId('<cloud-id>')
   ->setApiKey('<api-key>')
   ->build();
```

Where <cloud-id> and <api-key> can be retrieved using the Elastic Cloud web UI.

You can get the `Cloud ID` from the `My deployment` page of your dashboard (see the red rectangle reported in the screenshot).



You can generate an `API key` in the `Management` page under the section `Security`.



When you click on `Create API key` button you can choose a name and set the other options (eg. restrict privileges, expire after time, etc).



After this step you will get the `API key`in the API keys page.



***IMPORTANT***: you need to copy and store the `API key`in a secure place, since you will not be able to view it again in Elastic Cloud.


## Security by default (HTTPS) [auth-http]

{{es}} 8.0 offers [security by default](https://www.elastic.co/blog/introducing-simplified-elastic-stack-security), that means it uses [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) for protect the communication between client and server.

In order to configure `elasticsearch-php` for connecting to {{es}} 8.0 we need to have the certificate authority file (CA).

You can install {{es}} in different ways, for instance using [Docker](docs-content://deploy-manage/deploy/self-managed/install-elasticsearch-with-docker.md) you need to execute the followind command:

```shell
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.0.1
```

Once you have the docker image installed you can execute {{es}}, for instance using a single-node cluster configuration, as follows:

```shell
docker network create elastic
docker run --name es01 --net elastic -p 9200:9200 -p 9300:9300 -it docker.elastic.co/elasticsearch/elasticsearch:8.0.1
```

This command creates an `elastic` Docker network and start {{es}} using the port `9200` (default).

When you run the docker image a password is generated for the `elastic` user and it’s printed to the terminal (you might need to scroll back a bit in the terminal to view it). You have to copy it since we will need to connect to {{es}}.

Now that {{es}} is running we can get the `http_ca.crt` file certificate. We need to copy it from the docker instance, using the following command:

```shell
docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
```

Once we have the `http_ca.crt` certificate and the `password`, copied during the start of {{es}} , we can use it to connect with `elasticsearch-php` as follows:

```php
$client = ClientBuilder::create()
    ->setHosts(['https://localhost:9200'])
    ->setBasicAuthentication('elastic', 'password copied during Elasticsearch start')
    ->setCABundle('path/to/http_ca.crt')
    ->build();
```

For more information about the Docker configuration of Elasticsearch you can read the official documentation [here](docs-content://deploy-manage/deploy/self-managed/install-elasticsearch-with-docker.md).


## Usage [client-usage]

This section is a crash-course overview of the client and its syntax. If you are familiar with {{es}}, you’ll notice that the methods are named just like REST endpoints.

You may also notice that the client is configured in a manner that facilitates easy discovery via your IDE. All core actions are available under the `$client` object (indexing, searching, getting, etc). Index and cluster management are located under the `$client->indices()` and `$client->cluster()` objects, respectively.


### Info API [_info_api]

You can get information about the {{es}} instance using the `info()` API, as follows:

```php
$response = $client->info();
```

The response that you get back contains the information about {{es}}. The `$response` is an object of `Elastic\Elasticsearch\Response\Elasticsearch` class that implements `ElasticsearchInterface`, PSR-7 [ResponseInterface](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) and [ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php).

This means the `$response` is a [PSR-7](https://www.php-fig.org/psr/psr-7/) object:

```php
echo $response->getStatusCode(); // 200
echo (string) $response->getBody(); // Response body in JSON
```

and also an "array", meaning you can access the response body as an associative array, as follows:

```php
echo $response['version']['number']; // 8.0.0

var_dump($response->asArray());  // response body content as array
```

Moreover, you can also access the response body as object, string or bool:

```php
echo $response->version->number; // 8.0.0

var_dump($response->asObject()); // response body content as object
var_dump($response->asString()); // response body as string (JSON)
var_dump($response->asBool());   // true if HTTP response code between 200 and 300
```


### Indexing a document [_indexing_a_document]

To index a document, we need to specify three pieces of information: index, id and a document body. This is done by constructing an associative array of key:value pairs. The request body is itself an associative array with key:value pairs corresponding to the data in your document:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id',
    'body'  => ['testField' => 'abc']
];

$response = $client->index($params);
print_r($response->asArray());
```

The response that you get back indicates that the document was created in the index that you specified. The response can be rendered as associatve array using the `asArray()` function. The array response contains a decoded version of the JSON that Elasticsearch returns:

```php
Array
(
    [_index] => my_index
    [_type] => _doc
    [_id] => my_id
    [_version] => 1
    [created] => 1
)
```


### Set the body as JSON string [_set_the_body_as_json_string]

If you want you can specify the `body`parameter as JSON string. This can be useful for testing (eg. copy & paste from online code examples) or if you have already some JSON documents to be stored in Elasticsearch.

For instance, the previous index example can be re-written as follows:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id',
    'body'  => '{"testField" : "abc"}'
];

$response = $client->index($params);
print_r($response->asArray());
```


### Getting a document [_getting_a_document]

Let’s get the document that we just indexed. This returns the document:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

$response = $client->get($params);
print_r($response->asArray());
```

The response contains metadata such as index, version, and so on as well as a `_source` field, which is the original document you sent to {{es}}.

```php
Array
(
    [_index] => my_index
    [_type] => _doc
    [_id] => my_id
    [_version] => 1
    [found] => 1
    [_source] => Array
        (
            [testField] => abc
        )

)
```


### Searching for a document [_searching_for_a_document]

Searching is a hallmark of {{es}}, so let’s perform a search. We are going to use the `match` query as a demonstration:

```php
$params = [
    'index' => 'my_index',
    'body'  => [
        'query' => [
            'match' => [
                'testField' => 'abc'
            ]
        ]
    ]
];

$response = $client->search($params);
print_r($response->asArray());
```

The response here is different from the previous ones. You can see metadata (`took`, `timed_out`, etc.) and an array named `hits`. This represents your search results. Inside of `hits` is another array named `hits`, which contains individual search results:

```php
Array
(
    [took] => 1
    [timed_out] =>
    [_shards] => Array
        (
            [total] => 5
            [successful] => 5
            [failed] => 0
        )

    [hits] => Array
        (
            [total] => 1
            [max_score] => 0.30685282
            [hits] => Array
                (
                    [0] => Array
                        (
                            [_index] => my_index
                            [_type] => _doc
                            [_id] => my_id
                            [_score] => 0.30685282
                            [_source] => Array
                                (
                                    [testField] => abc
                                )
                        )
                )
        )
)
```


### Deleting a document [_deleting_a_document]

Alright, let’s go ahead and delete the document that we added previously:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

$response = $client->delete($params);
print_r($response->asArray());
```

This syntax is identical to the `get` syntax. The only difference is the operation: `delete` instead of `get`. The response confirms the document is deleted:

```php
Array
(
    [found] => 1
    [_index] => my_index
    [_type] => _doc
    [_id] => my_id
    [_version] => 2
)
```


### Deleting an index [_deleting_an_index_2]

Due to the dynamic nature of {{es}}, the first document you added automatically built an index with some default settings. Delete that index and specify your own settings later:

```php
$deleteParams = [
    'index' => 'my_index'
];
$response = $client->indices()->delete($deleteParams);
print_r($response->asArray());
```

The response:

```php
Array
(
    [acknowledged] => 1
)
```


### Creating an index [_creating_an_index_2]

Now that you are starting fresh (no data or index), add a new index with custom settings:

```php
$params = [
    'index' => 'my_index',
    'body' => [
        'settings' => [
            'number_of_shards' => 2,
            'number_of_replicas' => 0
        ]
    ]
];

$response = $client->indices()->create($params);
print_r($response->asArray());
```

{{es}} now creates that index with your chosen settings and return an acknowledgement:

```php
Array
(
    [acknowledged] => 1
)
```

---

## File: docs/reference/deleting_documents.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/deleting_documents.html
---

# Deleting documents [deleting_documents]

Finally, you can delete documents by specifying their full `/index/_doc_/id` path:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

// Delete doc at /my_index/_doc_/my_id
$response = $client->delete($params);
```

​

---

## File: docs/reference/enabling_logger.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/enabling_logger.html
---

# Enabling the Logger [enabling_logger]

Elasticsearch-PHP supports logging, but it is not enabled by default for performance reasons. If you wish to enable logging, you need to select a logging implementation, install it, then enable the logger in the Client. The recommended logger is [Monolog](https://github.com/Seldaek/monolog), but any logger that implements the [PSR-3](https://www.php-fig.org/psr/psr-3/) interface works.

To begin using Monolog, just require it using composer:

```shell
composer require monolog/monolog
```

Once Monolog (or another logger) is installed, you need to create a log object and inject it into the client:

```php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('name');
$logger->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));

$client = ClientBuilder::create()
    ->setLogger($logger)        // Set your custom logger
    ->build();                  // Build the client object
```

---

## File: docs/reference/esql.md

---
navigation_title: "ES|QL"
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/esql.html
---

# ES|QL in the PHP client [esql]


This page helps you understand and use [ES|QL](docs-content://explore-analyze/query-filter/languages/esql.md) in the PHP client.

There are two ways to use ES|QL in the PHP client:

* Use the Elasticsearch [ES|QL API](https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-esql) directly: This is the most flexible approach, but it’s also the most complex because you must handle results in their raw form. You can choose the precise format of results, such as JSON, CSV, or text.
* Use ES|QL `mapTo($class)` helper. This mapper takes care of parsing the raw response and converting into an array of objects. If you don’t specify the class using the `$class` parameter, the mapper uses [stdClass](https://www.php.net/manual/en/class.stdclass.php).

ES|QL queries can be given directly as regular strings or heredoc strings, or for a more convenient option you can use the [ES|QL query builder](#esql-query-builder) helper, which can define ES|QL queries using PHP code.

## How to use the ES|QL API [esql-how-to]

The [ES|QL query API](https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-esql) allows you to specify how results should be returned. You can choose a [response format](docs-content://explore-analyze/query-filter/languages/esql-rest.md#esql-rest-format) such as CSV, text, or JSON, then fine-tune it with parameters like column separators and locale.

The default response from Elasticsearch is a table in JSON, where `columns` is an array of descriptions and `values` is an array of rows containing the values.

$$$query-script$$$
Here’s an example query and PHP script:

```php
$query = <<<EOD
    FROM books
    | WHERE author == "Stephen King"
    | SORT rating DESC
    | LIMIT 10
EOD;

$result = $client->esql()->query([
    'body' => ['query' => $query]
]);

foreach ($result['values'] as $value) {
    $i=0;
    foreach ($result['columns'] as $col) {
        printf("%s : %s\n", $col['name'], $value[$i++]);
    }
    print("---\n");
}
```

Here’s the JSON response from Elasticsearch:

```json
{
    "columns": [
        { "name": "author", "type": "text" },
        { "name": "description", "type": "text" },
        { "name": "publisher", "type": "keyword" },
        { "name": "rating", "type": "double" },
        { "name": "title", "type": "text" },
        { "name": "year", "type": "integer" }
    ],
    "values": [
        [
            "Stephen King",
            "The author ...",
            "Turtleback",
            5.0,
            "How writers write",
            2002
        ],
        [
            "Stephen King",
            "In Blockade Billy, a retired coach...",
            "Simon and Schuster",
            5.0,
            "Blockade",
            2010
        ],
        [
            "Stephen King",
            "A chilling collection of twenty horror stories.",
            "Signet Book",
            4.55859375,
            "Night Shift (Signet)",
            1979
        ],
        ...
    ]
}
```

Using this response, the PHP script (provided [above](#query-script)) produces the following output:

```php
author : Stephen King
description : The author ...
publisher : Turtleback
rating : 5.0
title : How writers write
year : 2002
---
author : Stephen King
description : In Blockade Billy, a retired coach...
publisher : Simon and Schuster
rating : 5.0
title : Blockade
year : 2010
---
author : Stephen King
description : A chilling collection of twenty horror stories.
publisher : Signet Book
rating : 4.55859375
title : Night Shift (Signet)
year : 1979
---
```

The following example gets ES|QL results as CSV and parses them:

```php
$result = $client->esql()->query([
    'format' => 'csv',
    'body' => ['query' => $query]
]);

var_dump($result->asArray());
```

The response looks something like this:

```json
array(12) {
  [0]=>
  array(6) {
    [0]=>
    string(6) "author"
    [1]=>
    string(11) "description"
    [2]=>
    string(9) "publisher"
    [3]=>
    string(6) "rating"
    [4]=>
    string(5) "title"
    [5]=>
    string(4) "year"
  }
  [1]=>
  array(6) {
    [0]=>
    string(12) "Stephen King"
    [1]=>
    string(249) "The author ..."
    [2]=>
    string(18) "Turtleback"
    [3]=>
    string(3) "5.0"
    [4]=>
    string(8) "How writers write"
    [5]=>
    string(4) "2002"
  }
```

In the response, the first row contains the column descriptions and the other rows contain the values, using a plain PHP array.


## Define your own mapping [esql-custom-mapping]

Although the `esql()->query()` API covers many use cases, your application might require a custom mapping.

You can map the ES|QL result into an array of objects, using the `mapTo()` function. Here’s an example:

```php
$result = $client->esql()->query([
    'body' => ['query' => $query]
]);

$books = $result->mapTo(); // Array of stdClass
foreach ($books as $book) {
    printf(
        "%s, %s, %d, Rating: %.2f\n",
        $book->author,
        $book->title,
        $book->year,
        $book->rating
    );
}
```

You can also specify a class name for the mapping. All the values will be assigned to the properties of the class.

Here’s an example mapper that returns an array of `Book` objects:

```php
class Book
{
    public string $author;
    public string $title;
    public string $description;
    public int $year;
    public float $rating;
}

$result = $client->esql()->query([
    'body' => ['query' => $query]
]);
$books = $result->mapTo(Book::class); // Array of Book
```

## Using the ES|QL query builder [esql-query-builder]

::::{warning}
This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
::::

The ES|QL query builder allows you to construct ES|QL queries using PHP syntax. Consider the following example:

```php
use Elastic\Elasticsearch\Helper\Esql\Query;

$query = Query::from("employees")
    ->sort("emp_no")
    ->keep("first_name", "last_name", "height")
    ->eval(height_feet: "height * 3.281", height_cm: "height * 100")
    ->limit(3);
```

Casting this query object to a string returns the raw ES|QL query, which you can send to the Elasticsearch ES|QL API:

```php
$result = $client->esql()->query([
    'body' => ['query' => (string)$query]
]);
```

### Creating an ES|QL query

To construct an ES|QL query object you typically use `Query::from()`, although there are more [source commands](https://www.elastic.co/docs/reference/query-languages/esql/commands/source-commands) available. Here are some examples:

```php
// FROM employees
$query = Query::from("employees");

// FROM <logs-{now/d}>
$query = Query::from("<logs-{now/d}>");

// FROM employees-00001, other-employees-*
$query = Query::from("employees-00001", "other-employees-*");

// FROM cluster_one:employees-00001, cluster_two:other-employees-*
$query = Query::from("cluster_one:employees-00001", "cluster_two:other-employees-*");

// FROM employees METADATA _id
$query = Query::from("employees")->metadata("_id");
```

Note how in the last example the optional `METADATA` clause of the `FROM` command is added as a chained method.

### Adding processing commands

Once you have a query object, you can add one or more processing commands to it by chaining them. The following example shows how to create a query that uses the `WHERE` and `LIMIT` processing commands to filter the results:

```php
$query = Query::from("employees")
    ->where("still_hired == true")
    ->limit(10);
```

The ES|QL documentation includes the complete list of available [processing commands](https://www.elastic.co/docs/reference/query-languages/esql/commands/processing-commands).

### Using Code completion

You can rely on autocompletion as an aid in constructing ES|QL queries with the query builder. Note that this requires an IDE that is configured with a PHP language server.

---

## File: docs/reference/getting_documents.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting_documents.html
---

# Getting documents [getting_documents]

{{es}} provides realtime GETs of documents. This means that as soon as the document is indexed and your client receives an acknowledgement, you can immediately retrieve the document from any shard. Get operations are performed by requesting a document by its full `index/type/id` path:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

// Get doc at /my_index/_doc/my_id
$response = $client->get($params);
```

​

---

## File: docs/reference/getting-started.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html
  - https://www.elastic.co/guide/en/serverless/current/elasticsearch-php-client-getting-started.html
---

# Getting started [getting-started-php]

This page guides you through the installation process of the PHP client, shows you how to instantiate the client, and how to perform basic Elasticsearch operations with it.


### Requirements [_requirements]

* [composer](http://getcomposer.org)

If you don’t have composer you can install it by running the following commands:

```shell
curl -s http://getcomposer.org/installer | php
php composer.phar install
```


### Installation [_installation]

To install the latest version of the client, run the following command:

```shell
composer require elasticsearch/elasticsearch
```

When you have installed elasticsearch-php you can start using it with the `Client` class. You can use the `ClientBuilder` class to create this object:

```php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();
```

Refer to the [*Installation*](/reference/installation.md) page to learn more.


### Connecting [_connecting]

You can connect to the Elastic Cloud using an API key and the Elasticsearch endpoint.

```php
$client = ClientBuilder::create()
   ->setHosts(['<elasticsearch-endpoint>'])
   ->setApiKey('<api-key>')
   ->build();
```

Your Elasticsearch endpoint can be found on the ***My deployment*** page of your deployment:



You can generate an API key on the ***Management*** page under Security.



For other connection options, refer to the [*Connecting*](/reference/connecting.md) section.


### Operations [_operations]

Time to use Elasticsearch! This section walks you through the basic, and most important, operations of Elasticsearch. For more operations and more advanced examples, refer to the [*Operations*](/reference/operations.md) page.


#### Creating an index [_creating_an_index]

This is how you create the `my_index` index:

```php
$client = ClientBuilder::create()->build();
$params = [
    'index' => 'my_index'
];

// Create the index
$response = $client->indices()->create($params);
```


#### Indexing documents [_indexing_documents]

This is a simple way of indexing a document:

```php
$params = [
    'index' => 'my_index',
    'body'  => [ 'testField' => 'abc']
];

// Document will be indexed to my_index/_doc/<autogenerated ID>
$response = $client->index($params);
```

You can bulk index documents with batches in a slightly more complex way:

```php
$params = ['body' => []];

for ($i = 1; $i <= 1234567; $i++) {
    $params['body'][] = [
        'index' => [
            '_index' => 'my_index',
            '_id'    => $i
        ]
    ];

    $params['body'][] = [
        'my_field'     => 'my_value',
        'second_field' => 'some more values'
    ];

    // Every 1000 documents stop and send the bulk request
    if ($i % 1000 == 0) {
        $responses = $client->bulk($params);

        // erase the old bulk request
        $params = ['body' => []];

        // unset the bulk response when you are done to save memory
        unset($responses);
    }
}

// Send the last batch if it exists
if (!empty($params['body'])) {
    $responses = $client->bulk($params);
}
```


#### Getting documents [_getting_documents]

You can get documents by using the following code:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

// Get doc at /my_index/_doc/my_id
$response = $client->get($params);
```


#### Searching documents [_searching_documents]

This is how you can create a single match query with the PHP client:

```php
$params = [
    'index' => 'my_index',
    'body'  => [
        'query' => [
            'match' => [
                'testField' => 'abc'
            ]
        ]
    ]
];

$results = $client->search($params);
```


#### Updating documents [_updating_documents]

This is how you can update a document, for example to add a new field:

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id',
    'body'  => [
        'doc' => [
            'new_field' => 'abc'
        ]
    ]
];

// Update doc at /my_index/_doc/my_id
$response = $client->update($params);
```


#### Deleting documents [_deleting_documents]

```php
$params = [
    'index' => 'my_index',
    'id'    => 'my_id'
];

// Delete doc at /my_index/_doc_/my_id
$response = $client->delete($params);
```


#### Deleting an index [_deleting_an_index]

```php
$params = ['index' => 'my_index'];
$response = $client->indices()->delete($params);
```


## Further reading [_further_reading]

* Use [*Client helpers*](/reference/client-helpers.md) for a more confortable experience with the APIs.

---

## File: docs/reference/host-config.md

---
mapped_pages:
  - https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/host-config.html
---

# Host Configuration [host-config]

The client offers an options to configure hosts.

The most common configuration is telling the client about your cluster: the number of nodes, their addresses, and ports. If no hosts are specified, the client attempts to connect to `localhost:9200`.

This behavior can be changed by using the `setHosts()` method on `ClientBuilder`. The method accepts an array of values, each entry corresponding to one node in your cluster. The format of the host can vary, depending on your needs (ip vs hostname, port, ssl, etc).

```php
$hosts = [
    '192.0.2.0:9200',         // IP + Port
    '192.0.2.0',              // Just IP
    'mydomain.server.com:9201', // Domain + Port
    'mydomain2.server.com',     // Just Domain
    'https://localhost',        // SSL to localhost
    'https://192.0.2.0:9200'  // SSL to IP + Port
];
$client = ClientBuilder::create()           // Instantiate a new ClientBuilder
                    ->setHosts($hosts)      // Set the hosts
                    ->build();              // Build the client object
```

Notice that the `ClientBuilder` object allows chaining method calls for brevity. It is also possible to call the methods individually:

```php
$hosts = [
    '192.0.2.0:9200',         // IP + Port
    '192.0.2.0',              // Just IP
    'mydomain.server.com:9201', // Domain + Port
    'mydomain2.server.com',     // Just Domain
    'https://localhost',        // SSL to localhost
    'https://192.0.2.0:9200'  // SSL to IP + Port
];
$clientBuilder = ClientBuilder::create();   // Instantiate a new ClientBuilder
$clientBuilder->setHosts($hosts);           // Set the hosts
$client = $clientBuilder->build();          // Build the client object
```