Download the PHP package anil/fast-api-crud without Composer
On this page you can find all versions of the php package anil/fast-api-crud. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download anil/fast-api-crud
More information about anil/fast-api-crud
Files in anil/fast-api-crud
Package fast-api-crud
Short Description A powerful Laravel package for building RESTful API CRUD operations with minimal boilerplate. Features pagination, filtering, sorting, soft deletes, permissions, lifecycle hooks, and more.
License MIT
Informations about the package fast-api-crud
Fast API CRUD for Laravel
A powerful Laravel package that provides full-featured CRUD operations with minimal boilerplate. Works for both API (JSON responses) and Web (Blade views) controllers out of the box.
Supports pagination (length-aware, simple, cursor), filtering, sorting, search, soft deletes, Spatie permissions, lifecycle hooks, and much more.
Supports: Laravel 12, 13 | PHP 8.2+
Requires: spatie/laravel-permission ^6.0 or ^7.0
Table of Contents
- Installation
- Quick Start
- Configuration
- API Controller
- Web Controller
- Scaffolding Command
- Query Parameters
- Controller Properties
- Lifecycle Hooks
- Contracts
- Model Traits
- Builder Macros
- Collection Macros
- API Responder
- Helper Functions
- Exceptions
- Permissions
- Routes
- Pagination Utility
- Enums
- Full Example
Installation
Publish the config file (optional):
Quick Start
1. Generate everything with one command
This creates: Model, Migration, Factory, Seeder, Controller, Resource, Store/Update Requests.
2. The generated controller — zero boilerplate
3. Register routes
One line registers the entire CRUD route set via the fastApiResource macro:
This registers:
Prefer to wire routes by hand? That works too:
4. That's it! You now have a fully working CRUD API
Configuration
File: config/fast-api.php
Rename query parameters
Every request key the index reads is configurable, so you can shape the public API your way. For example, to use ?limit=, ?sort=, ?dir=, ?q=:
API Controller (BaseController)
For JSON API endpoints. Returns JsonResponse, JsonResource, and AnonymousResourceCollection.
Constructor
Available Methods
| Method | HTTP | Return Type | Description |
|---|---|---|---|
index() |
GET | AnonymousResourceCollection |
Paginated list |
show($id) |
GET | JsonResource |
Single resource |
store() |
POST | JsonResponse (201) |
Create resource |
update($id) |
PUT | JsonResource\|JsonResponse |
Update resource |
destroy($id) |
DELETE | JsonResponse (204) |
Delete resource |
delete() |
POST | JsonResponse (204) |
Bulk delete via delete_rows array |
changeStatus($id, $column = 'status') |
PUT | JsonResource\|JsonResponse |
Toggle boolean column (0/1) |
updateColumn($id, $column = 'status') |
PUT | JsonResource\|JsonResponse |
Update specific fillable column |
restore($id) |
PUT | JsonResource\|JsonResponse |
Restore soft-deleted |
restoreAll() |
POST | JsonResponse (204) |
Restore all trashed |
permanentDelete($id) |
POST | JsonResponse (204) |
Force delete trashed |
Methods returning JsonResource|JsonResponse return JsonResponse when an exception occurs during the operation.
Example Responses
GET /posts (index):
GET /posts/1 (show):
POST /posts (store — 201 Created):
DELETE /posts/1 (destroy — 204):
Error response (400):
Validation error (422 — handled by Laravel):
Web Controller (BaseWebController)
For Blade/web applications. Returns View and RedirectResponse with flash messages.
Constructor
Available Methods
| Method | HTTP | Return | Description |
|---|---|---|---|
index() |
GET | View |
List page ({viewPrefix}.index) |
create() |
GET | View |
Create form ({viewPrefix}.create) |
store() |
POST | RedirectResponse |
Create, redirect with flash |
show($id) |
GET | View |
Detail page ({viewPrefix}.show) |
edit($id) |
GET | View |
Edit form ({viewPrefix}.edit) |
update($id) |
PUT | RedirectResponse |
Update, redirect with flash |
destroy($id) |
DELETE | RedirectResponse |
Delete, redirect with flash |
delete() |
POST | RedirectResponse |
Bulk delete, redirect |
changeStatus($id) |
PUT | RedirectResponse |
Toggle status, redirect |
restore($id) |
PUT | RedirectResponse |
Restore, redirect |
restoreAll() |
POST | RedirectResponse |
Restore all, redirect |
permanentDelete($id) |
POST | RedirectResponse |
Force delete, redirect |
View Variables
- index:
$posts(or your$collectionName) — paginated collection - show/edit:
$post(or your$resourceName) — single model instance
Customizing Flash Messages
Override any of the message methods in your controller. All return string and work with Laravel's __() translation helper:
Flash messages use session keys from config (fast-api.web.flash_key_success and fast-api.web.flash_key_error).
Overriding Views
Override any method to pass extra data to views:
Blade View Example
Web Routes
Scaffolding Command
Generated files per model:
| File | Path |
|---|---|
| Model | app/Models/Post.php |
| Migration | database/migrations/create_posts_table.php |
| Factory | database/factories/PostFactory.php |
| Seeder | database/seeders/PostSeeder.php |
| Resource | app/Http/Resources/Post/PostResource.php |
| Store Request | app/Http/Requests/Post/StorePostRequest.php |
| Update Request | app/Http/Requests/Post/UpdatePostRequest.php |
| Controller | app/Http/Controllers/PostController.php |
| Views (--web) | resources/views/posts/index.blade.php, create.blade.php, edit.blade.php, show.blade.php |
Query Parameters
The package reads these query parameters automatically:
Filtering
The filters parameter accepts a JSON object. Each key is matched against the model's scopes:
activecallsscopeActive(1)on the modelqueryFiltercallsscopeQueryFilter("search term")
Sorting
sortBy— column name to sort by (default:id)descending—truefor DESC,falsefor ASC (default:true)
If the model implements Sortable, its defaults are used when no sort params are provided.
Pagination
rowsPerPage— records per page (default: 15, max: 100)
Search
If the model implements the Searchable interface, performs a LIKE search across the columns returned by searchableColumns().
Includes (client-driven eager loading)
Passed as an include key inside the filters JSON (string or array form):
Eager loads relations on demand. Only relations listed in the controller's
$allowedIncludes allowlist are honoured — anything else is silently ignored.
Works on both index and show.
Trashed (soft-deleted records)
Passed as a trashed key inside the filters JSON:
Opt-in: set $allowTrashedFilter = true on the controller. Ignored unless the
model uses SoftDeletes.
Combined Example
One filters param drives scopes, includes, and trashed together:
Controller Properties
Customize behavior by setting properties in your controller:
Scopes with Parameters
All scope properties ($scopes, $loadScopes, $deleteScopes, $updateScopes, $columnScopes, $restoreScopes) support the same syntax.
Lifecycle Hooks
Define methods on your model to hook into CRUD operations. These are called automatically by the controller.
You can also override hooks in the controller:
Contracts
Searchable
Enables automatic LIKE search on ?search= query parameter.
Request: GET /posts?search=laravel
Generates: WHERE (name LIKE '%laravel%' OR desc LIKE '%laravel%' OR EXISTS (SELECT ... FROM users WHERE name LIKE '%laravel%' OR email LIKE '%laravel%'))
Sortable
Provides default sort configuration when no sortBy query parameter is given.
HasPermissionSlug
Provides a permission slug for use with permissionMiddleware() in controllers.
Use the slug in your controller's middleware() method (see Permissions):
| Action | Permission | Routes |
|---|---|---|
| View | view-posts |
index, show |
| Store | store-posts |
store |
| Update | update-posts |
update, updateColumn |
| Delete | delete-posts |
destroy, delete, permanentDelete |
| Change Status | change-status-posts |
changeStatus |
| Restore | restore-posts |
restore, restoreAll |
Model Traits
HasDateScopes
Adds query scopes for common date ranges. All accept an optional $column parameter (default: created_at).
Available scopes:
UUID primary keys
This package does not ship a UUID trait — use Laravel's first-party traits, which
set incrementing/keyType, fill the key on creation, and add UUID-aware route
model binding:
Ordered UUIDs (v7) are recommended for primary keys because of their B-tree index locality. Reach for a pure-random v4 only if you must hide record creation order.
AnonymizesOnDelete
Anonymizes unique column values on soft delete to prevent constraint violations.
When soft-deleted, unique columns get _{timestamp} appended:
This prevents conflicts when creating a new user with [email protected] while the old record is soft-deleted. Controlled by fast-api.soft_delete.anonymize_unique_columns config.
ReplicatesWithRelations
Replicate a model along with all its loaded relations.
Supported relations: BelongsTo, MorphTo, HasOne, MorphOne, HasMany, MorphMany, BelongsToMany, MorphToMany
Not supported: HasOneThrough and HasManyThrough relations will throw an Exception during replication.
The trait also re-applies castable attributes (numeric, boolean, string, json) to the replicated model to ensure proper type handling.
Builder Macros
These macros are registered on Illuminate\Database\Eloquent\Builder and available on all queries.
initializer
Apply request-based filters, sorting, and scopes automatically.
How it works:
- Reads
?filters={"scope":"value"}— decodes JSON, calls matching model scopes (usesStr::studlyto findscope{Name}methods) - Reads
?sortBy=column&descending=true— applies ordering - If model implements
Sortableand no sort params given, usessortByDefaults() - Default sort:
iddescending
likeWhere
Multi-column LIKE search with relation support. Returns the query unmodified if $searchTerm is null or empty.
paginates
Length-aware pagination using rowsPerPage request parameter.
- Respects
fast-api.pagination.max_per_page(default: 100) - When
rowsPerPage=0andfast-api.pagination.allow_all=true, returns all records
simplePaginates
Simple pagination (no total count) using rowsPerPage request parameter. Same behavior as paginates() but without total count query.
cursorPaginates
Cursor-based pagination using rowsPerPage request parameter. Best for infinite scroll or large datasets.
withAggregates
Apply multiple aggregate functions in a single call.
withCountWhereHas / orWithCountWhereHas
Adds a conditional withCount that also filters results using whereHas (or orWhereHas).
Collection Macros
paginate
Paginate an in-memory collection.
API Responder
The HasApiResponse trait (used by BaseController) provides response helpers for every HTTP status code. You can also use it in any controller:
Core Methods
The envelope keys (data, errors, message) are configurable via fast-api.response.* config.
Complete Method Reference
All success methods accept array $data = []. All error methods accept string $message and array $data = [].
1xx Informational:
| Method | Status | Default Message |
|---|---|---|
continue() |
100 | — |
switchingProtocols() |
101 | — |
processing() |
102 | — |
earlyHints() |
103 | — |
2xx Success:
| Method | Status | Notes |
|---|---|---|
ok() |
200 | — |
created() |
201 | — |
accepted() |
202 | — |
nonAuthoritativeInformation() |
203 | — |
noContent() |
204 | Returns null body |
resetContent() |
205 | — |
partialContent() |
206 | — |
multiStatus() |
207 | — |
alreadyReported() |
208 | — |
imUsed() |
226 | — |
3xx Redirection:
| Method | Status |
|---|---|
multipleChoices() |
300 |
movedPermanently() |
301 |
found() |
302 |
seeOther() |
303 |
notModified() |
304 |
useProxy() |
305 |
temporaryRedirect() |
307 |
permanentRedirect() |
308 |
4xx Client Error:
| Method | Status | Default Message |
|---|---|---|
badRequest() |
400 | Bad Request |
unauthorized() |
401 | Unauthorized |
paymentRequired() |
402 | Payment Required |
forbidden() |
403 | Forbidden |
notFound() |
404 | Not Found |
methodNotAllowed() |
405 | Method Not Allowed |
notAcceptable() |
406 | Not Acceptable |
proxyAuthenticationRequired() |
407 | Proxy Authentication Required |
requestTimeout() |
408 | Request Timeout |
conflict() |
409 | Conflict |
gone() |
410 | Gone |
lengthRequired() |
411 | Length Required |
preconditionFailed() |
412 | Precondition Failed |
contentTooLarge() |
413 | Content Too Large |
uriTooLong() |
414 | URI Too Long |
unsupportedMediaType() |
415 | Unsupported Media Type |
rangeNotSatisfiable() |
416 | Range Not Satisfiable |
expectationFailed() |
417 | Expectation Failed |
imATeapot() |
418 | I'm a teapot |
misdirectedRequest() |
421 | Misdirected Request |
unprocessableContent() |
422 | Unprocessable Content |
locked() |
423 | Locked |
failedDependency() |
424 | Failed Dependency |
tooEarly() |
425 | Too Early |
upgradeRequired() |
426 | Upgrade Required |
preconditionRequired() |
428 | Precondition Required |
tooManyRequests() |
429 | Too Many Requests |
requestHeaderFieldsTooLarge() |
431 | Request Header Fields Too Large |
unavailableForLegalReasons() |
451 | Unavailable For Legal Reasons |
5xx Server Error:
| Method | Status | Default Message |
|---|---|---|
internalServerError() |
500 | Internal Server Error |
notImplemented() |
501 | Not Implemented |
badGateway() |
502 | Bad Gateway |
serviceUnavailable() |
503 | Service Unavailable |
gatewayTimeout() |
504 | Gateway Timeout |
httpVersionNotSupported() |
505 | HTTP Version Not Supported |
variantAlsoNegotiates() |
506 | Variant Also Negotiates |
insufficientStorage() |
507 | Insufficient Storage |
loopDetected() |
508 | Loop Detected |
notExtended() |
510 | Not Extended |
networkAuthenticationRequired() |
511 | Network Authentication Required |
Helper Functions
Global helper functions available throughout your application (autoloaded via composer).
Date & Time
Duration
Filtering & Sorting
Utility
Introspection
Class Discovery
Exceptions
ApiException
Custom exception that renders as JSON with debug info in development.
Production response:
Debug response (when APP_DEBUG=true):
Permissions
Both BaseController and BaseWebController implement Laravel's HasMiddleware interface. Override the static middleware() method in your controller and call permissionMiddleware() with the slug to register Spatie permission middleware:
permissionMiddleware() returns an empty array when fast-api.permissions.enabled is false, so toggling permissions off in config is safe without changing controller code.
Routes
Route::fastApiResource (recommended)
Register the full CRUD route set in one line:
This registers, in this order (collection routes before {id} routes):
| Method | URI | Action |
|---|---|---|
| GET | /posts |
index |
| POST | /posts |
store |
| DELETE | /posts |
delete (bulk) |
| POST | /posts/restore |
restoreAll |
| PATCH | /posts/{id}/status/{column} |
updateColumn |
| PATCH | /posts/{id}/status |
changeStatus |
| PATCH | /posts/{id}/restore |
restore |
| DELETE | /posts/{id}/force |
permanentDelete |
| GET | /posts/{id} |
show |
| PUT / PATCH | /posts/{id} |
update |
| DELETE | /posts/{id} |
destroy |
Registering routes manually
To wire them by hand, mirror the macro's verbs/URIs so permissionMiddleware() and your
clients line up (keep collection routes above the {id} routes):
For web controllers, create and edit form routes aren't registered by fastApiResource —
add them separately (or use Route::resource for the standard verbs).
Pagination Utility
The Anil\FastApiCrud\Support\Pagination class provides static helpers used internally by the macros. You can also use them directly:
Enums
PaginationType
CrudAction
Used for permission middleware registration.
Full Example
Model
API Controller
Web Controller
License
MIT
All versions of fast-api-crud with dependencies
illuminate/auth Version ^12.0||^13.0
illuminate/database Version ^12.0||^13.0
illuminate/http Version ^12.0||^13.0
illuminate/pagination Version ^12.0||^13.0
illuminate/routing Version ^12.0||^13.0
illuminate/support Version ^12.0||^13.0