I've run into a problem where I've used an attribute casted as an array in a Laravel resource and I wanted to preserve the keys of that array. By default, Laravel will re-index the array, which is not what I wanted.
To preserve the keys, you can use the preserveKeys
method on the collection. Here's an example:
1namespace App\Http\Resources;
2
3use Illuminate\Http\Resources\Json\JsonResource;
4
5class User extends JsonResource
6{
7 /**
8 * Indicates if the resource's collection keys should be preserved.
9 *
10 * @var bool
11 */
12 public $preserveKeys = true;
13}
When the preserveKeys
property is set to true
, collection keys will be preserved:
1use App\User;
2use App\Http\Resources\User as UserResource;
3
4Route::get('/user', function () {
5 return UserResource::collection(User::all()->keyBy->id);
6});
What I didn't know is that this didn't only apply to the resource, but also to the attributes of the resource.
If you don't want to enable this option for the complete resource, once approach you can take is to create a new resource like this:
1namespace App\Http\Resources;
2
3use Illuminate\Http\Request;
4use Illuminate\Http\Resources\Json\JsonResource;
5
6class ArrayPreservingKeysResource extends JsonResource
7{
8 /**
9 * Indicates if the resource's collection keys should be preserved.
10 *
11 * @var bool
12 */
13 public $preserveKeys = true;
14
15 public function toArray(Request $request): array
16 {
17 return $this->resource;
18 }
19}
You can then apply to any array you want to preserve the keys of in the resource:
1namespace App\Http\Resources;
2
3use App\Domains\Predictions\Models\Prediction;
4use Illuminate\Http\Request;
5use Illuminate\Http\Resources\Json\JsonResource;
6
7/**
8 * @mixin Company
9 */
10class CompanyResource extends JsonResource
11{
12 public function toArray(Request $request): array
13 {
14 return [
15 'id' => $this->id,
16 'name' => $this->name,
17 'data' => new ArrayPreservingKeysResource($this->data),
18 ];
19 }
20}
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.