PHPackages                             grabmy/laravel-api-builder - 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. grabmy/laravel-api-builder

ActiveLibrary

grabmy/laravel-api-builder
==========================

A database and API generator for Laravel

0.2.1(7y ago)033PHPPHP &gt;=5.3.0

Since May 14Pushed 4y agoCompare

[ Source](https://github.com/grabmy/laravel-api-builder)[ Packagist](https://packagist.org/packages/grabmy/laravel-api-builder)[ RSS](/packages/grabmy-laravel-api-builder/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (1)Versions (6)Used By (0)

Laravel API Builder
===================

[](#laravel-api-builder)

A Laravel database and API generator.

Author: Thierry DE LAPEYRE

Features
--------

[](#features)

- Generate table migration file, controller file, model file and add the routes
- One artisan command to generate everything with logs
- Fetch the foreign table record or list of records linked to your table
- Validate fields and return comprehensive errors
- Separate the table constraints and sort the table creation to prevent migration errors

Requires
--------

[](#requires)

- PHP &gt;= 7
- Laravel &gt;= 5.5

Install
-------

[](#install)

```
composer require grabmy/laravel-api-builder
```

Additional artisan commands must appear when you type:

```
php artisan list
```

The artisan command is "make:api" and you must give the path of a JSON configuration file as a parameter. The optional verbose -v parameter can show more logs.

```
php artisan make:api ./api.json -v
```

Quick start
-----------

[](#quick-start)

Create a configuration file "api.json" in the root folder of your Laravel project:

```
{
  "tables": {
    "article": {
      "fields": {
        "id": "increments",
        "name": "string|required|min:2",
        "description": "string:200|nullable",
        "published": "bool|default:0"
      },
      "api": {
        "endpoint": "article",
        "methods": ["GET", "POST", "PUT", "DELETE"]
      }
    }
  }
}
```

In this example, we define a simple table and API behavior. A table will be created with an integer incrementing "id", a string "name", a string "description" with length 200 and a boolean "published" with default false (0).

To boostrap your table migration and create all the files for the API in your project, you must run a command.

> **WARNING**: If you already have a model, controller or migration file with the same filenames, the files will be overwritten.

```
php artisan make:api ./api.json
```

If everything works, you can see the files generated in green. You still have to run the migration that creates the table in your database.

> **WARNING**: the basic migrate command will also destroy and recreate other tables you have in the migration of your project

```
php artisan migrate fresh
```

Assuming your project is accessible at "", you can now:

- Get all content of the table article with:
    GET
- Get just one item of the table article by its id:
    GET [http://127.0.0.1:8000/api/article/{id}](http://127.0.0.1:8000/api/article/%7Bid%7D)
- Create an article with a name, description and published values in JSON body:
    POST
- Update an article with the modified values in JSON body:
    PUT [http://127.0.0.1:8000/api/article/{id}](http://127.0.0.1:8000/api/article/%7Bid%7D)
- Delete an article:
    DELETE [http://127.0.0.1:8000/api/article/{id}](http://127.0.0.1:8000/api/article/%7Bid%7D)

Configuration file
------------------

[](#configuration-file)

The configuration file contains the definition of the tables and the behavior of the API. Each tables have their fields definition.

Multiple tables:

```
{
  "tables": {
    "article": {
      ...
    },
    "category": {
      ...
    },
    "user": {
      ...
    }
  }
}
```

Multiple fields for each table:

```
{
  "tables": {
    "article": {
      "fields": {
        "id": "integer",
        "name": "string",
        "description": "string",
        "content": "text"
      }
    }
  }
}
```

You can have multiple options for a field. Each options are separated by the character pipe "|". The main option is the type of the field, which I usually put first (it's easier to find).

Multiple options:

```
{
  "tables": {
    "product": {
      "fields": {
        "id": "uuid|primary",
        "name": "string|required",
        "description": "text|nullable",
        "quantity": "integer"
      }
    }
  }
}
```

An option can have some additional parameters. Each parameters are separated by the character semicolon ":".

Options with multiple parameters:

```
{
  ...
        "description": "string:200",
        "published": "bool|default:0",
        "category_id": "integer|link:category:id|nullable"
  ...
  }
```

The available requests
----------------------

[](#the-available-requests)

### Getting the record list

[](#getting-the-record-list)

Url: GET /api/endpoint

In our example if we have two articles, GET  will result:

Status code: 200

Body:

```
[
  {
    "id": 1,
    "name": "First article",
    "description": "This is my first article",
    "content": "..."
  },
  {
    "id": 2,
    "name": "Aviation and aerospace",
    "description": "AS9102 is the Aerospace Standard",
    "content": "..."
  }
]
```

### Getting one record

[](#getting-one-record)

Url: GET /endpoint/{id}

In our example, GET  will result:

Status code: 200

Body:

```
{
  "id": 1,
  "name": "First article",
  "description": "This is my first article",
  "content": "..."
}
```

### Creating a record

[](#creating-a-record)

@TODO

### Updating a record

[](#updating-a-record)

@TODO

### Deleting a record

[](#deleting-a-record)

@TODO

### Errors

[](#errors)

@TODO

Field types
-----------

[](#field-types)

TypeDescriptionParametersstringJust a stringoptional lengthtextLong textintIntegerboolBooleanfloatA float numberuuidAn UUIDincrementsAn incrementing integerone-to-manyA list of records from another tableTable, fieldmany-to-manyA list of records from another tableTable, field### UUID

[](#uuid)

If the field has an UUID type and is primary, the API will generate an UUID on POST creation. If the UUID field is not primary, on POST creation and PUT update, the API will automatically check if the passed string is a valid UUID.

### Increments

[](#increments)

@TODO

### List

[](#list)

@TODO

Other options
-------------

[](#other-options)

OptionDescriptionParametersmaxCheck the maximum lengthLengthminCheck the minimum lengthLengthtypeCheck the typeTyperequiredCheck if a value existsnullableField value can be null and optionaldefaultSet the default valueValueprimarySet the field as primary keyomitDon't return the field value in APIone-to-oneLink the foreign key to another tabletable, fieldasReturn this field value with another namecascadeDelete record if foreign record is deletedtype### Type option

[](#type-option)

Return an error if the JSON don't have the correct type on POST creation and PUT update. List of types:

- integer
- float
- string
- UUID

```
{
  ...
    "name": "string|type:string",
    "number": "integer|type:integer",
    "valid": "boolean|type:boolean"
  ...
}
```

### One to many

[](#one-to-many)

@TODO

### Cascade

[](#cascade)

The cascade option must be puts in one-to-one or one-to-many fields.

```
{
  "tables": {
    "order": {
      "fields": {
        "product_id": "integer|one-to-one:product:id|cascade",
        "categories": "one-to-many:category:order_id|cascade",
        "image": "file|cascade",
  ...
}
```

If a record from table order is deleted, the previous API config will:

- Delete a record from table product if order.product\_id is set
- Delete a list of records from table category if category records are linked to this order record
- Delete the file path image if it exists

API configuration
-----------------

[](#api-configuration)

### Endpoint

[](#endpoint)

@TODO

### Fetch

[](#fetch)

The fetch feature is a powerfull feature that allows you to tell the API to fetch records or array of records from other tables.

In the fetchable parameter:

- Set a field value to true will fetch this field record and every records in it
- Set a field value to false will only fetch the field record but not the records in it
- No field or set the field to an empty object will not fetch the field record

The default value for the fetchable parameter is true.

For example with this configuration:

```
{
  "tables": {
    "article": {
      "fields": {
        "id": "increments",
        "name": "string|required|min:2",
        "category_id": "integer|link:category:id|as:category",
        "websites": "list:website:article_id"
      },
      "api": {
        "endpoint": "article",
        "fetchable": true
      }
    }
  }
}
```

Here, we have a link to a record of the "category" table and a list of records of the "website" table. Setting "fetchable" to true will fetch all fields linked to our table (type "list" or option "link").

The "as" option is mandatory with the "link" option. It means the category record will be placed in a field with the name "category" instead of "category\_id". The "websites" field is a list, so it will get an array of records from the "website" table where article\_id is set to the value of the id of the article.

Now, when we are getting one article record:

```
{
  "id": 1,
  "name": "First article",
  "category": {
    "id": 5,
    "name": "Dummy",
    "tag_id": 3
  },
  "websites": [
    {
      "id": 1,
      "url": "http://www.mywebsite.com/"
    },
    {
      "id": 2,
      "url": "https://www.google.com/"
    }
  ]
}
```

If we set the fetchable parameter to false, we get the article record without fetching any linked record in it.

```
{
  ...
        "fetchable": false
  ...
}
```

Our article from the API becomes flat:

```
{
  "id": 1,
  "name": "First article",
  "category_id": 5,
}
```

We don't see the "websites" field because it is not saved field in the database, so it will be available only if the websites records are fetched. We see now the "category\_id" field which is not filtered out.

You can also set the fetchable parameter to just fetch "category" in our article and fetch everything in it but not fetching "websites". So the "tag\_id" the category record becomes a record as we can imagine it's a link to a tag table.

```
{
  ...
        "fetchable": {
          "category": true
        }
  ...
}
```

The category is fetched and every field that can be fetched in it:

```
{
  "id": 1,
  "name": "First article",
  "category": {
    "id": 5,
    "name": "Dummy",
    "tag": {
      "code": "DUMMY",
      "searchable": true
    }
  }
}
```

You can set the API result as you want and go as deep as you like without creating an infinite loop. Be aware that the more you fetch records from other tables, the slower your API will be, especially if you fetch in an array.

### Fetch POST and PUT option

[](#fetch-post-and-put-option)

@TODO

### Methods

[](#methods)

@TODO

What this API generator doesn't do
----------------------------------

[](#what-this-api-generator-doesnt-do)

- Table with multiple fields as primary key
- Change the path of generated files (models, controllers ...)

TODO
----

[](#todo)

- Save and restore database in JSON files
- Add an error on wrong api methods
- Add an error if "link" dont have an "as" option
- Add type check for email, ip, url
- Add field type json

DONE
----

[](#done)

- Cascade deletion
- Add field type json
- Fix wrong fields on update and fillable
- Add "many-to-many" type
- Make a default sort number for tables

PENDING
-------

[](#pending)

- Add where clause to one-to-many and one-to-one fields
- Change migration, model, controller, api route path in config
- Change namespace and class extends in config

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 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 ~38 days

Total

4

Last Release

2805d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3e082b1d8b5103094d8b4a7128f7fd950e2256a1751d1b6659bd8557b2a34caf?d=identicon)[grabmy](/maintainers/grabmy)

---

Top Contributors

[![grabmy](https://avatars.githubusercontent.com/u/38759136?v=4)](https://github.com/grabmy "grabmy (17 commits)")

### Embed Badge

![Health badge](/badges/grabmy-laravel-api-builder/health.svg)

```
[![Health](https://phpackages.com/badges/grabmy-laravel-api-builder/health.svg)](https://phpackages.com/packages/grabmy-laravel-api-builder)
```

###  Alternatives

[badaso/core

The API &amp; platform builder, build your apps 10x faster even more, it's open source &amp; 100% free !

1.3k16.2k10](/packages/badaso-core)[binarycabin/laravel-uuid

A wrapper for webpatser/laravel-uuid with additional integration

86589.4k](/packages/binarycabin-laravel-uuid)[exceedone/exment

Management for Product, Client, Contracts, Subscription, ...

27937.6k](/packages/exceedone-exment)[alsofronie/eloquent-uuid

A Laravel Eloquent Model trait for using UUID's as primary keys

93332.8k10](/packages/alsofronie-eloquent-uuid)[lecturize/laravel-addresses

Simple address and contact management for Laravel.

20164.1k](/packages/lecturize-laravel-addresses)[lecturize/laravel-taxonomies

Simple, nestable Terms &amp; Taxonomies (similar to WordPress) for Laravel.

10310.5k](/packages/lecturize-laravel-taxonomies)

PHPackages © 2026

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