PHPackages                             macropay-solutions/laravel-crud-wizard-free - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. macropay-solutions/laravel-crud-wizard-free

ActiveLibrary[Admin Panels](/categories/admin)

macropay-solutions/laravel-crud-wizard-free
===========================================

Free library for laravel/lumen crud operations including url query language

8.0.1(2mo ago)12178↓100%12MITPHPPHP ^8.0CI passing

Since Mar 23Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/macropay-solutions/laravel-crud-wizard-free)[ Packagist](https://packagist.org/packages/macropay-solutions/laravel-crud-wizard-free)[ RSS](/packages/macropay-solutions-laravel-crud-wizard-free/feed)WikiDiscussions production Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (95)Used By (2)Security (1)

laravel-crud-wizard-free - MaravelQL
====================================

[](#laravel-crud-wizard-free---maravelql)

[![1_9gPPofZEi8eKSFMrEMIF5w7](https://private-user-images.githubusercontent.com/153634237/562817973-0211be8f-c274-4240-ba80-f4f329af9fd5.webp?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzQxODY5NTIsIm5iZiI6MTc3NDE4NjY1MiwicGF0aCI6Ii8xNTM2MzQyMzcvNTYyODE3OTczLTAyMTFiZThmLWMyNzQtNDI0MC1iYTgwLWY0ZjMyOWFmOWZkNS53ZWJwP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMjJUMTMzNzMyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZGNiZjcyMTdiYmE1YjRlNTZmMjIxMzUzYTY0NWYyMTVkYzA1ZTZmZjRlNTVkOWQxOTdmMzcxYjViMDJiMzc4OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.JuaG9hyUSSsMXVj1llh-2qyZ2zvAvIHNmrVof-y8V-A)](https://private-user-images.githubusercontent.com/153634237/562817973-0211be8f-c274-4240-ba80-f4f329af9fd5.webp?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzQxODY5NTIsIm5iZiI6MTc3NDE4NjY1MiwicGF0aCI6Ii8xNTM2MzQyMzcvNTYyODE3OTczLTAyMTFiZThmLWMyNzQtNDI0MC1iYTgwLWY0ZjMyOWFmOWZkNS53ZWJwP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMjJUMTMzNzMyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZGNiZjcyMTdiYmE1YjRlNTZmMjIxMzUzYTY0NWYyMTVkYzA1ZTZmZjRlNTVkOWQxOTdmMzcxYjViMDJiMzc4OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.JuaG9hyUSSsMXVj1llh-2qyZ2zvAvIHNmrVof-y8V-A)

[![Build Status](https://github.com/macropay-solutions/laravel-crud-wizard-free/actions/workflows/tests.yml/badge.svg)](https://github.com/macropay-solutions/laravel-crud-wizard-free/actions)[![Total Downloads](https://camo.githubusercontent.com/57c7dc892464b19c9acdbd7f1c25db652ad3c9c4bb33933b7237cb24fe602bed/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d6163726f7061792d736f6c7574696f6e732f6c61726176656c2d637275642d77697a6172642d66726565)](https://packagist.org/packages/macropay-solutions/laravel-crud-wizard-free)[![Latest Stable Version](https://camo.githubusercontent.com/7d292f14175d8794f231c00f4f9cb5c610ba2e9d76505be374c10eb879e4006f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6163726f7061792d736f6c7574696f6e732f6c61726176656c2d637275642d77697a6172642d66726565)](https://packagist.org/packages/macropay-solutions/laravel-crud-wizard-free)[![License](https://camo.githubusercontent.com/5d318a97543fc12f6f64831e05743e855f1363efe4cb69adcf14357691186e8a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6d6163726f7061792d736f6c7574696f6e732f6c61726176656c2d637275642d77697a6172642d66726565)](https://packagist.org/packages/macropay-solutions/laravel-crud-wizard-free)

This is a stripped down version from the paid version [Maravel rest wizard](https://github.com/macropay-solutions/laravel-lumen-crud-wizard) (for laravel/lumen &gt;= 8 and maravelith/maravel &gt;= 10).

Features: Freemium vs Pro High Level Comparison
-----------------------------------------------

[](#features-freemium-vs-pro-high-level-comparison)

Feature / OperationMaravelQL Freemium (`laravel-crud-wizard-free`)MaravelQL Pro (`maravel-rest-wizard`)**Data Engine Support**✅ SQL Databases Only✅ SQL + **Elasticsearch (via SQL Driver)****Create Resource**✅ Standard Create✅ Standard Create**Read / Get Resource**✅ Single retrieve with relations✅ Single retrieve with relations**Update Resource**✅ Standard Update✅ Update, **Upsert**, &amp; **Incrementing** (`++x.xx`)**Delete Resource**✅ Standard Delete✅ Standard Delete**Bulk Delete Resource**❌✅ Via `list({filters})->delete()`**List Resource**✅ Standard List✅ Standard List**List Relation as Resource**❌✅ (e.g., `GET /{resource}/{pk}/{relation}?`)**Composite Primary Key**✅ Supported (e.g., `12_35`)✅ Supported (e.g., `12_35`)**Default Filtering (`=`)**✅ **Strict Match** (Exact equality)✅ **Starts With** (Prefix match by default)**Advanced Filters**❌✅ `equals`, `in`, `not in`, `from`, `to`, `contains`, `notContains`, `is null`, `is not null`**Response Formats**✅ JSON✅ JSON, **JSONL** (`limit=-1`), **StreamedJsonResponse****Pagination**✅ LengthAware, Simple, Cursor✅ All Free + `limit=0` (Count only)**Sorting**✅ Multi-column sorting✅ Multi-column &amp; **Aggregate Sorting****Relational Loading**✅ `withRelations`, `withRelationsCount`, `withRelationsExistence`✅ All Free + `with appends`, `with distinct relations`**Relation Constraints**❌✅ `has relations`, `doesn't have relations`, `has distinct relations`**Custom Deep Relations**❌✅ `HasManySelfThroughSelf`, `HasManyThrough2LinkTables`, `HasManyThrough3LinkTables`, `HasOneSelfThroughSelf`, `HasOneThrough2LinkTables`, `HasOneThrough3LinkTables`**Aggregations**❌✅ Sums, Averages, Minimums, Maximums, Distinct column(s) fetching**Elasticsearch KPIs**❌✅ **Real-time Aggregations** on ES Indexes**Group By &amp; Subtotals**❌✅ Group By, Sub-totals, Sub-averages, Sub-minimums, Sub-maximums**Group Constraints**❌✅ Count Distinct, Group Count, Havings (including relation counts)**DB Protection / Guardrails**❌✅ API Timeout blocks (MySQL/MariaDB), MVCC `select count(*)` slow query fix#### The Freemium Advantage

[](#the-freemium-advantage)

With the free version, you can instantly pull resources, load their relationships, check if relationships exist, and paginate through large datasets.

- *Example (Free):* `GET /operations?currency=EUR&withRelationsCount[]=products` (Get all operations where currency exactly equals EUR and include the count of related products).

#### The Pro Advantage

[](#the-pro-advantage)

When your data logic gets complex, the paid version of MaravelQL replaces hundreds of lines of Eloquent sub-queries, aggregations, and groupings. It also includes built-in safeguards against API-triggered database blocking.

- *Example (Pro):* `GET /operations?currency[in][]=EUR&currency[in][]=USD&withSum=value` (Get operations where currency is IN \[EUR, USD\] and include the total sum of their values).

Url query language lib for RESTful CRUD (micro) services using Lumen/Laravel 8-9-10-11-12 and Maravelith/Maravel &gt;=10
------------------------------------------------------------------------------------------------------------------------

[](#url-query-language-lib-for-restful-crud-micro-services-using-lumenlaravel-8-9-10-11-12-and-maravelithmaravel-10)

### This is not just another CRUD lib!

[](#this-is-not-just-another-crud-lib)

It has built in filtering capabilities that can be used for listing but also for mass deleting, so it could be called a CRU**F**D (create, read, update, **filter** and delete) lib instead.

[Demo page for listing](https://laravel-crud-wizard.com/laravel-12-free/laravel-lumen-crud-wizard#operations)

[Demo integration](https://github.com/macropay-solutions/laravel-crud-wizard-decorator-free-demo/commits/production/)

I. [Install](#i-install)

II. [Start using it](#ii-start-using-it)

III. [Crud routes](#iii-crud-routes)

III.1. [Create resource](#iii1-create-resource)

III.2. [Get resource](#iii2-get-resource)

III.3. [List filtered resource](#iii3-list-filtered-resource)

III.4. [Update resource (or create)](#iii4-update-resource-or-create)

III.5. [Delete resource](#iii5-delete-resource)

I. Install
----------

[](#i-install)

```
composer require macropay-solutions/laravel-crud-wizard-free

```

II. Start using it
------------------

[](#ii-start-using-it)

**NOTE**

The lib contains a backward compatible fix for this issue [laravel/framework#51825](https://github.com/laravel/framework/issues/51825) (compatible with the fix from Maravelith/Maravel)

This will not cover the cases when the relation is instantiated in the model without calling the functions from the HasRelationship trait (or to be more precise, from HasCleverRelationships trait)! Those cases will still have this issue.

To cover also those cases in Laravel/Lumen (Maravel/Maravelith does not need this), for example for HasManyThrough use in model anonymous class:

```
      return new class (
          $query,
          $farParent,
          $throughParent,
          $firstKey,
          $secondKey,
          $localKey,
          $secondLocalKey,
          $this // this is crucial
      ) extends HasManyThrough {
          public function __construct(
              Builder $query,
              Model $farParent,
              Model $throughParent,
              string $firstKey,
              string $secondKey,
              string $localKey,
              string $secondLocalKey,
              BaseModel $resourceModel
          ) {
              $this->setConstraintsStaticFlag($resourceModel);

              return parent::__construct(
                  $query,
                  $farParent,
                  $throughParent,
                  $firstKey,
                  $secondKey,
                  $localKey,
                  $secondLocalKey
              );
          }
      };
```

Register

\\MacropaySolutions\\LaravelCrudWizard\\Providers\\CrudProvider in Maravel/Maravelith or \\MacropaySolutions\\LaravelCrudWizard\\Providers\\CrudProviderLaravelLumen in Lumen/Laravel

\\MacropaySolutions\\LaravelCrudWizard\\Providers\\ValidationServiceProvider instead of Illuminate\\Validation\\ValidationServiceProvider::class if you are using **illuminate/validation &lt; 11.44.1 to solve CVE-2025-27515 security issue and [laravel/framework#41734 (comment)](https://github.com/laravel/framework/issues/41734#issuecomment-3127680521) issue** (fixed in Maravel/Maravelith, so it is not needed). Note that after this any present key from the request will be validated even if it is empty string. See

Create a constant in your code

```
    class DbCrudMap
    {
        public const MODEL_FQN_TO_CONTROLLER_MAP = [
            BaseModelChild::class => ResourceControllerTraitIncludedChild::class,
            ...
        ];
    }
```

Use  to generate the model, service and controller or extend:

- BaseModel for Maravel/Maravelith or BaseModelLaravelLumen (it needs datetime NOT timestamp for created\_at and updated\_at columns)
- BaseResourceService

Create a Controller that uses ResourceControllerTrait and call `$this->init();` from its \_\_construct.

Optionally if you don't want to expose some models as resources but, you want to expose them as relation on an exposed resource then define in your Base Controller or ResourceController:

```
    protected array $relatedModelFqnToControllerMap = [
        RelatedBaseModelChild::class => RelatedResourceControllerTraitIncludedChild::class,
    ];
```

**Active Record Segregation of Properties:** for model attributes(columns) autocomplete and to avoid clashes with the model properties or relations:

- extend BaseModelAttributes following the same FQN structure as the parent's:

    ```
    \App\Models\ChildBaseModel paired with \App\Models\Attributes\ChildBaseModelAttributes
    \App\Models\Folder\ChildBaseModel paired with \App\Models\Folder\Attributes\ChildBaseModelAttributes

    ```
- add in its class dock block using **@property** all the models properties/attributes/columns
- add in the model's class dock block **@property ChildBaseModelAttributes $a** and **@mixin ChildBaseModelAttributes**
- use `$model->a->` instead of `$model->` *(this will work without autocomplete even if you don't do the above)*

**Active Record Segregation of Properties:** for model relation autocomplete and to avoid clashes with the model properties and attributes(columns):

- extend BaseModelRelations following the same FQN structure as the parent's:

    ```
    \App\Models\ChildBaseModel paired with \App\Models\Attributes\ChildBaseModelRelations
    \App\Models\Folder\ChildBaseModel paired with \App\Models\Folder\Attributes\ChildBaseModelRelations

    ```
- add in its class dock block using **@property-read** all the models relations
- add in the model's class dock block **@property ChildBaseModelRelations $r** and **@mixin ChildBaseModelRelations**
- use `$model->r->` instead of `$model->` *(this will work without autocomplete even if you don't do the above)*
- BaseModelFrozenAttributes can be also extended on the same logic and used for model read only situations - DTO without setters (Reflection or Closure binding usage will retrieve/set protected stdClass not Model - but the model can be retrieved from DB by its primary key that is readable in this frozen model):

```
#OperationModel example for BaseModelFrozenAttributes
    public function getFrozen(): OperationFrozenAttributes
    {
        return parent::getFrozen(); // this is needed for autocompletion and will include also the loaded relations
        // or
        return new OperationFrozenAttributes((clone $this)->forceFill($this->toArray()));
        // or just attributes without loaded relations
        return new OperationFrozenAttributes((clone $this)->forceFill($this->attributesToArray()));
    }
```

```
#OperationService example for BaseModelAttributes and BaseModelFrozenAttributes
    public function someFunction(): void
    {
         // BaseModelAttributes
         echo $this->model-a->value; // has autocomplete - will print for example 1
         echo $this->model-a->value = 10; // has autocomplete - will print 10
         echo $this->model->value; // has autocomplete - will print 10

         // BaseModelFrozenAttributes
         $dto = $this->model->getFrozen();
         echo $dto->client_id; // has autocomplete - will print for example 1
         $dto->client_id = 4; // Exception: Dynamic properties are forbidden.

         if (isset($dto->client)) {
             /** @var ClientFrozenAttributes $client */
             // $client will be an stdClass that has autocomplete like a ClientFrozenAttributes
             $client = $dto->client;
             echo $client->name; // has autocomplete - will print for example 'name'
             $client->name = 'text'; // NO Exception
             echo $client->name; // will print 'text'
             // $client changes can happen, but they will not be persisted in the $dto ($client is a stdClass clone)
             echo $dto->client->name; // will print 'name'
             echo $dto->client->name = 'text'; // will print 'text'
             echo $dto->client->name; // will print 'name'
         }

         foreach (($dto->products ?? []) as $k => $product) {
             /** @var ProductFrozenAttributes $product */
             // $product will be an stdClass that has autocompletes like a ProductFrozenAttributes
             echo $product->value; // has autocomplete - will print for example 1
             $product->value = 2; // NO Exception
             echo $product->value; // will print 2
             // $product changes can happen, but they will not be persisted in the $dto ($product is a stdClass clone)
             echo $dto->products[$k]->value; // will print 1
             echo $dto->products[$k]->value = 2; // will print 2
             echo $dto->products[$k]->value; // will print 1
         }
    }
```

Add this new resource to the above map.

Register the crud routes in your application using (for example in Laravel/Maravelith)

```
    try {
        foreach (
            ResourceHelper::getResourceNameToControllerFQNMap(DbCrudMap::MODEL_FQN_TO_CONTROLLER_MAP) as $resource => $controller
        ) {
            Route::get('/' . $resource, [$controller, 'list'])->name($resource . '.list');
            Route::post('/' . $resource . '/l/i/s/t', [$controller, 'list'])->name($resource . '.post_list');
            Route::post('/' . $resource, [$controller, 'create'])->name($resource . '.create');
            Route::put('/' . $resource . '/{identifier}', [$controller, 'update'])->name($resource . '.update');
            Route::get('/' . $resource . '/{identifier}', [$controller, 'get'])->name($resource . '.get');
            Route::delete('/' . $resource . '/{identifier}', [$controller, 'delete'])
                ->name($resource . '.delete' . $resource);
            // Route::get('/' . $resource . '/{identifier}/{relation}', [$controller, 'listRelation'])
            //  ->name($resource . '.listRelated'); // paid version only
            // Route::post('/' . $resource . '/{identifier}/{relation}/l/i/s/t', [$controller, 'listRelation'])
            //  ->name($resource . '.post_listRelated'); // paid version only
            Route::get('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [$controller, 'getRelated'])
                ->name($resource . '.getRelated');
            Route::put('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [$controller, 'updateRelated'])
                ->name($resource . '.updateRelated');
            Route::delete('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [
                $controller,
                'deleteRelated'
            ])->name($resource . '.deleteRelated');

        }
    } catch (Throwable $e) {
        \Illuminate\Support\Facades\Log::error($e->getMessage());
    }
```

for example for Lumen/Maravel:

```
    try {
        foreach (
            ResourceHelper::getResourceNameToControllerFQNMap(
                DbCrudMap::MODEL_FQN_TO_CONTROLLER_MAP
            ) as $resource => $controllerFqn
        ) {
            $controllerFqnExploded = \explode('\\', $controllerFqn);
            $controller = \end($controllerFqnExploded);
            //$router->get('/' . $resource . '/{identifier}/{relation}', [
            //    'as' => $resource . '.listRelated',
            //    'uses' => $controller . '@listRelation',
            //]); // paid version only
            $router->get('/' . $resource, [
                'as' => $resource . '.list',
                'uses' => $controller . '@list',
            ]);
            //$router->post('/' . $resource . '/{identifier}/{relation}/l/i/s/t', [
            //    'as' => $resource . '.post_listRelated',
            //    'uses' => $controller . '@listRelation',
            //]); // paid version only
            $router->post('/' . $resource . '/l/i/s/t', [
                'as' => $resource . '.post_list',
                'uses' => $controller . '@list',
            ]);
            $router->post('/' . $resource, [
                'as' => $resource . '.create',
                'uses' => $controller . '@create',
            ]);
            $router->put('/' . $resource . '/{identifier}', [
                'as' => $resource . '.update',
                'uses' => $controller . '@update',
            ]);
            $router->get('/' . $resource . '/{identifier}', [
                'as' => $resource . '.get',
                'uses' => $controller . '@get',
            ]);
            $router->delete('/' . $resource . '/{identifier}', [
                'as' => $resource . '.delete',
                'uses' => $controller . '@delete',
            ]);

            $router->get('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [
                'as' => $resource . '.getRelated',
                'uses' => $controller . '@getRelated',
            ]);
            $router->put('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [
                'as' => $resource . '.updateRelated',
                'uses' => $controller . '@updateRelated',
            ]);
            $router->delete('/' . $resource . '/{identifier}/{relation}/{relatedIdentifier}', [
                'as' => $resource . '.deleteRelated',
                'uses' => $controller . '@deleteRelated',
            ]);
        }
    } catch (Throwable $e) {
        \Illuminate\Support\Facades\Log::error($e->getMessage());
    }
```

OBS

Set `$returnNullOnInvalidColumnAttributeAccess = false;` in model if you want exception instead of null on accessing invalid model attributes or invalid relations (It also needs error\_reporting = E\_ALL in php ini file).

Set `LIST_UN_HYDRATED_WHEN_POSSIBLE = true` in model if you want to skip eloquent hydration for list db query results; note that setting this to true will not append the primary\_key\_identifier on response. Also if you use casts or any logic that alters (conditionally or not) the attributes of the model, you should leave LIST\_UN\_HYDRATED\_WHEN\_POSSIBLE as false.

Set LIVE\_MODE=false in your .env file for non prod environments.

Use Request::getFiltered macro to sanitize data retrieved from request

```
(string)\request('signature', '');
```

The above will throw Array to string conversion error for query: *?signature\[\]=*The proper way of handling it before:

```
(string)\filter_var(\request('signature', ''), \FILTER_DEFAULT);
```

The new way of handling it:

```
(string)\request()->getFiltered('signature', '');
```

See also [Laravel crud wizard demo](https://github.com/macropay-solutions/laravel-crud-wizard-demo)

### III. Crud routes

[](#iii-crud-routes)

`The identifier can be a primary key or a combination of primary keys with _ between them if the resource has a combined primary key!!!`

see \\MacropaySolutions\\LaravelCrudWizard\\Models\\BaseModel::COMPOSITE\_PK\_SEPARATOR

#### III.1 Create resource

[](#iii1-create-resource)

**POST** /{resource}

headers:

```
  Authorization: Bearer ... // if needed. not coded in this lib

  Accept: application/json

  ContentType: application/json

```

body:

```
  {
     "column_name":"value",
     ...
  }

```

Json Response:

201:

```
{
    "column_name":"value",
    ...
}

```

400:

```
{
    "message": "The given data was invalid.", // or other message
    "errors": {
        "column_name1": [
            "The column name 1 field is required."
        ],
        "column_name_2": [
           "The column name 2 field is required."
        ],
        ...
     }
}

```

The above "errors" are optional and appear only for validation errors while "message" will always be present.

#### III.2 Get resource

[](#iii2-get-resource)

**GET** /{resource}/{identifier}?withRelations\[\]=has\_manyRelation&amp;withRelations\[\]=has\_oneRelation&amp;withRelationsCount\[\]=has\_manyRelation&amp;withRelationsExistence\[\]=has\_manyRelation

**GET** /{resource}/{identifier}/{relation}/{relatedIdentifier}?withRelations\[\]=has\_manyRelation&amp;withRelations\[\]=has\_oneRelation&amp;withRelationsCount\[\]=has\_manyRelation&amp;withRelationsExistence\[\]=has\_manyRelation

headers:

```
  Authorization: Bearer ... // if needed. not coded in this lib

  Accept: application/json

```

Use **POST** LIST requests if the identifier contains **sensitive data**

Json Response:

200:

```
{
    "identifier":"value",
    "column_name":"value",
    ...
    "index_required_on_filtering": [
       "column_name_1",
       "column_name2"
    ],
    "has_oneRelation":{...},
    "has_manyRelation":[
        {
            "id": ...,
            "name": "...",
            "pivot": {
               "key1": 25,
               "key2": 5
            }
        }
    ],
    "has_manyRelation_count": 0,
    "has_manyRelation_exist": false
}

```

400:

```
{
    "message": ...
}

```

The identifier can be composed by multiple identifiers for pivot resources that have composite primary key. Example:/table1-table2-pivot/3\_10

The relations will be retrieved as well when required. The relation keys CAN'T be used for filtering!!!

`index_required_on_filtering` key CAN'T be used for filtering.

`pivot` is optional and appears only on relations that are tied via a pivot.

#### III.3 List filtered resource

[](#iii3-list-filtered-resource)

**GET** /{resource}?page=1&amp;limit=10&amp;column=2&amp;sort\[0\]\[by\]=updated\_at&amp;sort\[0\]\[dir\]=ASC&amp;withRelations\[\]=has\_manyRelation&amp;withRelations\[\]=has\_oneRelation&amp;withRelationsCount\[\]=has\_manyRelation&amp;withRelationsExistence\[\]=has\_manyRelation

**POST** /{resource}/l/i/s/t

**GET** /{resource}/{identifier}/{relation}?... // available only in paid version

**POST** /{resource}/{identifier}/{relation}/l/i/s/t // available only in paid version

Advanced filters and aggregations are available only in the paid version

headers:

```
  Authorization: Bearer ... // if needed. not coded in this lib

  Accept: application/json

  Content-Type: application/json OR application/x-www-form-urlencoded // for POST

```

Body for POST:

```
{"page":"1","limit":"10","column":"2","sort":[{"by":"updated_at","dir":"ASC"}],"withRelations":["has_manyRelation","has_oneRelation"],"withRelationsCount":["has_manyRelation"],"withRelationsExistence":["has_manyRelation"]}

```

OR

```
page=1&limit=10&column=2&sort[0][by]=updated_at&sort[0][dir]=ASC&withRelations[]=has_manyRelation&withRelations[]=has_oneRelation&withRelationsCount[]=has_manyRelation&withRelationsExistence[]=has_manyRelation

```

Use **POST** requests if GET returns this error message: **Request Header Or Cookie Too Large**

or if the filters contain **sensitive data**

Json Response:

200:

```
{
    "index_required_on_filtering": [
       "column_name1",
       "column_name2"
    ],
    "current_page": 1, // not present when cursor is present in request
    "data": [
        {
           "identifier":"value",
           "column_name":"value",
           ...,
          "has_oneRelation":{...},
          "has_manyRelation":[
              {
                  "id": ...,
                  "name": "...",
                  "pivot": {
                     "key1": 25,
                     "key2": 5
                  }
              }
          ],
          "has_manyRelation_count": 0,
          "has_manyRelation_exist": false
        }
    ],
    "from": 1, // not present when cursor is present in request
    "last_page": 1, // not present when cursor is present in request or when simplePaginate is true in controller or present in request
    "per_page": 10,
    "to": 1, // not present when cursor is present in request
    "total": 1, // not present when cursor is present in request or simplePaginate is true in controller or present in request
    "has_more_pages": bool,
    "cursor": "..." // present only when cursor is present in request
}

```

The reserved words / parameters that will be used as query params are:

```
    page,
    limit,
    simplePaginate
    cursor,
    sort,
    withRelations,
    withRelationsCount,
    withRelationsExistence,

```

Defaults:

```
page=1;
limit=15;
simplePaginate is false by default and only its presence is checked in request, not its value
cursor is not defined
sort[][dir]=DESC

```

Obs.

```
index_required_on_filtering key CAN'T be used for filtering.
use ?cursor= for cursor pagination and ?simplePaginate=1 for simplePaginate. Use none of them for length aware paginator.
if \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class is used use ?cursor=1 instead of emtpy string
sort works also on aggregated colums for relation count and existence
withRelations which uses with function does not load morphable relations in laravel/Maravelith. BaseResourceService::addRelationsToExistingModel can be used for those or loadMorph.

```

#### III.4 Update resource (or create)

[](#iii4-update-resource-or-create)

**PUT** /{resource}/{identifier}

**PUT** /{resource}/{identifier}/{relation}/{relatedIdentifier}

headers:

```
  Authorization: Bearer ... // if needed. not coded in this lib

  Accept: application/json

  ContentType: application/json

```

body:

```
  {
     "column_name":"value",
     ...
  }

```

Json Response:

200 | 201:

```
{
    // all resource's fields
}

```

400:

```
{
    "message": "The given data was invalid.", // or other message
    "errors": {
        "column_name": [
           "The column name field is invalid."
        ],
        ...
    }
}

```

The above "errors" are optional and appear only for validation errors while "message" will always be present.

The identifier can be composed by multiple identifiers for pivot resources that have composite primary key (and empty string primary key in their model). Example:/resources/3\_10

Update is not available on some resources.

**UpdateOrCreate** is available on resources that have their model defined with incrementing = false ONLY if the request contains all the keys from the primary key (found also in function getPrimaryKeyFilter).

Update will validate only dirty columns, not all sent columns, meaning the update can be made with all columns of the resource instead of just the changed ones.

#### III.5 Delete resource

[](#iii5-delete-resource)

**DELETE** /{resource}/{identifier}

**DELETE** /{resource}/{identifier}/{relation}/{relatedIdentifier}

headers:

```
  Authorization: Bearer ... // if needed. not coded in this lib

```

Json Response:

204:

```
[]

```

400:

```
{
    "message": ...
}

```

Delete is not available by default.

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance88

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

94

Last Release

64d ago

Major Versions

3.5.6 → 4.0.02025-05-23

4.3.4 → 5.0.02025-10-11

5.1.0 → 6.0.02025-12-25

6.0.1 → 7.0.02026-02-12

7.1.2 → 8.0.02026-03-09

### Community

Maintainers

![](https://www.gravatar.com/avatar/6af9c4a6c1c9fc82963cd8c274cb21a76bc8cf26d47fb39ee186e358160f78a1?d=identicon)[macropay-solutions](/maintainers/macropay-solutions)

---

Top Contributors

[![macropay-solutions](https://avatars.githubusercontent.com/u/153634237?v=4)](https://github.com/macropay-solutions "macropay-solutions (52 commits)")

---

Tags

aggregation-frameworkcrudcrud-apicrud-generatordynamiceloquent-qleloquentqlfilterfiltering-datalaravellumenquery-builderquery-language-processorquery-language-sqlrestful-apirestful-clientrestful-webservicesurl-query-languagelaravellumencrudRESTful APIfreewizardurl-query-language

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/macropay-solutions-laravel-crud-wizard-free/health.svg)

```
[![Health](https://phpackages.com/badges/macropay-solutions-laravel-crud-wizard-free/health.svg)](https://phpackages.com/packages/macropay-solutions-laravel-crud-wizard-free)
```

###  Alternatives

[takielias/tablar-crud-generator

Laravel Tablar Crud Generator based on https://github.com/takielias/tablar

315.6k](/packages/takielias-tablar-crud-generator)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
