Created
July 16, 2025 13:08
-
-
Save Shaz3e/c2417bfc0d71d0f476d78db011b09f58 to your computer and use it in GitHub Desktop.
Create CRUD API with one command
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace {{ namespace }}; | |
use {{ rootNamespace }}Http\Controllers\Controller; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Gate; | |
use {{ rootNamespace }}Models\{{ modelClass }}; | |
use {{ rootNamespace }}Http\Resources\{{ path }}\{{ modelClass }}\{{ resourceListClass }}; | |
use {{ rootNamespace }}Http\Resources\{{ path }}\{{ modelClass }}\{{ resourceClass }}; | |
use {{ rootNamespace }}Http\Requests\{{ path }}\{{ modelClass }}\Store{{ modelClass }}Request; | |
use {{ rootNamespace }}Http\Requests\{{ path }}\{{ modelClass }}\Update{{ modelClass }}Request; | |
class {{ class }} extends Controller | |
{ | |
/** | |
* Display a listing of the resource. | |
*/ | |
public function index() | |
{ | |
Gate::authorize('viewAny', {{ modelClass }}::class); | |
${{ modelVariable }}s = {{ modelClass }}::paginate(10); | |
$message = ${{ modelVariable }}s->isEmpty() | |
? 'No record found' | |
: 'Data retrieved'; | |
return $this->api->success( | |
$message, | |
{{ resourceListClass }}::collection(${{ modelVariable }}s) | |
); | |
} | |
/** | |
* Store a newly created resource in storage. | |
*/ | |
public function store(Store{{ modelClass }}Request $request) | |
{ | |
Gate::authorize('create', {{ modelClass }}::class); | |
$validated = $request->validated(); | |
${{ modelVariable }} = {{ modelClass }}::create($validated); | |
return $this->api->success( | |
'{{ modelClass }} created successfully', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Display the specified resource. | |
*/ | |
public function show(string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('view', ${{ modelVariable }}); | |
return $this->api->success( | |
'{{ modelClass }} found', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Update the specified resource in storage. | |
*/ | |
public function update(Update{{ modelClass }}Request $request, string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('update', ${{ modelVariable }}); | |
$validated = $request->validated(); | |
${{ modelVariable }}->update($validated); | |
return $this->api->success( | |
'{{ modelClass }} updated successfully', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Remove the specified resource from storage. | |
*/ | |
public function destroy(string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('delete', ${{ modelVariable }}); | |
if (${{ modelVariable }}->trashed()) { | |
return $this->api->error('{{ modelClass }} is already deleted', 400); | |
} | |
${{ modelVariable }}->delete(); | |
return $this->api->success( | |
'{{ modelClass }} deleted successfully', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Restore the specified resource from storage. | |
*/ | |
public function restore(string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::withTrashed()->find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('restore', ${{ modelVariable }}); | |
if (! ${{ modelVariable }}->trashed()) { | |
return $this->api->error('{{ modelClass }} is not deleted and cannot be restored', 400); | |
} | |
${{ modelVariable }}->restore(); | |
return $this->api->success( | |
'{{ modelClass }} restored successfully', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Permanently delete the specified resource from storage. | |
*/ | |
public function forceDelete(string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::withTrashed()->find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('forceDelete', ${{ modelVariable }}); | |
if (! ${{ modelVariable }}->trashed()) { | |
return $this->api->error('{{ modelClass }} must be soft-deleted before it can be permanently deleted', 400); | |
} | |
${{ modelVariable }}->forceDelete(); | |
return $this->api->success('{{ modelClass }} permanently deleted successfully'); | |
} | |
/** | |
* Toggle active status for a resource. | |
*/ | |
public function isActive(Request $request, string $id) | |
{ | |
${{ modelVariable }} = {{ modelClass }}::find($id); | |
if (! ${{ modelVariable }}) { | |
return $this->api->notFound('{{ modelClass }} not found'); | |
} | |
Gate::authorize('update', ${{ modelVariable }}); | |
$validated = $request->validate([ | |
'is_active' => 'required|boolean', | |
]); | |
${{ modelVariable }}->update($validated); | |
return $this->api->success( | |
'{{ modelClass }} updated successfully', | |
new {{ resourceClass }}(${{ modelVariable }}) | |
); | |
} | |
/** | |
* Return a list of all active resources. | |
*/ | |
public function activeList() | |
{ | |
Gate::authorize('viewAny', {{ modelClass }}::class); | |
${{ modelVariable }}s = {{ modelClass }}::active()->paginate(10); | |
$message = ${{ modelVariable }}s->isEmpty() | |
? 'No record found' | |
: 'Data retrieved for active {{ modelClass }}s'; | |
return $this->api->success( | |
$message, | |
{{ resourceListClass }}::collection(${{ modelVariable }}s) | |
); | |
} | |
/** | |
* Return a list of all inactive resources. | |
*/ | |
public function inActiveList() | |
{ | |
Gate::authorize('viewAny', {{ modelClass }}::class); | |
${{ modelVariable }}s = {{ modelClass }}::inactive()->paginate(10); | |
$message = ${{ modelVariable }}s->isEmpty() | |
? 'No record found' | |
: 'Data retrieved for inactive {{ modelClass }}s'; | |
return $this->api->success( | |
$message, | |
{{ resourceListClass }}::collection(${{ modelVariable }}s) | |
); | |
} | |
/** | |
* Return a list of all deleted resources. | |
*/ | |
public function deletedList() | |
{ | |
Gate::authorize('viewAny', {{ modelClass }}::class); | |
${{ modelVariable }}s = {{ modelClass }}::onlyDeleted()->paginate(10); | |
$message = ${{ modelVariable }}s->isEmpty() | |
? 'No record found' | |
: 'Data retrieved for deleted {{ modelClass }}s'; | |
return $this->api->success( | |
$message, | |
{{ resourceListClass }}::collection(${{ modelVariable }}s) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Run: php artisan make:command DevResource | |
namespace App\Console\Commands\Dev; | |
use Illuminate\Console\Command; | |
use Illuminate\Support\Str; | |
class DevResource extends Command | |
{ | |
/** | |
* The name and signature of the console command. | |
* | |
* @var string | |
*/ | |
protected $signature = 'dev:resource {name?} {path?}'; | |
/** | |
* The console command description. | |
* | |
* @var string | |
*/ | |
protected $description = 'This command will generated Controller with API Crud, Store Request, Update Request, Model, Resource, Policy and Migrations'; | |
/** | |
* Execute the console command. | |
*/ | |
public function handle() | |
{ | |
$name = $this->argument('name') ?? $this->ask('What is the name of the resource?'); | |
$path = $this->argument('path') ?? $this->ask('What is the path for the resource (e.g. Admin/Client)?'); | |
if (! $name || ! $path) { | |
$this->error('Both name and path are required.'); | |
return; | |
} | |
$modelClass = Str::studly($name); // IbClient | |
$modelVariable = Str::camel($name); // ibClient | |
$resourceListClass = $modelClass.'ListResource'; | |
$resourceClass = $modelClass.'Resource'; | |
$controllerClass = $modelClass.'Controller'; | |
$namespace = "App\\Http\\Controllers\\$path"; | |
// π Generate controller manually from stub | |
$stub = file_get_contents(base_path('stubs/controller.api.stub')); | |
$stub = str_replace( | |
[ | |
'{{ namespace }}', | |
'{{ rootNamespace }}', | |
'{{ class }}', | |
'{{ modelClass }}', | |
'{{ modelVariable }}', | |
'{{ resourceListClass }}', | |
'{{ resourceClass }}', | |
'{{ path }}', | |
], | |
[ | |
$namespace, | |
'App\\', | |
$controllerClass, | |
$modelClass, | |
$modelVariable, | |
$resourceListClass, | |
$resourceClass, | |
$path, | |
], | |
$stub | |
); | |
$controllerPath = app_path("Http/Controllers/{$path}/{$controllerClass}.php"); | |
if (! is_dir(dirname($controllerPath))) { | |
mkdir(dirname($controllerPath), 0755, true); | |
} | |
file_put_contents($controllerPath, $stub); | |
$this->info("β Controller created: $controllerPath"); | |
// β Store Request | |
$this->call('make:request', [ | |
'name' => "$path/$name/Store{$name}Request", | |
]); | |
// β Update Request | |
$this->call('make:request', [ | |
'name' => "$path/$name/Update{$name}Request", | |
]); | |
// β Model | |
$this->call('make:model', [ | |
'name' => $name, | |
]); | |
// β Factory | |
$this->call('make:factory', [ | |
'name' => "{$name}Factory", | |
'--model' => $name, | |
]); | |
// β Resource | |
$this->call('make:resource', [ | |
'name' => "$path/{$name}/{$name}Resource", | |
]); | |
// β List Model Resource | |
$this->call('make:resource', [ | |
'name' => "$path/{$name}/{$name}ListResource", | |
]); | |
// β Policy | |
$this->call('make:policy', [ | |
'name' => "{$name}Policy", | |
'--model' => $name, | |
]); | |
// β Observer | |
$this->call('make:observer', [ | |
'name' => "{$name}Observer", | |
'--model' => $name, | |
]); | |
// β Migration | |
$this->call('make:migration', [ | |
'name' => 'create_'.Str::snake(Str::pluralStudly($name)).'_table', | |
]); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace {{ namespace }}; | |
{{ factoryImport }} | |
use Illuminate\Database\Eloquent\Model; | |
use Illuminate\Database\Eloquent\Attributes\ObservedBy; | |
use Illuminate\Database\Eloquent\Attributes\UsePolicy; | |
use Illuminate\Database\Eloquent\Factories\HasFactory; | |
use App\Observers\{{ class }}Observer; | |
use App\Policies\{{ class }}Policy; | |
use Illuminate\Database\Eloquent\SoftDeletes; | |
#[ObservedBy({{ class }}Observer::class)] | |
#[UsePolicy({{ class }}Policy::class)] | |
class {{ class }} extends Model | |
{ | |
use HasFactory, SoftDeletes; | |
protected $fillable = []; | |
/** | |
* Scope a query to only include active records. | |
*/ | |
public function scopeActive($query) | |
{ | |
return $query->where('is_active', true); | |
} | |
/** | |
* Scope a query to only include inactive records. | |
*/ | |
public function scopeInactive($query) | |
{ | |
return $query->where('is_active', false); | |
} | |
/** | |
* Scope a query to only include soft-deleted records. | |
*/ | |
public function scopeOnlyDeleted($query) | |
{ | |
return $query->onlyTrashed(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment