Skip to content

Instantly share code, notes, and snippets.

@Shaz3e
Created July 16, 2025 13:08
Show Gist options
  • Save Shaz3e/c2417bfc0d71d0f476d78db011b09f58 to your computer and use it in GitHub Desktop.
Save Shaz3e/c2417bfc0d71d0f476d78db011b09f58 to your computer and use it in GitHub Desktop.
Create CRUD API with one command
<?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)
);
}
}
<?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',
]);
}
}
<?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