feat: Replace Fractal with Laravel Data (Phase 1)#2448
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughIntroduces Laravel Data DTOs and Fractal-compatible serializers for users, API keys, and SSH keys, then updates client controllers to use the new data classes for item and collection responses. ChangesLaravel Data migration
Sequence Diagram(s)sequenceDiagram
participant Controller
participant DataDTO
participant DataCollection
participant APIResponse
Controller->>DataDTO: Build typed response data
DataDTO->>DataCollection: Select collection serializer when applicable
DataCollection->>APIResponse: Return object, data, and meta
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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 |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
app/Data/UserData.php (1)
33-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTimestamp serialization inconsistent across DTOs.
UserDatausessetTimezone('UTC')->toAtomString()whileApiKeyDataandUserSSHKeyDatause baretoAtomString(). If the app timezone differs from UTC, timestamps will serialize differently across resources. Consider normalizing the approach.♻️ Suggested normalization
- created_at: $user->created_at->setTimezone('UTC')->toAtomString(), - updated_at: $user->updated_at->setTimezone('UTC')->toAtomString(), + created_at: $user->created_at->toAtomString(), + updated_at: $user->updated_at->toAtomString(),Or alternatively, add
setTimezone('UTC')toApiKeyDataandUserSSHKeyDatafor consistency. The key is picking one approach and applying it everywhere.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/Data/UserData.php` around lines 33 - 38, Normalize timestamp serialization consistently across the DTOs: update the visible UserData fields created_at and updated_at, along with the corresponding timestamp fields in ApiKeyData and UserSSHKeyData, to use the same timezone handling before toAtomString(). Apply one approach everywhere, preserving the existing UTC-normalized behavior.app/Data/Data.php (1)
47-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider a typed contract instead of
method_existsduck-typing.Since one PR goal is enabling Scramble to statically read response types, a small interface (e.g.
HasResourceName) or abstract method would makegetResourceName()explicit and analyzable, rather than relying on runtimemethod_exists.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/Data/Data.php` around lines 47 - 49, Replace the method_exists-based fallback in the resource key resolution with an explicit typed contract, such as a HasResourceName interface or abstract getResourceName() requirement. Update the relevant resource classes to implement or satisfy that contract, while preserving the existing class_basename fallback only where the contract is intentionally absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/Data/CursorPaginatedDataCollection.php`:
- Around line 19-23: The additional metadata stored by additional() is dropped
when the collection is serialized outside fractal mode. Update the non-fractal
return path in the collection serialization logic (lines 25–69) to include
_additional alongside the returned data, while preserving the existing isFractal
behavior.
- Around line 53-61: Update the metadata cleanup in the cursor pagination flow
to also remove next_cursor and prev_cursor from $meta before merging additional
metadata and assigning the custom cursor. Preserve the existing removal of path,
per_page, next_page_url, and prev_page_url.
In `@app/Data/Data.php`:
- Around line 51-63: Update the additional-data handling around
getAdditionalData() so non-meta keys are preserved in the response instead of
being removed from attributes and dropped; retain meta’s existing response
behavior, and iterate only over additional keys (without the unused $value
variable) when excluding them from $array.
- Around line 43-54: Replace the unsupported getAdditionalData() call in
Data::toArray() with Spatie Laravel Data’s supported additional-data API,
preserving the existing iteration that removes additional-data keys from the
serialized array.
In `@app/Data/PaginatedDataCollection.php`:
- Around line 19-23: Update PaginatedDataCollection’s non-fractal response path
to merge _additional into the returned $array before the return, ensuring values
supplied through additional() are preserved. Keep the existing isFractal
metadata behavior unchanged and retain additional()’s current accumulation
semantics.
---
Nitpick comments:
In `@app/Data/Data.php`:
- Around line 47-49: Replace the method_exists-based fallback in the resource
key resolution with an explicit typed contract, such as a HasResourceName
interface or abstract getResourceName() requirement. Update the relevant
resource classes to implement or satisfy that contract, while preserving the
existing class_basename fallback only where the contract is intentionally
absent.
In `@app/Data/UserData.php`:
- Around line 33-38: Normalize timestamp serialization consistently across the
DTOs: update the visible UserData fields created_at and updated_at, along with
the corresponding timestamp fields in ApiKeyData and UserSSHKeyData, to use the
same timezone handling before toAtomString(). Apply one approach everywhere,
preserving the existing UTC-normalized behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f7548105-5961-4790-b1af-5aa82f831f1b
📒 Files selected for processing (10)
app/Data/ApiKeyData.phpapp/Data/CursorPaginatedDataCollection.phpapp/Data/Data.phpapp/Data/DataCollection.phpapp/Data/PaginatedDataCollection.phpapp/Data/UserData.phpapp/Data/UserSSHKeyData.phpapp/Http/Controllers/Api/Client/AccountController.phpapp/Http/Controllers/Api/Client/ApiKeyController.phpapp/Http/Controllers/Api/Client/SSHKeyController.php
| public function additional(array $additional): static | ||
| { | ||
| $this->_additional = array_merge($this->_additional, $additional); | ||
| return $this; | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Same additional() bypass as DataCollection.php/PaginatedDataCollection.php.
Metadata passed to ->additional([...]) is only surfaced when isFractal is true. Outside fractal mode (return $array;, Line 68), it is silently dropped. Same underlying issue and suggested fix as noted on app/Data/DataCollection.php.
Also applies to: 25-69
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/Data/CursorPaginatedDataCollection.php` around lines 19 - 23, The
additional metadata stored by additional() is dropped when the collection is
serialized outside fractal mode. Update the non-fractal return path in the
collection serialization logic (lines 25–69) to include _additional alongside
the returned data, while preserving the existing isFractal behavior.
| $meta = $array['meta'] ?? []; | ||
| unset($meta['path'], $meta['per_page'], $meta['next_page_url'], $meta['prev_page_url']); | ||
|
|
||
| if (isset($this->_additional['meta'])) { | ||
| $meta = array_merge($meta, $this->_additional['meta']); | ||
| } | ||
|
|
||
| $meta['cursor'] = $cursor; | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the target file and nearby context
printf '\n== CursorPaginatedDataCollection.php ==\n'
cat -n app/Data/CursorPaginatedDataCollection.php | sed -n '1,160p'
# Look for related cursor/meta handling in the repo
printf '\n== Search for cursor meta handling ==\n'
rg -n "next_cursor|prev_cursor|cursor" app src . -g '!vendor' -g '!node_modules' || true
# Check composer constraints for Laravel version clues
printf '\n== composer.json ==\n'
cat -n composer.json | sed -n '1,220p'Repository: pelican-dev/panel
Length of output: 50375
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Determine whether the codebase vendors Laravel paginator classes or references their array shape.
printf '\n== Search for CursorPaginator usage ==\n'
rg -n "CursorPaginator|cursor paginator|toArray\(\)" . -g '!vendor' -g '!node_modules' || true
# If a lockfile exists, inspect installed Laravel component versions.
printf '\n== composer.lock Laravel packages ==\n'
if [ -f composer.lock ]; then
rg -n '"name": "illuminate/(pagination|support|contracts|collections|container)|"version":' composer.lock | sed -n '1,120p'
fiRepository: pelican-dev/panel
Length of output: 50374
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== composer.json relevant deps ==\n'
python3 - <<'PY'
import json
from pathlib import Path
data = json.loads(Path('composer.json').read_text())
for section in ('require', 'require-dev'):
deps = data.get(section, {})
for name in ('laravel/framework', 'illuminate/pagination', 'spatie/laravel-data'):
if name in deps:
print(f'{section}: {name} {deps[name]}')
PY
printf '\n== composer.lock relevant package versions ==\n'
python3 - <<'PY'
import json
from pathlib import Path
p = Path('composer.lock')
if not p.exists():
print('composer.lock missing')
raise SystemExit(0)
data = json.loads(p.read_text())
wanted = {'laravel/framework', 'illuminate/pagination', 'spatie/laravel-data'}
for pkg in data.get('packages', []) + data.get('packages-dev', []):
if pkg.get('name') in wanted:
print(pkg['name'], pkg.get('version'))
PY
printf '\n== repository references to CursorPaginator ==\n'
rg -n "CursorPaginator|next_cursor|prev_cursor" app config database routes tests .github . -g '!vendor' -g '!node_modules' | sed -n '1,120p'Repository: pelican-dev/panel
Length of output: 751
🌐 Web query:
Laravel 13.19 CursorPaginator toArray next_cursor prev_cursor meta source
💡 Result:
In Laravel 13.19, the CursorPaginator class's toArray() method defines the structure of the array representation, which serves as the basis for its JSON output [1][2][3]. The toArray() implementation is as follows: return [ 'data' => $this->items->toArray, 'path' => $this->path, 'per_page' => $this->perPage, 'next_cursor' => $this->nextCursor?->encode, 'next_page_url' => $this->nextPageUrl, 'prev_cursor' => $this->previousCursor?->encode, 'prev_page_url' => $this->previousPageUrl, ]; Key structural details include: 1. Data: The records for the current page are located under the 'data' key [1][3]. 2. Cursors: The 'next_cursor' and 'prev_cursor' values are generated by calling the encode method on the respective Cursor objects returned by nextCursor() and previousCursor() [1][2]. 3. Meta: Unlike standard paginators, the default toArray() output for CursorPaginator does not include a dedicated 'meta' key; it includes pagination information (like cursors and URLs) at the top level of the array [1][3]. If you are using API Resources or custom response formatting that requires a 'meta' object, you may need to manually structure the response, as CursorPaginator does not automatically calculate a 'total' count due to the nature of cursor-based pagination [4]. To include such data, developers typically create an explicit structure in the controller or resource collection [4]. Top results: [1][3][5]
Citations:
- 1: https://github.com/laravel/framework/blob/12.x/src/Illuminate/Pagination/CursorPaginator.php
- 2: https://github.com/illuminate/pagination/blob/master/CursorPaginator.php
- 3: https://github.com/laravel/framework/blob/1d3c6c59/src/Illuminate/Pagination/CursorPaginator.php
- 4: https://devsolus.com/laravel-resource-not-showing-total-attribute-inside-meta-when-returned-as-json-response/
- 5: https://laravel.com/docs/13.x/pagination
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== app/Data/Data.php ==\n'
cat -n app/Data/Data.php | sed -n '1,220p'
printf '\n== Cursor collection inheritance points ==\n'
rg -n "CursorPaginatedDataCollection|PaginatedDataCollection|toArray\(\): array|additional\(array" app/Data -nRepository: pelican-dev/panel
Length of output: 4231
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== app/Data/Data.php ==\n'
cat -n app/Data/Data.php | sed -n '1,220p'
printf '\n== app/Data directory outline ==\n'
find app/Data -maxdepth 1 -type f | sortRepository: pelican-dev/panel
Length of output: 2985
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== app/Data/PaginatedDataCollection.php ==\n'
cat -n app/Data/PaginatedDataCollection.php | sed -n '1,220p'
printf '\n== app/Data/DataCollection.php ==\n'
cat -n app/Data/DataCollection.php | sed -n '1,220p'Repository: pelican-dev/panel
Length of output: 5761
🌐 Web query:
Spatie Laravel Data CursorPaginatedDataCollection toArray meta next_cursor prev_cursor
💡 Result:
In the spatie/laravel-data package, CursorPaginatedDataCollection is designed to handle cursor-based pagination for data objects [1][2]. When you call toArray on a CursorPaginatedDataCollection, it transforms the underlying CursorPaginator instance into an array representation [3][4]. Regarding the specific metadata keys next_cursor and prev_cursor: 1. Standard Laravel Behavior: The underlying Laravel CursorPaginator class includes next_cursor and prev_cursor in its own toArray method, along with next_page_url and prev_page_url [4]. 2. Spatie Implementation: Spatie's CursorPaginatedDataCollection essentially wraps this cursor-paginated data [3][1]. When converted to an array, the metadata structure typically mirrors the underlying paginator's output, which includes the cursor information necessary for navigation [4]. 3. Key Clarification: While the package provides the cursor values in the metadata [4], note that in some contexts (like TypeScript transformer generation), there has been historical confusion regarding the naming of these properties compared to standard pagination links [5]. However, when using the standard toArray method, the structure returned by the underlying Laravel CursorPaginator—containing next_cursor and prev_cursor—is preserved within the meta key of the final array output [4]. If you find that these keys are missing in your specific output, verify that you are interacting with the collection as a resource, as Spatie's data objects are designed to automatically include this pagination metadata when returned in responses [6].
Citations:
- 1: https://spatie-laravel-data.mintlify.app/as-a-dto/collections
- 2: https://spatie.be/docs/laravel-data/v3/advanced-usage/custom-collections
- 3: https://github.com/spatie/laravel-data/blob/40b64605/src/CursorPaginatedDataCollection.php
- 4: https://github.com/laravel/framework/blob/12.x/src/Illuminate/Pagination/CursorPaginator.php
- 5: fix DataTypeScriptTransformer cursor paginator properties spatie/laravel-data#1098
- 6: https://spatie.be/docs/laravel-data/v4/as-a-resource/from-data-to-resource
🌐 Web query:
site:github.com spatie/laravel-data CursorPaginatedDataCollection toArray meta next_cursor prev_cursor
💡 Result:
When using CursorPaginatedDataCollection in spatie/laravel-data, calling the toArray method results in a structure that includes the paginated data items and a meta key containing pagination information [1]. This meta object incorporates cursor-based pagination fields, including next_cursor and prev_cursor [2][1]. The underlying behavior is driven by the Laravel CursorPaginator [3][2]. When transformed to an array, the meta section typically includes the following [2][1]: - data: The collection of transformed data objects [2][1]. - meta: - next_cursor: The encoded string representing the cursor for the next page (or null) [2][1]. - prev_cursor: The encoded string representing the cursor for the previous page (or null) [2][1]. - next_page_url: The URL to the next page [2][1]. - prev_page_url: The URL to the previous page [2][1]. - path: The base path for the paginator [2][1]. - per_page: The number of items per page [2][1]. Note that while these fields exist within the Laravel CursorPaginator implementation [2], some users have noted that when using the spatie/laravel-data package, this information is structured under the meta key [1]. The next_cursor and prev_cursor values are strings generated by the underlying Laravel framework's cursor encoding [2][1].
Citations:
- 1: Paginate does not work spatie/laravel-data#236
- 2: https://github.com/laravel/framework/blob/12.x/src/Illuminate/Pagination/CursorPaginator.php
- 3: https://github.com/spatie/laravel-data/blob/40b64605/src/CursorPaginatedDataCollection.php
Strip next_cursor / prev_cursor from meta The parent paginator output still carries those keys, so they end up duplicated next to the custom cursor object here. app/Data/CursorPaginatedDataCollection.php:54
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/Data/CursorPaginatedDataCollection.php` around lines 53 - 61, Update the
metadata cleanup in the cursor pagination flow to also remove next_cursor and
prev_cursor from $meta before merging additional metadata and assigning the
custom cursor. Preserve the existing removal of path, per_page, next_page_url,
and prev_page_url.
| public function toArray(): array | ||
| { | ||
| $array = parent::toArray(); | ||
| if ($this->isFractal) { | ||
| $resourceKey = method_exists($this, 'getResourceName') | ||
| ? $this->getResourceName() | ||
| : strtolower(class_basename($this)); | ||
|
|
||
| $additional = $this->getAdditionalData(); | ||
| foreach ($additional as $key => $value) { | ||
| unset($array[$key]); | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect vendor source (if present) for the real additional-data accessor.
fd -t d 'laravel-data' vendor/spatie 2>/dev/null
rg -n 'function getAdditional|protected array \$additional|function additional\(' vendor/spatie/laravel-data/src 2>/dev/nullRepository: pelican-dev/panel
Length of output: 155
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the package version pinned in the repo and any local references to the accessor.
rg -n '"spatie/laravel-data"|spatie/laravel-data' composer.json composer.lock 2>/dev/null || true
rg -n 'getAdditionalData|additionalData|setFractal|toArray\(' app src tests 2>/dev/null || trueRepository: pelican-dev/panel
Length of output: 17360
🌐 Web query:
spatie/laravel-data 4.23.0 getAdditionalData additional trait source
💡 Result:
In spatie/laravel-data, the ability to use the additional method—and by extension manage additional data—is provided by the AppendableData trait [1]. The specific trait is: Spatie\LaravelData\Concerns\AppendableData [1] This trait is one of the standard concerns implemented by the base Data class [2]. It enables the additional(['key' => 'value']) method, which allows you to append extra properties to your data objects or collections when they are transformed into a resource [3][1][4]. While your query specifically mentions getAdditionalData, please note that the public API provided by the AppendableData trait is primarily additional [1][4]. If you are looking for how the data is stored or retrieved internally, you should inspect the source code of the AppendableData trait within the package's src/Concerns directory [2][1]. As of version 4.23.0, there are no breaking changes or new features introduced that modify the core functionality of the AppendableData trait [5][6]. The version 4.23.0 release focused on validation rule overrides and other bug fixes [5][6].
Citations:
- 1: https://spatie-laravel-data.mintlify.app/advanced-usage/traits-and-interfaces
- 2: https://github.com/spatie/laravel-data/blob/main/docs/advanced-usage/traits-and-interfaces.md
- 3: https://github.com/spatie/laravel-data/blob/main/docs/as-a-resource/appending-properties.md
- 4: https://spatie.be/docs/laravel-data/v4/as-a-resource/appending-properties
- 5: https://github.com/spatie/laravel-data/releases/tag/4.23.0
- 6: https://github.com/spatie/laravel-data/blob/HEAD/CHANGELOG.md
🌐 Web query:
site:github.com/spatie/laravel-data "function getAdditionalData" OR "getAdditionalData()" "AppendableData"
💡 Result:
In the context of the spatie/laravel-data package, AppendableData refers to a trait and contract that provides functionality for appending extra properties to data objects when they are transformed [1][2]. The package does not define a specific method named getAdditionalData that returns an AppendableData object. Instead, the package provides an additional method on data objects to add extra properties to the transformed output [3]. Usage Example: SongData::from(Song::first)->additional([ 'year' => 1987, ]); The AppendableData trait is implemented by the base Data class, allowing data objects to include supplemental data alongside their primary attributes when serialized [2]. While you can use additional to pass an array of data, the internal mechanisms for handling these properties are managed by the AppendableData trait and the underlying transformation logic [3][2].
Citations:
- 1: https://github.com/spatie/laravel-data/blob/main/docs/advanced-usage/internal-structures.md
- 2: https://github.com/spatie/laravel-data/blob/main/docs/advanced-usage/traits-and-interfaces.md
- 3: https://github.com/spatie/laravel-data/blob/main/docs/as-a-resource/appending-properties.md
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- app/Data/Data.php ---'
cat -n app/Data/Data.php
echo
echo '--- project references to getAdditionalData ---'
rg -n 'function getAdditionalData|getAdditionalData\(' app tests src 2>/dev/null || true
echo
echo '--- related data classes ---'
for f in app/Data/DataCollection.php app/Data/PaginatedDataCollection.php app/Data/CursorPaginatedDataCollection.php; do
echo "### $f"
cat -n "$f"
echo
doneRepository: pelican-dev/panel
Length of output: 11285
🌐 Web query:
site:github.com/spatie/laravel-data "getAdditionalData" "Data.php" "additional("
💡 Result:
The code snippet getAdditionalData likely refers to the additional() method provided by the spatie/laravel-data package in PHP [1][2]. This method is used to append extra properties to a data object when it is transformed into a resource (e.g., when returned as a JSON response in a Laravel controller) [2]. Key aspects of the additional() method include: 1. Functionality: It allows you to pass an array of key-value pairs that will be included alongside the serialized data object in the final response [1][2]. 2. Usage: You call additional() on an instance of a data object, often before returning it [3][2]. It supports passing a closure, which receives the underlying data object, allowing for dynamic property values [2]. 3. Relationship to Wrapping: When a data object is wrapped (e.g., using wrap('data')), the properties added via additional() are generally not included inside the wrapper; they appear at the top level of the response, similar to how additional() works with standard Laravel JsonResource classes [1][4]. 4. Alternative: You can also use the with() method within your Data class to define additional properties that should always be included whenever that data object is transformed [3][2]. Example usage: $data = SongData::from($song)->additional([ 'year' => 1987, 'slug' => fn(SongData $songData) => Str::slug($songData->title), ]);
Citations:
- 1: Not wrapping additional properties spatie/laravel-data#893
- 2: https://github.com/spatie/laravel-data/blob/main/docs/as-a-resource/appending-properties.md
- 3: https://github.com/spatie/laravel-data/blob/40b64605/tests/WrapTest.php
- 4: How to add additional like JsonResource spatie/laravel-data#512
Replace getAdditionalData()
Spatie\LaravelData\Data doesn't expose this accessor, so any path that hits the fractal branch will throw a fatal error. Use the package's supported additional-data API instead.
🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 52-52: Avoid unused local variables such as '$value'. (undefined)
(UnusedLocalVariable)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/Data/Data.php` around lines 43 - 54, Replace the unsupported
getAdditionalData() call in Data::toArray() with Spatie Laravel Data’s supported
additional-data API, preserving the existing iteration that removes
additional-data keys from the serialized array.
| public function additional(array $additional): static | ||
| { | ||
| $this->_additional = array_merge($this->_additional, $additional); | ||
| return $this; | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Same additional() bypass as in DataCollection.php.
This override doesn't delegate to any parent additional() implementation, so metadata is only surfaced when isFractal is true (Line 78-80). In the default (non-fractal) branch (return $array;, Line 90), anything passed to ->additional([...]) is lost. See the equivalent comment on app/Data/DataCollection.php for a suggested defensive fix (merge _additional into $array in the non-fractal branch too).
Also applies to: 25-91
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/Data/PaginatedDataCollection.php` around lines 19 - 23, Update
PaginatedDataCollection’s non-fractal response path to merge _additional into
the returned $array before the return, ensuring values supplied through
additional() are preserved. Keep the existing isFractal metadata behavior
unchanged and retain additional()’s current accumulation semantics.
|
Thanks for the contribution, however that issue is not resolved by this pr. |
Closes #1051. Introduces custom base Data and collection classes with fractal structure formatting when setFractal(true) is used. Migrated ApiKeyController, SSHKeyController, and AccountController as Phase 1.