Open-source project
elastic/elasticsearch-php avatar
elastic/elasticsearch-php

elasticsearch-php: 500 endpoints, one PSR-shaped client

Official PHP client for Elasticsearch.

5,336 stars963 forksPHPMIT

At a glance

What is it?
elasticsearch-php is the official PHP client for Elasticsearch, exposing more than 500 endpoints over PSR-7 messages and PSR-18 HTTP clients, with a built-in cURL transport replacing Guzzle since 9.0. It is versioned in lockstep with the Elasticsearch server and released quarterly, with v9.5.0 on 2026-08-04.
Who is it for?
Use elasticsearch-php when a PHP application needs Elasticsearch's search and analytics, and you want endpoint coverage that tracks the server release for release. Talk to the REST API directly with any HTTP client if your surface is two endpoints and a dependency is not worth it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An official client measured in endpoints

The one-sentence description is accurate and undersells the surface: this is the official PHP client for Elasticsearch, and it offers 500+ endpoints for interacting with a cluster, the full REST API surface of the server rendered as PHP methods. The README deliberately demonstrates only the basics, index, search and delete, through anchors into the getting-started documentation, covering creating an index, indexing, getting, searching, updating and deleting documents, and deleting the index. For running the server itself, the documented local path is a single shell line that starts both Elasticsearch and Kibana:

bash
curl -fsSL https://elastic.co/start-local | sh

The alternative is a free Elastic Cloud trial, and both paths end at the same client. The audience is any PHP application, framework or plain script, that needs search, logging aggregation or analytics from an Elasticsearch deployment without hand-building HTTP requests per endpoint. The endpoint count is the appeal in practice: whatever capability the server grows, the corresponding method already exists here, named after the API and documented in PHPDoc, rather than arriving as a URL to construct and debug by hand.

Versioned in lockstep with the server

The versioning rule is stricter than most libraries and worth internalizing before choosing a version. The client is versioned and released alongside the Elasticsearch server, and the guidance is explicit: use the most recent library version within the major version of your server. For Elasticsearch 8.16, that means 8.16 or above of the library, but not 9.0. A compatibility table maps main to main, 9.x to 9.x and 8.x to 8.x. Forward compatibility has a precise meaning here: clients communicate with greater or equal minor server versions without breaking, but an 8.12 client does not automatically gain the new features of an 8.13 server, the 8.13 client is required for that. Backwards compatibility with older servers is limited to default distributions and carries no guarantees. Release cadence is roughly quarterly, v9.3.0 on 2026-02-04, v9.4.0 on 2026-05-06 and v9.5.0 on 2026-08-04, with the last repository push on 2026-09-28, and the client supports currently maintained PHP versions. The lockstep model has a planning consequence worth stating: a server upgrade and a client upgrade are one project, and pinning the client while upgrading the server is precisely the combination the compatibility notes exist to prevent, while the quarterly rhythm gives teams a predictable point at which new server features become reachable from PHP.

PSR-7 and PSR-18: the client is ordinary HTTP underneath

Version 9.0.0 kept the 8.x architecture, which rests on two PHP standards: PSR-7 for HTTP messages and PSR-18 for HTTP client communications. The practical consequence of that choice became visible in the same release, when the Guzzle dependency was removed entirely. By default the client now uses a built-in cURL-based PSR-18 implementation when no other PSR-18 compatible client is detected, through the companion elastic-transport-php library at its own 9.0.0, and any PSR-18 client an application already runs can be plugged in instead. For dependency-sensitive PHP projects this is the difference between adopting the official client and writing a thin REST wrapper: the client adds no HTTP framework of its own, respects the interfaces the ecosystem already standardized, and gets out of the way. The transport lives in a sibling repository, elastic-transport-php, released on its own line, so the HTTP layer evolves independently of the endpoint surface, and BREAKING_CHANGES.md records what moved across both when a major version lands. The product-response check is visible in the mocking example, where a valid response carries the Elasticsearch header check and product name.

Serverless merged in, detected and guarded

The serverless story is a case study in consolidation done carefully. The separate elastic/elasticsearch-serverless client is deprecated, and its functionality was merged back into this one, with zero impact claimed on default behavior. Endpoints available in serverless carry a @group serverless attribute in their PHPDoc, and calling an endpoint that exists but is not available in serverless mode returns a 410 HTTP error with a message saying exactly that, so the failure is legible rather than mysterious. Detection is layered: the client recognizes serverless automatically when the URL is Elastic-managed, such as *.elastic.cloud, and when a proxy hides that, from the first response. Explicit control exists too, Client::setServerless(true), false by default, for topologies where neither signal suffices. One client binary, one API surface, two deployment models, with the boundary enforced at the endpoint level. The @group serverless marker doubles as documentation tooling: searching the source for the attribute yields the exact serverless-capable surface, which is faster than cross-referencing the server's own capability tables when planning a serverless deployment.

To mock the client, mock PSR-18

Testing is where the PSR architecture pays its second dividend: the documented way to mock the Elasticsearch client is simply to mock a PSR-18 HTTP client, with no Elasticsearch-specific test doubles required. The README's example uses php-http/mock-client with a PSR-7 response from Nyholm:

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();

Responses are queued onto the mock, and endpoint calls return them:

php
$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!

A test suite built this way needs no live cluster, no containers and no network, which is the property that makes endpoint-heavy clients testable at all. Because result objects wrap PSR-7 responses, assertions can inspect status codes, headers and bodies through the standard interfaces rather than client-specific accessors, keeping the test layer portable if the HTTP client ever changes.

A test matrix readable from the file names

The repository's quality infrastructure is legible before you open a single config file. Beside the unit tests driven by phpunit.xml.dist sit phpunit-integration-tests.xml, phpunit-integration-cloud-tests.xml, phpunit-yaml-serverless-tests.xml and phpunit-yaml-stack-tests.xml, a four-way split between local integration, cloud, serverless and full-stack YAML-driven suites, matching exactly the deployment models the client supports. Static analysis runs under phpstan with a committed configuration, and CI lives in Buildkite alongside GitHub workflows. The YAML-driven suites imply that test scenarios are declared as data and executed against the client, an arrangement that lets the same definitions be shared across Elastic's official language clients rather than rewritten per language. The examples directory is thin but pointed, holding a dense_vector_benchmark.php, a benchmark for vector search, the workload class that motivates much of current Elasticsearch interest. Catalog metadata appears as catalog-info.yaml for Backstage-style service discovery, and AGENTS.md continues the pattern of repositories that onboard coding agents deliberately.

A README that routes rather than teaches

The README's own structure is a deliberate choice worth naming: installation and connecting do not appear as inline copy-paste blocks but as links into the getting-started documentation on elastic.co, and the usage section is a table of contents into the server's REST API reference. The rationale is maintenance: a client that tracks 500 server endpoints cannot keep a README tutorial honest, so the README routes to the source of truth and reserves its own space for what is specific to this library, versioning rules, compatibility semantics, the 9.0 breaking changes and the mocking pattern. BREAKING_CHANGES.md and CHANGELOG.md carry the release history, the former being the document to read before any major bump, and the NOTICE file records attribution alongside the MIT license. For an integrator, the lesson is where to look: architecture and boundaries here, operations in the official docs, and the exact endpoint surface in the server reference.

Editorial conclusion

Use elasticsearch-php when a PHP application needs Elasticsearch's search and analytics, and you want endpoint coverage that tracks the server release for release. Talk to the REST API directly with any HTTP client if your surface is two endpoints and a dependency is not worth it. Verify first that your client major version matches your server, 9.x for 9.x and 8.x for 8.x per the compatibility table, that your PHP version is currently maintained, and read BREAKING_CHANGES.md before any major upgrade, since that file is where the contract actually lives.

Frequently asked questions

What is elasticsearch-php?

elasticsearch-php is the official PHP client for Elasticsearch, an MIT-licensed Composer package exposing more than 500 endpoints for interacting with a cluster, from indexing and searching documents to managing indices.

How do you run Elasticsearch locally for PHP development?

Run curl -fsSL https://elastic.co/start-local | sh to start Elasticsearch and Kibana on your local machine, or sign up for a free Elastic Cloud trial. The PHP client then connects as described in the getting-started documentation.

How do you mock the elasticsearch-php client in tests?

Mock a PSR-18 HTTP client and inject it with ClientBuilder::setHttpClient(), for example php-http/mock-client. Queue responses with addResponse(), and endpoint calls such as $client->info() return them, so no live cluster is needed.

Official sources

  1. elastic/elasticsearch-php on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/elastic-elasticsearch-php.svg)](https://hysenlabs.com/projects/elastic-elasticsearch-php)