Bump to PHP 8.1, improve type safety for Tasks
Pull Request
Related issue
Fixes #703 Closes #739
What does this PR do?
- Bumps PHP requirement to 8.1;
- Adds missing types where there were none at all, or was impossible to use because of unions;
- Adds Task object for type safety to be returned instead of undocumented array shapes;
- Fully enables
trailing_comma_in_multilinecs fixer rule; - Disables
php_unit_strictcs fixer rule, because it breaks tests;
~~This introduces a BC break for someone who is extending meilisearch classes, but not for those who consumes the data, as Task object was added implementing \ArrayAccess, so all raw data can still be accessed.~~
This introduces a BC break for task data access and for someone who is extending meilisearch classes.
Migration guide
Before
$promise = $this->client->createIndex('new-index', ['primaryKey' => 'objectID']);
$this->index->waitForTask($promise['taskUid']);
After
$task = $this->client->createIndex('new-index', ['primaryKey' => 'objectID']);
$this->index->waitForTask($task->getTaskUid());
Before
$task = $this->client->getTask($taskUid);
if ($task['status'] === 'succeeded') {
// snip...
}
After
use MeiliSearch\Contracts\TaskStatus;
$task = $this->client->getTask($taskUid);
if ($task->getStatus() instanceof TaskStatus::Succeeded) {
// snip...
}
Before
$task = $this->client->getTask($taskUid);
if ($task['type'] === 'indexCreation') {
// snip...
}
After
use MeiliSearch\Contracts\TaskType;
$task = $this->client->getTask($taskUid);
if ($task->getType() instanceof TaskType::IndexCreation) {
// snip...
}
PR checklist
Please check if your PR fulfills the following requirements:
- [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [x] Have you read the contributing guidelines?
- [x] Have you made sure that the title is accurate and descriptive of the changes?
Summary by CodeRabbit
-
New Features
- Introduced a comprehensive
Taskobject with detailed status and type enums and multiple task detail classes for clearer task management. - Added a new
partialfunction for partial application of callables. - Added extensive tests for the
Taskobject and pagination settings.
- Introduced a comprehensive
-
Breaking Changes
- Raised minimum PHP version requirement to 8.1.
- Updated many endpoints to return
Taskobjects instead of arrays for asynchronous operations (documents, indexes, settings, dumps, snapshots, tasks). - Enforced stricter and more explicit type declarations across the codebase.
-
Improvements
- Enhanced type safety with explicit parameter and return types.
- Streamlined exception classes with clearer type annotations.
- Simplified and unified method signatures and return types for better consistency.
- Updated test code to work with
Taskobjects instead of raw arrays, improving clarity and type safety. - Simplified asynchronous task handling in tests by directly awaiting
Taskobjects. - Improved internal code consistency by removing deprecated or unused methods and variables.
-
Bug Fixes
- Improved reliability and consistency of method signatures and expected outputs.
-
Tests
- Expanded and refined test coverage reflecting new
Taskobject usage. - Removed redundant assertions and outdated test methods.
- Updated tests to use method calls on
Taskobjects rather than array access. - Corrected test method names for typos and improved test clarity.
- Expanded and refined test coverage reflecting new
-
Chores
- Updated CI workflows to run tests only on PHP 8.1 and above.
- Updated coding style configurations and dependency version constraints.
- Reformatted PHPUnit configuration for detailed error and deprecation reporting.
Codecov Report
Attention: Patch coverage is 97.15100% with 10 lines in your changes missing coverage. Please review.
Project coverage is 90.40%. Comparing base (
368c73f) to head (cfed046). Report is 73 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #735 +/- ##
==========================================
- Coverage 90.74% 90.40% -0.34%
==========================================
Files 52 73 +21
Lines 1340 1595 +255
==========================================
+ Hits 1216 1442 +226
- Misses 124 153 +29
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
YAY!
If these are to be deprecated, are they going to be replaced with direct access to the object?
public function getData(): array
{
return $this->data;
}
// @todo: deprecate
public function offsetExists(mixed $offset): bool
{
return \array_key_exists($offset, $this->data);
}
// @todo: deprecate
public function offsetGet(mixed $offset): mixed
{
return $this->data[$offset] ?? null;
}
// @todo: deprecate
public function offsetSet(mixed $offset, mixed $value): void
{
throw new \LogicException(\sprintf('Setting data on "%s::%s" is not supported.', get_debug_type($this), $offset));
}
// @todo: deprecate
public function offsetUnset(mixed $offset): void
{
throw new \LogicException(\sprintf('Unsetting data on "%s::%s" is not supported.', get_debug_type($this), $offset));
}
@tacman if this PR will get merged, then you'll get access to both ways: $task->getError() or $task['error']
but imho previous way should be deprecated, because it does not provide types
That makes sense. I imagine there will be other things in 2.0 as well.
Hi, thanks for your PR.
Do we want to release this in a v2.x?
Can you add a "migration guide" to your first comment to highlight the required implementation changes?
@Strift
Do we want to release this in a v2.x?
Based on semver, it should be in v2.x, but if you want to be in line with meilisearch/meilisearch repository, I think it's reasonable to release this in v1.
Can you add a "migration guide" to your first comment to highlight the required implementation changes?
Can you link to some previous comment where I could see how this looks like?
Hi @norkunas, no need to follow a specific format. A simple before/after of the relevant parts of the code is enough. Here's an example for meilisearch JS: https://github.com/meilisearch/meilisearch-js/releases/tag/v0.48.0
It's mainly so I have examples to refer to when writing the release changelog. Double-checking with the actual code changes is better, but the code samples are a good resource too for me, especially if I write the changelog a long time after reviewing the PR.
@Strift I've updated description, is it ok for you? Also it should be decided if we deprecate the array access or not.
I also have a side idea for another improvement:
Add wait(int $timeoutInMs, int $intervalInMs) method to task.
So instead of:
$task = $this->client->createIndex('new-index', ['primaryKey' => 'objectID']);
$task = $this->index->waitForTask($task->getTaskUid());
we could write:
$task = $this->client->createIndex('new-index', ['primaryKey' => 'objectID'])->wait();
But not sure, as then we'd need for this method to work at least inject in in the Task object the Meilisearch\Endpoints\Tasks endpoint, or the http client, or the meilisearch client itself..
Hello here! Thank you for your PR @norkunas! With @brunoocasali and the PHP community, we originally chose to make the PHP SDK follow the same version number as Meilisearch's one Here, if we merge this branch, we will break this useful convention forever. Is it what we want?
Hi, I'm for merging to v1 :) I think this is an acceptable BC break to provide type safety
I also think that it would be good to have typed task details based on https://www.meilisearch.com/docs/reference/api/tasks#details, because now it's always array<mixed>, so static analyzers will always complain.
Regarding the other topics of discussion in this thread:
I also have a side idea for another improvement: Add wait(int $timeoutInMs, int $intervalInMs) method to task.
This could be a welcome addition, but I prefer having it in a separate PR to keep this one's scope minimal.
Thanks @Strift for review, I'm currently preparing for details data to be typed.
[!NOTE]
Other AI code review bot(s) detected
CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.
Walkthrough
Convert many async task return values from arrays to a strongly-typed, immutable Task object (with enums and a wait() helper), add TaskDetail types, broaden PHP 8.1+ typing across the codebase, remove legacy PHP matrix CI jobs, and update tests to use the new Task-based API.
Changes
| Cohort / File(s) | Change Summary |
|---|---|
Workflows.github/workflows/meilisearch-beta-tests.yml, .../pre-release-tests.yml, .../tests.yml |
Remove PHP 7.4/8.0 from CI matrices, delete legacy PHP7 Guzzle job, and adjust Symfony-HttpClient exclusions. |
Composer / toolingcomposer.json, .php-cs-fixer.dist.php, phpunit.xml.dist |
Raise PHP requirement to ^8.1, update dependencies, add files autoload entry, toggle php-cs-fixer options, and update PHPUnit config/display settings. |
Core Task model & enumssrc/Contracts/Task.php, src/Contracts/TaskStatus.php, src/Contracts/TaskType.php, src/Contracts/TaskError.php |
Add immutable Task class with getters, wait() and fromArray(); add TaskStatus and TaskType enums; add TaskError. |
Task details typessrc/Contracts/TaskDetails.php, src/Contracts/TaskDetails/*.php |
Add TaskDetails interface and multiple concrete detail classes (DocumentAdditionOrUpdateDetails, DocumentDeletionDetails, DocumentEditionDetails, DumpCreationDetails, IndexCreationDetails, IndexDeletionDetails, IndexSwapDetails, IndexUpdateDetails, SettingsUpdateDetails, TaskCancelationDetails, TaskDeletionDetails). |
Endpoints β API return typessrc/Endpoints/*.php, src/Endpoints/Delegates/* |
Change many endpoint/mutator return types from array to Task (and list<Task> for batch ops); tighten parameter types (int |
Tasks endpoint logicsrc/Endpoints/Tasks.php, src/Endpoints/TasksResults.php |
Make get/cancel/delete return Task, make waitTask static and Task-returning, map tasks results to Task instances. |
Documents / Settings / Indexes changessrc/Endpoints/Delegates/HandlesDocuments.php, HandlesSettings.php, HandlesIndex.php, Indexes.php, Dumps.php, Snapshots.php, Batches.php, Keys.php, TenantToken.php |
Convert document/settings/index/dump/snapshot operations to return Task objects; adjust signatures, PHPDoc and internal handling accordingly. |
HTTP & serializationsrc/Http/Client.php, src/Http/Serialize/*.php, src/Contracts/Http.php |
Small refactors (trailing commas, query empty check), add stronger serialize/unserialize type hints, type post/put/patch $body as mixed. |
Contracts & misc typingsrc/Contracts/Data.php, src/Contracts/SimilarDocumentsQuery.php |
Add property and method return typing (e.g., array, mixed), tighten constructor/props. |
Exceptions & new LogicExceptionsrc/Exceptions/*.php, src/Exceptions/LogicException.php |
Add return/type declarations, remove obsolete factory, and add new LogicException implementing ExceptionInterface. |
Helperssrc/functions.php |
Add internal partial() helper for partial application. |
Search JSON outputsrc/Search/SearchResult.php, src/Search/FacetSearchResult.php |
Use JSON_THROW_ON_ERROR when encoding to raise JsonException on failure. |
Tests β Task usagetests/Contracts/TaskTest.php, tests/MockTask.php, tests/**/ |
Add Task tests and MockTask; update many tests to expect Task objects and use ->wait() chaining; remove legacy promise helpers and assertIsValidPromise. |
Test harnesstests/TestCase.php |
Remove promise validator, adjust setup/teardown to work with Task objects and inline waits. |
Sequence Diagram(s)
%%{init: {"themeVariables":{"actorBackground":"#E6F7FF","actorBorder":"#7FCFE6","noteBackground":"#FFF4E6"}}}%%
sequenceDiagram
participant Client
participant Endpoint
participant HTTP
participant Task
Client->>Endpoint: call mutating API (e.g., addDocuments)
Endpoint->>HTTP: send HTTP request
HTTP-->>Endpoint: response array (task data)
Note right of Endpoint: wrap response into Task
Endpoint->>Task: Task::fromArray(response, partial(Tasks::waitTask, $http))
Endpoint-->>Client: return Task object
Client->>Task: ->wait(timeout?, interval?)
Task->>HTTP: poll task status via Tasks::waitTask
HTTP-->>Task: updated task data
Task-->>Client: resolved Task (finished or timed out)
Estimated code review effort
π― 4 (Complex) | β±οΈ ~45 minutes
Areas to focus during review:
- Task::fromArray mapping and all TaskDetails factory conversions for edge-case/missing keys.
- wait()/waitTask polling logic and timeout/error behavior (static vs. instance usage).
- Backwards-compatibility surface: any public methods that changed return types (may be semver-impacting).
- Tests that were adjusted β ensure mocks and MockTask create method match Task constructor and await semantics.
- CI/workflow removals to ensure other dependent jobs or matrix entries are not expected elsewhere.
Possibly related PRs
- meilisearch/meilisearch-php#758 β adjusts CI matrix and removes legacy PHP7 Guzzle job (closely related to workflow changes).
- meilisearch/meilisearch-php#753 β adds
disableOnNumberstypo-tolerance field and related tests (overlaps testing/type changes in typo-tolerance). - meilisearch/meilisearch-php#759 β modifies
src/Contracts/Http.phpmethod parameter typing (related to mixed body parameter changes).
Suggested labels
CI
Suggested reviewers
- brunoocasali
- norkunas
- curquiza
Poem
"I hopped through code with tiny paws,
Tasks now wear enums, neat as laws.
No arrays lost in rabbit holes,
Waits return as tidy goals.
A carrot for types β swift and bright! πβ¨"
Pre-merge checks and finishing touches
β Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | β οΈ Warning | Docstring coverage is 44.69% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
β Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title check | β Passed | The title 'Bump to PHP 8.1, improve type safety for Tasks' accurately summarizes the main changes: PHP version bump and type safety improvements for Task handling. |
| Linked Issues check | β Passed | The PR comprehensively addresses both linked issues: #703 implements Task object with typed accessors replacing array returns, and #739 adds wait() method for chaining task completion waits. |
| Out of Scope Changes check | β Passed | All changes align with the stated objectives: PHP 8.1 requirement, Task typing, trailing commas, php-cs-fixer updates, test refactoring, and Task-based API returns are all in-scope enhancements. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
@norkunas After further discussing the subject with @curquiza, we decided it would be more prudent to release it as v2 since it introduces a few breaking changes, especially the deprecation of PHP 7.
If that becomes a burden for our users later, we can introduce a table to showcase which SDK version supports which Meilisearch version. In any case, I think that's better, the engine and their SDKs are independent pieces of software that should be able to evolve independently and should remain adherent to semver rules :)
So, since we are doing a v2, feel free to suggest other potential breaking changes so we can release it in the same package!
Thanks a lot for the PR by the way, loved it!
CC: @Strift
@norkunas After further discussing the subject with @curquiza, we decided it would be more prudent to release it as v2 since it introduces a few breaking changes, especially the deprecation of PHP 7.
If that becomes a burden for our users later, we can introduce a table to showcase which SDK version supports which Meilisearch version. In any case, I think that's better, the engine and their SDKs are independent pieces of software that should be able to evolve independently and should remain adherent to semver rules :)
So, since we are doing a v2, feel free to suggest other potential breaking changes so we can release it in the same package!
Thanks a lot for the PR by the way, loved it!
CC: @Strift
Sounds good π
Then I think we can remove array access of task data here?
Then I think we can remove array access of task data here?
If you think we have more benefits by removing it than by keeping, I agree in removing it.
@Strift i should switch to v2 branch target here?
@Strift can you upmerge to v2, because it requires changes here that are already done on v1.15
Hi @norkunas, yes! Thanks for updating the target branch to v2.
So, I think we need to make the tests pass and merge this branch :)
Can you do this @norkunas then ask for my review again, please?
@brunoocasali that's not up to me. v2 needs to be upmerged, because main has some pushed changes
Apologies, I may have made a mistake.
I merged the changes from v2 into this branch, but maybe I should have rebased the PR instead.
I never do merges
Can we revert these 4 commits so we can start again?
I don't want to force push over your branch
@Strift i've removed those commits. i can now rebase, but the PR target is still v2, i should change it to main, which is now v2, right?
Let's us know when we can start testing V2. I'm eager to use the new return types.
@norkunas yes, you can target main directly