Skip to content

Elastica: support ruflin/elastica ^8.0 || ^9.0 - #20

Open
f3l1x wants to merge 4 commits into
masterfrom
feature/elastica-8
Open

f3l1x wants to merge 4 commits into
masterfrom
feature/elastica-8

Conversation

@f3l1x

@f3l1x f3l1x commented Oct 1, 2026

Copy link
Copy Markdown
Member

Why

ruflin/elastica 7 pins elasticsearch/elasticsearch ^7, so contributte/elastica can't be installed next to contributte/elasticsearch v0.6.0, which needs elasticsearch/elasticsearch ^8.11. With this PR they resolve together (checked with a path-repo dry run: elastica 8.2.0, elasticsearch-php 8.19.0, contributte/elasticsearch 0.6.0).

Constraint: ruflin/elastica: ^8.0 || ^9.0

  • Elastica 8 swapped its own Connection/Transport layer for the official client (elastic/transport + elasticsearch/elasticsearch 8). The Client constructor config, request(), Elastica\Request, getTransferInfo() and ResponseException are all gone or replaced. Supporting 7 and 8 together would need two clients, two config schemas and two panels, so I dropped 7 rather than offer dual support.
  • From 8.x to 9.x the Client/ClientConfiguration API is the same. The only 9.0 break that touches this package is the removal of Elastica\Request, and the code no longer uses it. One codebase covers both majors.
  • PHP stays >=8.1, since both majors support it. This doesn't conflict with Composer: require PHP >=8.2 #18.

Changes

  • Client: the hooks now wrap sendRequest(RequestInterface): Elasticsearch, which every endpoint goes through, instead of the removed request(). The callbacks receive the PSR-7 request the transport actually sent (with the node host resolved).
  • ElasticaExtension: new config schema that mirrors Elastica 8's ClientConfiguration/_buildTransport. New top-level logger option (a PSR-3 service passed to the Elastica client). Null or empty values are not passed through, so Elastica's defaults still apply.
  • Tracy panel: works on PSR-7 request/response. Requests are grouped by scheme://host:port, with no user info, so credentials don't leak. The explain re-run now also covers POST _search, since ES client 8 sends searches with a body as POST. BlueScreen shows ClientResponseException/ServerResponseException responses (the old Elastica\Exception\ResponseException no longer exists).
  • composer: guzzlehttp/guzzle added to require-dev. elastic/transport needs a PSR-18 client, and the package suggests one. Branch alias bumped to 3.0.0-dev because this is a BC break.
  • QA: contributte/qa 0.4 removed ruleset-8.0.xml, so make cs was already failing on master (and on Composer: require PHP >=8.2 #18). The ruleset now uses the base ruleset.xml with php_version=80100. Stale phpstan ignoreErrors removed; phpstan level 9 passes with no ignores.
  • Tests: new tests for the default, documented and full config, rejection of legacy keys, and the Tracy panel/hooks/BlueScreen. They use a fake PSR-18 client, so no Elasticsearch server is needed.
  • Docs: setup (PSR-18 client), full config, a migration table from Elastica 7, and the event signatures.

BC impact for users

Config migration (old keys are rejected by the schema, e.g. Unexpected item 'elastica › config › host', did you mean 'hosts'?):

Before After
host: es.local + port: 9200 hosts: [http://es.local:9200]
url: http://es.local:9200/ hosts: [http://es.local:9200]
connections: [...] hosts: [...]
roundRobin: true transport_config: node_pool: @nodePool
username / password unchanged (also api_key, cloud_id)
auth_type, transport, proxy, curl, compression, persistent, timeout, headers, path, bigintConversion removed; set these on the PSR-18 HTTP client (transport_config: http_client / http_client_options)

Other breaks:

  • A PSR-18 HTTP client must be installed (e.g. guzzlehttp/guzzle or symfony/http-client).
  • onSuccess/onFailure signatures changed to (Client, Psr\Http\Message\RequestInterface, Elastic\Elasticsearch\Response\Elasticsearch|Throwable, float).
  • Panel::$queries entries are now ['request' => ..., 'response' => ..., 'time' => ..., 'exception' => ...] with PSR-7 objects.
  • Elastica 8/9 API changes apply to user code (4xx/5xx now throw Elastic\Elasticsearch\Exception\ClientResponseException/ServerResponseException, Elastica\Request is gone in 9, and so on). See the UPGRADE-8.0 and UPGRADE-9.0 guides.

Test results (local, PHP 8.5)

Stack cs phpstan tests
elastica 9.0.0, elasticsearch-php 9.5.0, transport 9.0.1 OK OK OK (2 files, 8 test methods)
elastica 8.2.0, elasticsearch-php 8.19.0, transport 8.11.0 – OK OK
elastica 8.0.0, elasticsearch-php 8.4.1, transport 8.8.0 (lowest, --ignore-platform-req=php) – OK OK

Not run locally: the CI matrix on PHP 8.1/8.2/8.3, including --prefer-lowest on 8.1. CI on this PR covers that.

Open questions

  • Is a new major (3.0) fine? The branch alias is bumped to 3.0.0-dev, and 2.x would stay on Elastica 7.
  • Docs: move documentation to README #19 moves .docs into README, so whichever lands second needs a small rebase of the docs.

@f3l1x

f3l1x commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

Raised the minimum PHP to >=8.2 (composer, phpstan/phpcs php_version, CI matrix, README). The PHP 8.1 jobs could not install because contributte/qa ^0.4 and contributte/tester ^0.4 require PHP >=8.2. This also covers #18.

@codecov

codecov Bot commented Oct 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.98305% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.27%. Comparing base (47de678) to head (4032149).

Files with missing lines Patch % Lines
src/Diagnostics/Panel.php 85.00% 9 Missing ⚠️
src/Client.php 77.77% 2 Missing ⚠️
src/Diagnostics/panel.phtml 86.66% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master      #20       +/-   ##
===========================================
+ Coverage   34.18%   87.27%   +53.08%     
===========================================
  Files           3        4        +1     
  Lines         117      220      +103     
===========================================
+ Hits           40      192      +152     
+ Misses         77       28       -49     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread composer.json
],
"require": {
"php": ">=8.1",
"ruflin/elastica": "^7.3.1",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support only 9.0

Comment thread .docs/README.md
```
register extension

Elastica 8+ is built on top of [elastic/transport](https://github.com/elastic/elastic-transport-php), which needs a [PSR-18](https://www.php-fig.org/psr/psr-18/) HTTP client.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite text

Comment thread .docs/README.md
Define at least one host, this would be minimal possible config.

```neon
elastica:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's support multiple connections based on github.com/contributte/doctrine-dbal and github.com/contributte/doctrine-orm

Comment thread .docs/README.md
headers: []
retries: null # defaults to number of hosts
retryOnConflict: 0
transport_config:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snake_case -> camelCase

Comment thread .docs/README.md
In docker environment you should use `host: elasticsearch` and `port: 9200` for example.
In docker environment you should use `hosts: [http://elasticsearch:9200]` for example.

### Upgrade from Elastica 7

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

];
$service = static fn () => Expect::anyOf(Expect::string(), Expect::type(Statement::class))->nullable();

// https://github.com/ruflin/Elastica/blob/8.x/src/ClientConfiguration.php

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

$builder = $this->getContainerBuilder();
$config = $this->config;

/** @var array<string, mixed> $clientConfig */

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too complex and too wordy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant