├── .editorconfig ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── dependabot-auto-merge.yml │ ├── php-cs-fixer.yml │ ├── run-tests.yml │ └── update-changelog.yml ├── .php_cs.dist.php ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── UPGRADE.md ├── composer.json ├── config └── fractal.php └── src ├── Console ├── Commands │ └── TransformerMakeCommand.php └── stubs │ └── transformer.stub ├── Facades └── Fractal.php ├── Fractal.php ├── FractalServiceProvider.php └── helpers.php /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_size = 4 9 | indent_style = space 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://spatie.be/open-source/support-us 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "weekly" 9 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: dependabot-auto-merge 2 | on: pull_request_target 3 | 4 | permissions: 5 | pull-requests: write 6 | contents: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.actor == 'dependabot[bot]' }} 12 | steps: 13 | 14 | - name: Dependabot metadata 15 | id: metadata 16 | uses: dependabot/fetch-metadata@v2.4.0 17 | with: 18 | github-token: "${{ secrets.GITHUB_TOKEN }}" 19 | compat-lookup: true 20 | 21 | - name: Auto-merge Dependabot PRs for semver-minor updates 22 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}} 23 | run: gh pr merge --auto --merge "$PR_URL" 24 | env: 25 | PR_URL: ${{github.event.pull_request.html_url}} 26 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 27 | 28 | - name: Auto-merge Dependabot PRs for semver-patch updates 29 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}} 30 | run: gh pr merge --auto --merge "$PR_URL" 31 | env: 32 | PR_URL: ${{github.event.pull_request.html_url}} 33 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 34 | 35 | - name: Auto-merge Dependabot PRs for Action major versions when compatibility is higher than 90% 36 | if: ${{steps.metadata.outputs.package-ecosystem == 'github_actions' && steps.metadata.outputs.update-type == 'version-update:semver-major' && steps.metadata.outputs.compatibility-score >= 90}} 37 | run: gh pr merge --auto --merge "$PR_URL" 38 | env: 39 | PR_URL: ${{github.event.pull_request.html_url}} 40 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 41 | -------------------------------------------------------------------------------- /.github/workflows/php-cs-fixer.yml: -------------------------------------------------------------------------------- 1 | name: Check & fix styling 2 | 3 | on: [push] 4 | 5 | jobs: 6 | php-cs-fixer: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout code 11 | uses: actions/checkout@v4 12 | with: 13 | ref: ${{ github.head_ref }} 14 | 15 | - name: Run PHP CS Fixer 16 | uses: docker://oskarstark/php-cs-fixer-ga 17 | with: 18 | args: --config=.php_cs.dist.php --allow-risky=yes 19 | 20 | - name: Commit changes 21 | uses: stefanzweifel/git-auto-commit-action@v4 22 | with: 23 | commit_message: Fix styling 24 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: run-tests 2 | 3 | on: 4 | - push 5 | 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | php: [8.4, 8.3, 8.2, 8.1, 8.0] 14 | laravel: ['9.*', '10.*', '11.*', '12.*'] 15 | dependency-version: [prefer-lowest, prefer-stable] 16 | include: 17 | - laravel: 10.* 18 | testbench: 8.* 19 | - laravel: 9.* 20 | testbench: 7.* 21 | - laravel: 11.* 22 | testbench: 9.* 23 | - laravel: 12.* 24 | testbench: 10.* 25 | exclude: 26 | - laravel: 10.* 27 | php: 8.0 28 | - laravel: 10.* 29 | php: 7.4 30 | - laravel: 11.* 31 | php: 8.1 32 | - laravel: 11.* 33 | php: 8.0 34 | - laravel: 12.* 35 | php: 8.1 36 | - laravel: 12.* 37 | php: 8.0 38 | 39 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} 40 | 41 | steps: 42 | - name: Checkout code 43 | uses: actions/checkout@v4 44 | 45 | - name: Setup PHP 46 | uses: shivammathur/setup-php@v2 47 | with: 48 | php-version: ${{ matrix.php }} 49 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick 50 | coverage: none 51 | 52 | - name: Install dependencies 53 | run: | 54 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update 55 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest 56 | 57 | - name: Execute tests 58 | run: vendor/bin/pest 59 | -------------------------------------------------------------------------------- /.github/workflows/update-changelog.yml: -------------------------------------------------------------------------------- 1 | name: "Update Changelog" 2 | 3 | on: 4 | release: 5 | types: [released] 6 | 7 | jobs: 8 | update: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v4 14 | with: 15 | ref: main 16 | 17 | - name: Update Changelog 18 | uses: stefanzweifel/changelog-updater-action@v1 19 | with: 20 | latest-version: ${{ github.event.release.name }} 21 | release-notes: ${{ github.event.release.body }} 22 | 23 | - name: Commit updated CHANGELOG 24 | uses: stefanzweifel/git-auto-commit-action@v4 25 | with: 26 | branch: main 27 | commit_message: Update CHANGELOG 28 | file_pattern: CHANGELOG.md 29 | -------------------------------------------------------------------------------- /.php_cs.dist.php: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__ . '/src', 6 | __DIR__ . '/tests', 7 | ]) 8 | ->name('*.php') 9 | ->notName('*.blade.php') 10 | ->ignoreDotFiles(true) 11 | ->ignoreVCS(true); 12 | 13 | return (new PhpCsFixer\Config()) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 18 | 'no_unused_imports' => true, 19 | 'not_operator_with_successor_space' => true, 20 | 'trailing_comma_in_multiline' => true, 21 | 'phpdoc_scalar' => true, 22 | 'unary_operator_spaces' => true, 23 | 'binary_operator_spaces' => true, 24 | 'blank_line_before_statement' => [ 25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 26 | ], 27 | 'phpdoc_single_line_var_spacing' => true, 28 | 'phpdoc_var_without_name' => true, 29 | 'class_attributes_separation' => [ 30 | 'elements' => [ 31 | 'method' => 'one', 32 | ], 33 | ], 34 | 'method_argument_space' => [ 35 | 'on_multiline' => 'ensure_fully_multiline', 36 | 'keep_multiple_spaces_after_comma' => true, 37 | ], 38 | 'single_trait_insert_per_statement' => true, 39 | ]) 40 | ->setFinder($finder); 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-fractal` will be documented in this file 4 | 5 | ## 6.3.2 - 2025-02-14 6 | 7 | ### What's Changed 8 | 9 | * Bump dependabot/fetch-metadata from 2.2.0 to 2.3.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/263 10 | * Laravel 12.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-fractal/pull/264 11 | 12 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.3.1...6.3.2 13 | 14 | ## 6.3.1 - 2024-12-16 15 | 16 | ### What's Changed 17 | 18 | * feat: disable fieldsets by default by @Mohammad-Alavi in https://github.com/spatie/laravel-fractal/pull/262 19 | 20 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.3.0...6.3.1 21 | 22 | ## 6.3.0 - 2024-12-09 23 | 24 | ### What's Changed 25 | 26 | * Allow auto parsing the `fieldsets` by @Mohammad-Alavi in https://github.com/spatie/laravel-fractal/pull/261 27 | 28 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.2.2...6.3.0 29 | 30 | ## 6.2.2 - 2024-12-09 31 | 32 | ### What's Changed 33 | 34 | * Bump dependabot/fetch-metadata from 1.6.0 to 2.1.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/257 35 | * Bump dependabot/fetch-metadata from 2.1.0 to 2.2.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/259 36 | * fix phpdoc mismatch by @Mohammad-Alavi in https://github.com/spatie/laravel-fractal/pull/260 37 | 38 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.2.1...6.2.2 39 | 40 | ## 6.2.1 - 2024-06-04 41 | 42 | ### What's Changed 43 | 44 | * fix: wrong `return` annotation by @Mohammad-Alavi in https://github.com/spatie/laravel-fractal/pull/258 45 | 46 | ### New Contributors 47 | 48 | * @Mohammad-Alavi made their first contribution in https://github.com/spatie/laravel-fractal/pull/258 49 | 50 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.2.0...6.2.1 51 | 52 | ## 6.2.0 - 2024-03-18 53 | 54 | ### What's Changed 55 | 56 | * Auto excludes by @simondotwhite in https://github.com/spatie/laravel-fractal/pull/253 57 | 58 | ### New Contributors 59 | 60 | * @simondotwhite made their first contribution in https://github.com/spatie/laravel-fractal/pull/253 61 | 62 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.1.0...6.2.0 63 | 64 | ## 6.1.0 - 2024-03-02 65 | 66 | ### What's Changed 67 | 68 | * Bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/247 69 | * Bump dependabot/fetch-metadata from 1.4.0 to 1.5.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/248 70 | * Bump dependabot/fetch-metadata from 1.5.0 to 1.5.1 by @dependabot in https://github.com/spatie/laravel-fractal/pull/249 71 | * Bump dependabot/fetch-metadata from 1.5.1 to 1.6.0 by @dependabot in https://github.com/spatie/laravel-fractal/pull/250 72 | * Bump actions/checkout from 3 to 4 by @dependabot in https://github.com/spatie/laravel-fractal/pull/251 73 | * Laravel 11.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-fractal/pull/254 74 | 75 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.0.3...6.1.0 76 | 77 | ## 6.0.3 - 2023-02-15 78 | 79 | ### What's Changed 80 | 81 | - Add Dependabot Automation by @patinthehat in https://github.com/spatie/laravel-fractal/pull/237 82 | - Bump actions/checkout from 2 to 3 by @dependabot in https://github.com/spatie/laravel-fractal/pull/239 83 | - Add PHP 8.2 Support by @patinthehat in https://github.com/spatie/laravel-fractal/pull/238 84 | - Fix broken tests by @patinthehat in https://github.com/spatie/laravel-fractal/pull/240 85 | - Refactor tests to pest by @AyoobMH in https://github.com/spatie/laravel-fractal/pull/244 86 | - Laravel 10.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-fractal/pull/245 87 | - Bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 by @dependabot in https://github.com/spatie/laravel-fractal/pull/246 88 | 89 | ### New Contributors 90 | 91 | - @patinthehat made their first contribution in https://github.com/spatie/laravel-fractal/pull/237 92 | - @dependabot made their first contribution in https://github.com/spatie/laravel-fractal/pull/239 93 | - @AyoobMH made their first contribution in https://github.com/spatie/laravel-fractal/pull/244 94 | - @laravel-shift made their first contribution in https://github.com/spatie/laravel-fractal/pull/245 95 | 96 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.0.2...6.0.3 97 | 98 | ## 6.0.2 - 2022-04-04 99 | 100 | ## What's Changed 101 | 102 | - Make stubs compatible with the latest `league/fractal` version by @osbre in https://github.com/spatie/laravel-fractal/pull/226 103 | 104 | ## New Contributors 105 | 106 | - @osbre made their first contribution in https://github.com/spatie/laravel-fractal/pull/226 107 | 108 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.0.1...6.0.2 109 | 110 | ## 6.0.1 - 2022-03-31 111 | 112 | ## What's Changed 113 | 114 | - Updated compose.json to handle with previous version by @deniscsz in https://github.com/spatie/laravel-fractal/pull/221 115 | 116 | ## New Contributors 117 | 118 | - @deniscsz made their first contribution in https://github.com/spatie/laravel-fractal/pull/221 119 | 120 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/6.0.0...6.0.1 121 | 122 | ## 6.0.0 - 2022-01-13 123 | 124 | ## What's Changed 125 | 126 | - Add support for Laravel 9 127 | - Fix style by @ahmadmayahi in https://github.com/spatie/laravel-fractal/pull/211 128 | - fix readme macroable push meta by @greg0x46 in https://github.com/spatie/laravel-fractal/pull/217 129 | 130 | ## New Contributors 131 | 132 | - @ahmadmayahi made their first contribution in https://github.com/spatie/laravel-fractal/pull/211 133 | - @greg0x46 made their first contribution in https://github.com/spatie/laravel-fractal/pull/217 134 | 135 | **Full Changelog**: https://github.com/spatie/laravel-fractal/compare/5.8.1...6.0.0 136 | 137 | ## 5.8.1 - 2020-11-12 138 | 139 | - add support for PHP 8 140 | 141 | ## 5.8.0 - 2020-09-08 142 | 143 | - add support for Laravel 8 144 | 145 | ## 5.7.0 - 2020-03-02 146 | 147 | - add support for Laravel 7 148 | 149 | ## 5.6.1 - 2019-11-19 150 | 151 | - update transformer stub (#200) 152 | 153 | ## 5.6.0 - 2019-09-04 154 | 155 | - make compatible with Laravel 6 156 | 157 | ## 5.5.1 - 2019-03-13 158 | 159 | - add `Spatie\Fractal\Facades\Fractal` 160 | 161 | ## 5.5.0 - 2019-02-27 162 | 163 | - drop support for PHP 7.1 164 | 165 | ## 5.4.4 - 2019-02-27 166 | 167 | - drop support for PHP 7.0 168 | - add support for Laravel 5.8 169 | 170 | ## 5.4.3 - 2019-01-16 171 | 172 | - improve singleton definition 173 | 174 | ## 5.4.2 - 2018-09-28 175 | 176 | - support Lumen 177 | 178 | ## 5.4.1 - 2018-08-24 179 | 180 | - add support for Laravel 5.7 181 | 182 | ## 5.4.0 - 2018-07-19 183 | 184 | - make fractal macroable 185 | 186 | ## 5.3.2 - 2018-06-13 187 | 188 | - fixed #153 189 | 190 | ## 5.3.1 - 2018-02-08 191 | 192 | - add support for L5.6 193 | 194 | ## 5.3.0 - 2017-11-28 195 | 196 | - add `transformWith` collection macro 197 | 198 | ## 5.2.0 - 2017-09-15 199 | 200 | - add compatibility with Lumen 5.5 201 | 202 | ## 5.1.0 - 2017-09-08 203 | 204 | - allow json encoding options to be passed to the `respond` method 205 | 206 | ## 5.0.1 - 2017-08-30 207 | 208 | - Fix wrongly tagged commit 209 | 210 | ## 5.0.0 - 2017-08-30 211 | 212 | - Laravel 5.5 support, dropped support for all older versions 213 | - renamed config file from `laravel-fractal` to `fractal` 214 | - added auto-includes 215 | 216 | ## 4.5.0 - 2017-08-20 217 | 218 | - add `default_paginator` to config file 219 | 220 | ## 4.4.0 - 2017-08-20 221 | 222 | - add `fractal_class` to config file 223 | 224 | ## 4.3.0 - 2017-07-26 225 | 226 | - Add baseUrl support for the JsonApi serializer 227 | 228 | ## 4.2.0 - 2017-07-18 229 | 230 | - Nothing changed! Something went wrong with tagging the last version so we had to bump the version a bit? 231 | 232 | ## 4.0.1 - 2017-05-05 233 | 234 | - Fixes bug where a passed serializer wouldn't be used 235 | 236 | ## 4.0.0 - 2017-04-26 237 | 238 | - Add compatiblity with fractal 0.16 through fractalistic 2.0 239 | 240 | ## 3.5.0 - 2017-02-22 241 | 242 | - Add compatiblity with Lumen 243 | 244 | ## 3.4.1 - 2017-02-07 245 | 246 | - Fix resolving `Fractal::class` out of the container 247 | 248 | ## 3.4.0 - 2017-02-04 249 | 250 | - Add support for passing paginators to the `data` argument of `fractal()` 251 | 252 | ## 3.3.1 - 2017-01-27 253 | 254 | - Bind `laravel-fractal` as a singleton 255 | 256 | ## 3.3.0 - 2017-01-23 257 | 258 | - Add support for Laravel 5.4 259 | 260 | ## 3.2.1 - 2017-01-20 261 | 262 | - Improve descriptions of generator command 263 | 264 | ## 3.2.0 - 2017-01-14 265 | 266 | - Allow closures to be used as serializers 267 | 268 | ## 3.1.3 - 2017-01-08 269 | 270 | - Fixed missing namespace import in Fractal 271 | 272 | ## 3.1.2 - 2017-01-08 273 | 274 | - The facade will now use the configured serializer 275 | 276 | ## 3.1.1 - 2017-01-08 277 | 278 | - Fix wrong implementation of the `respond` method. 279 | 280 | If you encounter errors when upgrading from `3.1.0` to this version, replace all usages of `Spatie\Fractal\Response` by `Illuminate\Http\JsonResponse`. All calls to the `headers` method on that class should be replaced by `withHeaders`. 281 | 282 | ## 3.1.0 - 2017-01-05 283 | 284 | - Add `respond` method 285 | 286 | ## 3.0.1 - 2016-12-09 287 | 288 | - Fix dependencies in `composer.json` 289 | 290 | ## 3.0.0 - 2016-12-09 291 | 292 | - Make use of `spatie/fractalistic` 293 | 294 | ## 2.1.0 - 2016-12-02 295 | 296 | - Add `make:transformer` artisan command. 297 | 298 | ## 2.0.0 - 2016-09-27 299 | 300 | - Made compatible with fractal `0.14` 301 | - Improvements to the `fractal`-helper function. 302 | - Added excludes 303 | 304 | ## 1.9.1 - 2016-08-23 305 | 306 | - Added L5.3 compatibility 307 | 308 | ## 1.9.0 - 2016-03-30 309 | 310 | - Added support for cursors 311 | 312 | ## 1.8.0 - 2016-02-18 313 | 314 | - The `Fractal`-class now implements the `JsonSerializable`-interface 315 | 316 | ## 1.7.4 - 2015-12-16 317 | 318 | - Fixed a bug when passing a null value to parseIncludes 319 | 320 | ## 1.7.3 - 2015-11-09 321 | 322 | - Fixed bug when adding multiple includes in one go 323 | 324 | ## 1.7.2 - 2015-11-09 325 | 326 | - Fix for adding multiple includes in one go. 327 | 328 | ** this version contains a bug when adding multiple includes in one go, please upgrade to v1.7.3 ** 329 | 330 | ## 1.7.1 - 2015-10-26 331 | 332 | - Fix for setting the default_serializer as an instantiation in Lumen 333 | 334 | ## 1.7.0 - 2015-10-26 335 | 336 | - Allow default_serializer to be set as an instantiation 337 | 338 | ## 1.6.1 - 2015-10-21 339 | 340 | - Dependency version number of fractal in composer.json 341 | 342 | ## 1.6.0 - 2015-10-20 343 | 344 | - Compatiblity with version v0.13 of Fractal 345 | 346 | Please not that the output of `JsonApiSerializer` has been changed in v0.13 of Fractal. 347 | 348 | ## 1.5.0 - 2015-10-14 349 | 350 | - Support for including meta data 351 | 352 | ## 1.4.0 - 2015-10-13 353 | 354 | - Pagination methods 355 | - Custom resource names 356 | 357 | ## 1.3.0 - 2015-10-13 358 | 359 | - Support for Lumen 360 | 361 | ## 1.2.0 - 2015-10-11 362 | 363 | - Methods to use includes 364 | - Create data method 365 | 366 | ## 1.1.0 - 2015-10-08 367 | 368 | - Made the `getResource`-function public 369 | 370 | ## 1.0.0 - 2015-10-07 371 | 372 | - Initial release 373 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Spatie bvba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An easy to use Fractal wrapper built for Laravel and Lumen applications 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-fractal.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-fractal) 4 | [![run-tests](https://github.com/spatie/laravel-fractal/actions/workflows/run-tests.yml/badge.svg)](https://github.com/spatie/laravel-fractal/actions/workflows/run-tests.yml) 5 | [![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-fractal.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-fractal) 6 | 7 | The package provides a nice and easy wrapper around [Fractal](http://fractal.thephpleague.com/) 8 | for use in your Laravel applications. If you don't know what Fractal does, [take a peek at their intro](http://fractal.thephpleague.com/). 9 | Shortly said, Fractal is very useful to transform data before using it in an API. 10 | 11 | Using Fractal data can be transformed like this: 12 | 13 | ```php 14 | use League\Fractal\Manager; 15 | use League\Fractal\Resource\Collection; 16 | 17 | $books = [ 18 | ['id' => 1, 'title' => 'Hogfather', 'characters' => [...]], 19 | ['id' => 2, 'title' => 'Game Of Kill Everyone', 'characters' => [...]] 20 | ]; 21 | 22 | $manager = new Manager(); 23 | 24 | $resource = new Collection($books, new BookTransformer()); 25 | 26 | $manager->parseIncludes('characters'); 27 | 28 | $manager->createData($resource)->toArray(); 29 | ``` 30 | 31 | This package makes that process a tad easier: 32 | 33 | ```php 34 | fractal() 35 | ->collection($books) 36 | ->transformWith(new BookTransformer()) 37 | ->includeCharacters() 38 | ->toArray(); 39 | ``` 40 | 41 | Lovers of facades will be glad to know that a facade is provided: 42 | ```php 43 | Fractal::collection($books)->transformWith(new BookTransformer())->toArray(); 44 | ``` 45 | 46 | There's also a very short syntax available to quickly transform data: 47 | 48 | ```php 49 | fractal($books, new BookTransformer())->toArray(); 50 | ``` 51 | 52 | You can transform directly from a Laravel collection as well: 53 | 54 | ```php 55 | collect($books)->transformWith(new BookTransformer()); 56 | ``` 57 | 58 | Transforming right from a Laravel collection is particularly useful for Eloquent results: 59 | 60 | ```php 61 | Users::all()->transformWith(new UserTransformer())->toArray(); 62 | ``` 63 | 64 | Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all 65 | our open source projects [on our website](https://spatie.be/opensource). 66 | 67 | ## Support us 68 | 69 | [](https://spatie.be/github-ad-click/laravel-fractal) 70 | 71 | We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). 72 | 73 | We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). 74 | 75 | ## Installation in Laravel 5.5 and up 76 | 77 | You can pull in the package via composer: 78 | ``` bash 79 | composer require spatie/laravel-fractal 80 | ``` 81 | 82 | The package will automatically register itself. 83 | 84 | If you want to [change the default serializer](https://github.com/spatie/fractalistic#changing-the-default-serializer), 85 | the [default paginator](https://github.com/spatie/fractalistic#using-pagination), 86 | or the default fractal class `Spatie\Fractal\Fractal` 87 | you must publish the config file: 88 | 89 | ```bash 90 | php artisan vendor:publish --provider="Spatie\Fractal\FractalServiceProvider" 91 | ``` 92 | 93 | > If you're upgrading to Laravel 5.5, the existing config file should be renamed from _laravel-fractal.php_ to _fractal.php_ 94 | 95 | This is the contents of the published file: 96 | 97 | ```php 98 | return [ 99 | /* 100 | * The default serializer to be used when performing a transformation. It 101 | * may be left empty to use Fractal's default one. This can either be a 102 | * string or a League\Fractal\Serializer\SerializerAbstract subclass. 103 | */ 104 | 'default_serializer' => '', 105 | 106 | /* The default paginator to be used when performing a transformation. It 107 | * may be left empty to use Fractal's default one. This can either be a 108 | * string or a League\Fractal\Paginator\PaginatorInterface subclass. 109 | */ 110 | 'default_paginator' => '', 111 | 112 | /* 113 | * League\Fractal\Serializer\JsonApiSerializer will use this value 114 | * as a prefix for generated links. Set to `null` to disable this. 115 | */ 116 | 'base_url' => null, 117 | 118 | /* 119 | * If you wish to override or extend the default Spatie\Fractal\Fractal 120 | * instance provide the name of the class you want to use. 121 | */ 122 | 'fractal_class' => Spatie\Fractal\Fractal::class, 123 | 124 | 'auto_includes' => [ 125 | 126 | /* 127 | * If enabled Fractal will automatically add the includes who's 128 | * names are present in the `include` request parameter. 129 | */ 130 | 'enabled' => true, 131 | 132 | /* 133 | * The name of key in the request to where we should look for the includes to include. 134 | */ 135 | 'request_key' => 'include', 136 | ], 137 | 138 | 'auto_excludes' => [ 139 | 140 | /* 141 | * If enabled Fractal will automatically add the excludes who's 142 | * names are present in the `exclude` request parameter. 143 | */ 144 | 'enabled' => true, 145 | 146 | /* 147 | * The name of key in the request to where we should look for the excludes to exclude. 148 | */ 149 | 'request_key' => 'exclude', 150 | ], 151 | 152 | 'auto_fieldsets' => [ 153 | 154 | /* 155 | * If enabled Fractal will automatically add the fieldsets who's 156 | * names are present in the `fields` request parameter. 157 | */ 158 | 'enabled' => true, 159 | 160 | /* 161 | * The name of key in the request, where we should look for the fieldsets to parse. 162 | */ 163 | 'request_key' => 'fields', 164 | ], 165 | ]; 166 | ``` 167 | 168 | ## Usage 169 | 170 | Refer to [the documentation of `spatie/fractalistic`](https://github.com/spatie/fractalistic) to learn all the methods this package provides. 171 | 172 | In all code examples you may use `fractal()` instead of `Fractal::create()`. 173 | 174 | ## Send a response with transformed data 175 | 176 | To return a response with json data you can do this in a Laravel app. 177 | 178 | ```php 179 | $books = fractal($books, new BookTransformer())->toArray(); 180 | 181 | return response()->json($books); 182 | ``` 183 | 184 | The `respond()` method on the Fractal class can make this process a bit more streamlined. 185 | 186 | ```php 187 | return fractal($books, new BookTransformer())->respond(); 188 | ``` 189 | 190 | You can pass a response code as the first parameter and optionally some headers as the second 191 | 192 | ```php 193 | return fractal($books, new BookTransformer())->respond(403, [ 194 | 'a-header' => 'a value', 195 | 'another-header' => 'another value', 196 | ]); 197 | ``` 198 | 199 | You can pass json encoding options as the third parameter: 200 | 201 | ```php 202 | return fractal($books, new BookTransformer())->respond(200, [], JSON_PRETTY_PRINT); 203 | ``` 204 | 205 | You can also set the status code and the headers using a callback: 206 | 207 | ```php 208 | use Illuminate\Http\JsonResponse; 209 | 210 | return fractal($books, new BookTransformer())->respond(function(JsonResponse $response) { 211 | $response 212 | ->setStatusCode(403) 213 | ->header('a-header', 'a value') 214 | ->withHeaders([ 215 | 'another-header' => 'another value', 216 | 'yet-another-header' => 'yet another value', 217 | ]); 218 | }); 219 | ``` 220 | 221 | You can add methods to the Fractal class using Laravel's Macroable trait. Imagine you want to add some stats to the metadata of your request, you can do so without cluttering your code: 222 | 223 | ```php 224 | use Spatie\Fractal\Fractal; 225 | 226 | Fractal::macro('stats', function ($stats) { 227 | // transform the passed stats as necessary here 228 | return $this->addMeta(['stats' => $stats]); 229 | }); 230 | 231 | fractal($books, new BookTransformer())->stats(['runtime' => 100])->respond(); 232 | ``` 233 | 234 | ## Quickly creating a transformer 235 | 236 | You can run the `make:transformer` command to quickly generate a dummy transformer. By default it will be stored in the `app\Transformers` directory. 237 | 238 | ## Upgrading 239 | 240 | ## From v4 to v5 241 | 242 | Rename your config file from `laravel-fractal` to `fractal` 243 | 244 | ### From v2 to v3 245 | 246 | `v3` was introduced to swap out the `league/fractal` with `spatie/fractalistic`. Support for Lumen was dropped. You should be able to upgrade a Laravel application from `v2` to `v3` without any code changes. 247 | ### From v1 to v2 248 | 249 | In most cases you can just upgrade to `v2` with making none or only minor changes to your code: 250 | 251 | - `resourceName` has been renamed to `withResourceName`. 252 | 253 | The main reason why `v2` of this package was tagged is because v0.14 of the underlying [Fractal](http://fractal.thephpleague.com/) by the League contains breaking change. If you use the `League\Fractal\Serializer\JsonApiSerializer` in v2 the `links` key will contain `self`, `first`, `next` and `last`. 254 | 255 | ## Changelog 256 | 257 | Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. 258 | 259 | ## Testing 260 | 261 | ``` bash 262 | $ composer test 263 | ``` 264 | 265 | ## Contributing 266 | 267 | Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. 268 | 269 | ## Security 270 | 271 | If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker. 272 | 273 | ## Credits 274 | 275 | - [Freek Van der Herten](https://twitter.com/freekmurze) 276 | - [All contributors](../../contributors) 277 | 278 | ## License 279 | 280 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 281 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | # Upgrade guide 2 | 3 | ## From v5 to v6 4 | 5 | In most cases, you don't need to do anything to upgrade, the API has remained the same. 6 | 7 | The facade has been moved from `Spatie\Fractal\FractalFacade` to `Spatie\Fractal\Facades\Fractal`. 8 | 9 | ## From v4 to v5 10 | 11 | If you have a configuration file named `laravel-fractal.php`, rename it to `fractal.php` for it to still be used. 12 | 13 | ## From v3 to v4 14 | 15 | v2 has mainly been made to provide compatibility with fractal 0.16 through fractalistic 2. In that version of Fractal your transformers, includes and excludes should return an array. String, ints, bools and such are not allowed anymore. 16 | 17 | If all your transformers follow that rule you should be able to upgrade to v2 without any modifications to your code. 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spatie/laravel-fractal", 3 | "description": "An easy to use Fractal integration for Laravel applications", 4 | "keywords": [ 5 | "spatie", 6 | "laravel-fractal", 7 | "laravel", 8 | "fractal", 9 | "lumen", 10 | "api", 11 | "transform" 12 | ], 13 | "homepage": "https://github.com/spatie/laravel-fractal", 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "Freek Van der Herten", 18 | "email": "freek@spatie.be", 19 | "homepage": "https://spatie.be", 20 | "role": "Developer" 21 | } 22 | ], 23 | "require": { 24 | "php": "^8.0", 25 | "illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0", 26 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", 27 | "league/fractal": "^0.20.1|^0.20", 28 | "nesbot/carbon": "^2.63|^3.0", 29 | "spatie/fractalistic": "^2.9.5|^2.9", 30 | "spatie/laravel-package-tools": "^1.11" 31 | }, 32 | "require-dev": { 33 | "ext-json": "*", 34 | "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", 35 | "pestphp/pest": "^1.22|^2.34|^3.0" 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Spatie\\Fractal\\": "src" 40 | }, 41 | "files": [ 42 | "src/helpers.php" 43 | ] 44 | }, 45 | "autoload-dev": { 46 | "psr-4": { 47 | "Spatie\\Fractal\\Test\\": "tests" 48 | } 49 | }, 50 | "scripts": { 51 | "test": "vendor/bin/pest" 52 | }, 53 | "config": { 54 | "sort-packages": true, 55 | "allow-plugins": { 56 | "pestphp/pest-plugin": true 57 | } 58 | }, 59 | "extra": { 60 | "laravel": { 61 | "providers": [ 62 | "Spatie\\Fractal\\FractalServiceProvider" 63 | ], 64 | "aliases": { 65 | "Fractal": "Spatie\\Fractal\\Facades\\Fractal" 66 | } 67 | } 68 | }, 69 | "minimum-stability": "dev", 70 | "prefer-stable": true 71 | } 72 | -------------------------------------------------------------------------------- /config/fractal.php: -------------------------------------------------------------------------------- 1 | '', 10 | 11 | /* The default paginator to be used when performing a transformation. It 12 | * may be left empty to use Fractal's default one. This can either be a 13 | * string or a League\Fractal\Paginator\PaginatorInterface subclass. 14 | */ 15 | 'default_paginator' => '', 16 | 17 | /* 18 | * League\Fractal\Serializer\JsonApiSerializer will use this value 19 | * as a prefix for generated links. Set to `null` to disable this. 20 | */ 21 | 'base_url' => null, 22 | 23 | /* 24 | * If you wish to override or extend the default Spatie\Fractal\Fractal 25 | * instance provide the name of the class you want to use. 26 | */ 27 | 'fractal_class' => Spatie\Fractal\Fractal::class, 28 | 29 | 'auto_includes' => [ 30 | 31 | /* 32 | * If enabled Fractal will automatically add the includes who's 33 | * names are present in the `include` request parameter. 34 | */ 35 | 'enabled' => true, 36 | 37 | /* 38 | * The name of key in the request to where we should look for the includes to include. 39 | */ 40 | 'request_key' => 'include', 41 | ], 42 | 43 | 'auto_excludes' => [ 44 | 45 | /* 46 | * If enabled Fractal will automatically add the excludes who's 47 | * names are present in the `exclude` request parameter. 48 | */ 49 | 'enabled' => true, 50 | 51 | /* 52 | * The name of key in the request to where we should look for the excludes to exclude. 53 | */ 54 | 'request_key' => 'exclude', 55 | ], 56 | 57 | 'auto_fieldsets' => [ 58 | 59 | /* 60 | * If enabled Fractal will automatically add the fieldsets who's 61 | * names are present in the `fields` request parameter. 62 | * 63 | * NOTE: This feature does not work if the "resource name" is not set. 64 | */ 65 | 'enabled' => false, 66 | 67 | /* 68 | * The name of key in the request, where we should look for the fieldsets to parse. 69 | */ 70 | 'request_key' => 'fields', 71 | ], 72 | ]; 73 | -------------------------------------------------------------------------------- /src/Console/Commands/TransformerMakeCommand.php: -------------------------------------------------------------------------------- 1 | get($requestKey)) { 42 | $fractal->parseIncludes($include); 43 | } 44 | } 45 | 46 | if (config('fractal.auto_excludes.enabled')) { 47 | $requestKey = config('fractal.auto_excludes.request_key'); 48 | 49 | if ($exclude = app('request')->get($requestKey)) { 50 | $fractal->parseExcludes($exclude); 51 | } 52 | } 53 | 54 | if (config('fractal.auto_fieldsets.enabled')) { 55 | $requestKey = config('fractal.auto_fieldsets.request_key'); 56 | 57 | if ($fieldsets = app('request')->get($requestKey)) { 58 | $fractal->parseFieldsets($fieldsets); 59 | } 60 | } 61 | 62 | if (empty($serializer)) { 63 | $serializer = config('fractal.default_serializer'); 64 | } 65 | 66 | if ($data instanceof LengthAwarePaginator) { 67 | $paginator = config('fractal.default_paginator'); 68 | 69 | if (empty($paginator)) { 70 | $paginator = IlluminatePaginatorAdapter::class; 71 | } 72 | 73 | $fractal->paginateWith(new $paginator($data)); 74 | } 75 | 76 | if (empty($serializer)) { 77 | return $fractal; 78 | } 79 | 80 | if ($serializer instanceof SerializerAbstract) { 81 | return $fractal->serializeWith($serializer); 82 | } 83 | 84 | if ($serializer instanceof Closure) { 85 | return $fractal->serializeWith($serializer()); 86 | } 87 | 88 | if ($serializer == JsonApiSerializer::class) { 89 | $baseUrl = config('fractal.base_url'); 90 | 91 | return $fractal->serializeWith(new $serializer($baseUrl)); 92 | } 93 | 94 | return $fractal->serializeWith(new $serializer()); 95 | } 96 | 97 | public function respond( 98 | callable|int $statusCode = 200, 99 | callable|array $headers = [], 100 | callable|int $options = 0 101 | ): JsonResponse { 102 | $response = new JsonResponse(); 103 | 104 | $response->setData($this->createData()->toArray()); 105 | 106 | if (is_int($statusCode)) { 107 | $statusCode = function (JsonResponse $response) use ($statusCode) { 108 | return $response->setStatusCode($statusCode); 109 | }; 110 | } 111 | 112 | if (is_array($headers)) { 113 | $headers = function (JsonResponse $response) use ($headers) { 114 | return $response->withHeaders($headers); 115 | }; 116 | } 117 | 118 | if (is_int($options)) { 119 | $options = function (JsonResponse $response) use ($options) { 120 | $response->setEncodingOptions($options); 121 | 122 | return $response; 123 | }; 124 | } 125 | 126 | if (is_callable($options)) { 127 | $options($response); 128 | } 129 | 130 | if (is_callable($statusCode)) { 131 | $statusCode($response); 132 | } 133 | 134 | if (is_callable($headers)) { 135 | $headers($response); 136 | } 137 | 138 | return $response; 139 | } 140 | 141 | public function __call($name, array $arguments) 142 | { 143 | if (static::hasMacro($name)) { 144 | return $this->macroCall($name, $arguments); 145 | } 146 | 147 | return parent::__call($name, $arguments); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/FractalServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('laravel-fractal') 16 | ->hasConfigFile() 17 | ->hasCommand(TransformerMakeCommand::class); 18 | } 19 | 20 | public function packageBooted() 21 | { 22 | Collection::macro('transformWith', function ($transformer) { 23 | return fractal($this, $transformer); 24 | }); 25 | } 26 | 27 | public function packageRegistered() 28 | { 29 | $this->app->singleton('fractal', function ($app, $arguments) { 30 | return fractal(...$arguments); 31 | }); 32 | 33 | $this->app->alias('fractal', Fractal::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/helpers.php: -------------------------------------------------------------------------------- 1 |