From 3fc53b2c434f793624630d5a8af2c57b3dde66cf Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 27 Aug 2025 23:59:40 +1200 Subject: [PATCH 1/6] Fix request filter for nested relationships --- composer.lock | 12 +-- src/Appwrite/Utopia/Request/Filters/V20.php | 86 +++++++++++++-------- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/composer.lock b/composer.lock index 077f5204d1..3bf17bc228 100644 --- a/composer.lock +++ b/composer.lock @@ -3557,16 +3557,16 @@ }, { "name": "utopia-php/database", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "99beaf1dd6dc3561c8332f9893325777553644a4" + "reference": "8a536fead840d9da6ee819fe6b80e0f047997f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/99beaf1dd6dc3561c8332f9893325777553644a4", - "reference": "99beaf1dd6dc3561c8332f9893325777553644a4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/8a536fead840d9da6ee819fe6b80e0f047997f69", + "reference": "8a536fead840d9da6ee819fe6b80e0f047997f69", "shasum": "" }, "require": { @@ -3607,9 +3607,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/1.2.1" + "source": "https://github.com/utopia-php/database/tree/1.2.3" }, - "time": "2025-08-26T16:05:26+00:00" + "time": "2025-08-27T11:47:04+00:00" }, { "name": "utopia-php/detector", diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 2683d600ef..d6e95ec327 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -32,59 +32,67 @@ class V20 extends Filter */ protected function manageSelectQueries(array $content): array { - $hasWildcard = false; if (!isset($content['queries'])) { - $hasWildcard = true; - // only query, make it json encoded! - $content['queries'] = [Query::select(['*'])->toString()]; + $content['queries'] = []; + } + + // Handle case where queries is an array but empty + if (\is_array($content['queries'])) { + $content['queries'] = \array_filter($content['queries'], function($q) { + if (\is_object($q) && empty((array)$q)) { + return false; + } + if (\is_string($q) && \trim($q) === '') { + return false; + } + if (empty($q)) { + return false; + } + return true; + }); } try { $parsed = Query::parseQueries($content['queries']); } catch (QueryException) { - // don't crash! return $content; } $selections = Query::groupByType($parsed)['selections'] ?? []; - - // If there are no select queries at all, add wildcard - if (empty($selections)) { - $hasWildcard = true; - $parsed[] = Query::select(['*']); - } elseif (!$hasWildcard) { - // check if any select includes a wildcard as we added one above + + // Check if we need to add wildcard + relationships + // This happens when: + // 1. No select queries exist, OR + // 2. A wildcard select exists + $needsRelationships = empty($selections); + if (!$needsRelationships) { foreach ($selections as $select) { if (\in_array('*', $select->getValues(), true)) { - $hasWildcard = true; + $needsRelationships = true; break; } } } /** - * Add `keys.*` for all model types! + * Add wildcard and relationship selects for backward compatibility */ - if ($hasWildcard) { + if ($needsRelationships) { $relatedKeys = $this->getRelatedCollectionKeys(); + $selects = \array_values(\array_unique(\array_merge(['*'], $relatedKeys))); - if (! empty($relatedKeys)) { - $selects = \array_values(\array_unique(\array_merge(['*'], $relatedKeys))); + // Remove any existing select queries + $parsed = \array_filter( + $parsed, + fn ($query) => $query->getMethod() !== Query::TYPE_SELECT + ); - // remove previous select queries - $parsed = \array_filter( - $parsed, - fn ($query) => $query->getMethod() !== Query::TYPE_SELECT - ); - - // add wildcard + relationship(s) selects - $parsed[] = Query::select($selects); - } + // Add wildcard + relationship(s) selects + $parsed[] = Query::select($selects); } $resolvedQueries = []; foreach ($parsed as $query) { - // make em json encoded! $resolvedQueries[] = $query->toString(); } @@ -95,12 +103,15 @@ class V20 extends Filter /** * Returns all relationship attribute keys in `key.*` format for use with `Query::select`. + * Recursively includes nested relationships up to 3 levels deep. + * Prevents infinite loops by tracking all visited collections in the current path. */ private function getRelatedCollectionKeys( ?string $databaseId = null, ?string $collectionId = null, ?string $prefix = null, int $depth = 1, + array $visited = [] ): array { $databaseId ??= $this->getParamValue('databaseId'); $collectionId ??= $this->getParamValue('collectionId'); @@ -112,6 +123,13 @@ class V20 extends Filter ) { return []; } + + // Check if we've already visited this collection in the current path to prevent cycles + if (in_array($collectionId, $visited)) { + return []; + } + + $visited[] = $collectionId; $dbForProject = $this->getDbForProject(); if ($dbForProject === null) { @@ -144,23 +162,27 @@ class V20 extends Filter $key = $attr['key']; $fullKey = $prefix ? $prefix . '.' . $key : $key; + $relatedCollectionId = $attr['relatedCollection'] ?? null; + + // Skip this relationship entirely if it points to an already visited collection + if ($relatedCollectionId && in_array($relatedCollectionId, $visited)) { + continue; + } // Add the wildcard select for this relationship $relationshipKeys[] = $fullKey . '.*'; - // Get the related collection for nested relationships - $relatedCollectionId = $attr['relatedCollection'] ?? null; - + // Continue recursively if we have a related collection if ($relatedCollectionId) { - // Recursively get nested relationship keys $nestedKeys = $this->getRelatedCollectionKeys( $databaseId, $relatedCollectionId, $fullKey, $depth + 1, + $visited ); - $relationshipKeys = \array_merge($relationshipKeys, $nestedKeys); + \array_push($relationshipKeys, ...$nestedKeys); } } From 146252243877464127c4c1ef3492c0bf2bbd14f2 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Aug 2025 00:04:25 +1200 Subject: [PATCH 2/6] Remove logging --- app/controllers/shared/api.php | 6 ------ .../Platform/Modules/Databases/Workers/Databases.php | 8 -------- 2 files changed, 14 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 40eddf574f..7742aac18f 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -810,12 +810,6 @@ App::shutdown() } if (!empty($queueForDatabase->getType())) { - Console::info("Triggering database event: \n" . \json_encode([ - 'projectId' => $project->getId(), - 'databaseId' => $queueForDatabase->getDatabase()?->getId(), - 'tableId' => $queueForDatabase->getTable()?->getId() ?? $queueForDatabase->getCollection()?->getId(), - 'rowId' => $queueForDatabase->getRow()?->getId() ?? $queueForDatabase->getDocument()?->getId(), - ])); $queueForDatabase->trigger(); } diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 22f1e6a2f2..9a98d77d2d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -64,14 +64,6 @@ class Databases extends Action $collection = new Document($payload['table'] ?? $payload['collection'] ?? []); $database = new Document($payload['database'] ?? []); - Console::info("Processing database operation: \n" . \json_encode([ - 'type' => $type, - 'projectId' => $project->getId(), - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), - 'documentId' => $document->getId(), - ], JSON_PRETTY_PRINT)); - $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); From 66f541092d84b90eda3dfc652843dcb6be1d4be4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Aug 2025 00:04:32 +1200 Subject: [PATCH 3/6] Update desc --- .../Databases/Http/Databases/Collections/Documents/Upsert.php | 2 +- .../Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index 8427ee6cd2..6027a20c41 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -45,7 +45,7 @@ class Upsert extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->desc('Create or update a document') + ->desc('Upsert a document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') ->label('scope', 'documents.write') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 36ca9709e1..c2695379e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -31,7 +31,7 @@ class Upsert extends DocumentUpsert $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows/:rowId') - ->desc('Create or update a row') + ->desc('Upsert a row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert') ->label('scope', ['rows.write', 'documents.write']) From 369c19039c3bec79ce0d6343e74be2ba0b0f7b6d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Aug 2025 00:04:40 +1200 Subject: [PATCH 4/6] Update specs --- app/config/specs/open-api3-1.8.x-client.json | 6 +++--- app/config/specs/open-api3-1.8.x-console.json | 6 +++--- app/config/specs/open-api3-1.8.x-server.json | 6 +++--- app/config/specs/open-api3-latest-client.json | 6 +++--- app/config/specs/open-api3-latest-console.json | 6 +++--- app/config/specs/open-api3-latest-server.json | 6 +++--- app/config/specs/swagger2-1.8.x-client.json | 6 +++--- app/config/specs/swagger2-1.8.x-console.json | 6 +++--- app/config/specs/swagger2-1.8.x-server.json | 6 +++--- app/config/specs/swagger2-latest-client.json | 6 +++--- app/config/specs/swagger2-latest-console.json | 6 +++--- app/config/specs/swagger2-latest-server.json | 6 +++--- 12 files changed, 36 insertions(+), 36 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index 1ccf7d82ab..21ab718af8 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -5146,7 +5146,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -5881,7 +5881,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -7799,7 +7799,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index cd2bb95ee6..8b894e8a55 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -9360,7 +9360,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -12791,7 +12791,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -36594,7 +36594,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index 7e5847f94c..0a40b8d604 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -8842,7 +8842,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -11576,7 +11576,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -26959,7 +26959,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 1ccf7d82ab..21ab718af8 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -5146,7 +5146,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -5881,7 +5881,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -7799,7 +7799,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index cd2bb95ee6..8b894e8a55 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -9360,7 +9360,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -12791,7 +12791,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -36594,7 +36594,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 7e5847f94c..0a40b8d604 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -8842,7 +8842,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "tags": [ "databases" @@ -11576,7 +11576,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "x-example": "GET", "enum": [ "GET", @@ -26959,7 +26959,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "tags": [ "tablesDB" diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index b08d8b0036..f634c5d9b8 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -5273,7 +5273,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -5978,7 +5978,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -7866,7 +7866,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index b4dfbb8ca6..9d5ba54989 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -9462,7 +9462,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -12836,7 +12836,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -36701,7 +36701,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index 2c358475f8..8bb0e09666 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -8934,7 +8934,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -11646,7 +11646,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -27126,7 +27126,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index b08d8b0036..f634c5d9b8 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -5273,7 +5273,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -5978,7 +5978,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -7866,7 +7866,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index b4dfbb8ca6..9d5ba54989 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -9462,7 +9462,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -12836,7 +12836,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -36701,7 +36701,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 2c358475f8..8bb0e09666 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -8934,7 +8934,7 @@ ] }, "put": { - "summary": "Create or update a document", + "summary": "Upsert a document", "operationId": "databasesUpsertDocument", "consumes": [ "application\/json" @@ -11646,7 +11646,7 @@ }, "method": { "type": "string", - "description": "HTTP method of execution. Default value is GET.", + "description": "HTTP method of execution. Default value is POST.", "default": "POST", "x-example": "GET", "enum": [ @@ -27126,7 +27126,7 @@ ] }, "put": { - "summary": "Create or update a row", + "summary": "Upsert a row", "operationId": "tablesDBUpsertRow", "consumes": [ "application\/json" From 75a1e5ca4ad6957223cc8e024e4badc0f70a7af4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Aug 2025 00:12:00 +1200 Subject: [PATCH 5/6] Format --- src/Appwrite/Utopia/Request/Filters/V20.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index d6e95ec327..3c605b0248 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -38,7 +38,7 @@ class V20 extends Filter // Handle case where queries is an array but empty if (\is_array($content['queries'])) { - $content['queries'] = \array_filter($content['queries'], function($q) { + $content['queries'] = \array_filter($content['queries'], function ($q) { if (\is_object($q) && empty((array)$q)) { return false; } @@ -59,7 +59,7 @@ class V20 extends Filter } $selections = Query::groupByType($parsed)['selections'] ?? []; - + // Check if we need to add wildcard + relationships // This happens when: // 1. No select queries exist, OR @@ -123,7 +123,7 @@ class V20 extends Filter ) { return []; } - + // Check if we've already visited this collection in the current path to prevent cycles if (in_array($collectionId, $visited)) { return []; @@ -163,7 +163,7 @@ class V20 extends Filter $key = $attr['key']; $fullKey = $prefix ? $prefix . '.' . $key : $key; $relatedCollectionId = $attr['relatedCollection'] ?? null; - + // Skip this relationship entirely if it points to an already visited collection if ($relatedCollectionId && in_array($relatedCollectionId, $visited)) { continue; From 61e0e74b56e9f9a0cf13e8090673c600cee7618e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Aug 2025 00:47:05 +1200 Subject: [PATCH 6/6] Update src/Appwrite/Utopia/Request/Filters/V20.php Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/Appwrite/Utopia/Request/Filters/V20.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 3c605b0248..c8622f8b7a 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -182,7 +182,7 @@ class V20 extends Filter $visited ); - \array_push($relationshipKeys, ...$nestedKeys); + $relationshipKeys = \array_merge($relationshipKeys, $nestedKeys); } }