AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Php Laravel

skill-j4flmao-agent-skills-laravel · by j4flmao

>

No reviews yet
0 installs
39 views
0.0% view→install

Install

$ agentstack add skill-j4flmao-agent-skills-laravel

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-j4flmao-agent-skills-laravel)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Php Laravel? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Laravel

Purpose

Build Laravel applications with clean MVC structure, service layer separation, Eloquent ORM best practices, form request validation, queue jobs, and comprehensive testing.

Agent Protocol

Trigger

User request includes: Laravel structure, Laravel app, Eloquent, Laravel service, Laravel validation, Laravel queue, Laravel testing, Laravel job, Laravel seeder.

Input Context

  • Laravel version (10.x, 11.x)
  • PHP version (8.1+)
  • Database (MySQL, PostgreSQL, SQLite)
  • Features (Auth, Queues, Broadcasting, Notifications, Cashier)

Output Artifact

Controller structure, service class, Eloquent model, form request, job class, seeder, test.

Response Format

Produce artifact directly. No preamble, no postamble, no explanations.

Completion Criteria

  • Controller delegates to service layer
  • Eloquent model with scopes, relations, casts
  • Form request class with validation rules
  • Service class with business logic
  • Queue job with typed properties
  • Feature/unit tests for critical paths

Max Response Length

4096 tokens

Architecture Decision Trees

Service Layer vs Repository vs Active Record

| Criterion | Service Layer | Repository | Active Record (Vanilla) | |-----------|--------------|------------|------------------------| | Business logic location | Service class | Repository class | Model methods | | Query abstraction | Service delegates to model | Repository encapsulates | Direct in controllers | | Testability | Easy (mock service) | Moderate (mock repo) | Hard (Eloquent facade) | | Complexity | Moderate | High (extra layer) | Low | | Laravel fit | Natural (dedicated directories) | Possible but uncommon | Default pattern |

Decision: Business logic outside controllers → Service Layer (most common in production Laravel apps). Need query abstraction → Repository. Simple CRUD → Active Record in controllers is acceptable.

Form Request vs Controller Validation

| Criterion | Form Request | Controller validate() | Manual validation | |-----------|-------------|----------------------|-------------------| | Reusability | Across controllers/actions | Per method | Per method | | Authorization | Built-in authorize() | Manual in controller | Manual | | Naming | StoreUserRequest | Inline array | Inline array | | Logic complexity | Custom rules, after hooks | Simple rules | Simple rules |

Decision: Reusable validation → Form Request. Simple one-off → Controller validate(). Complex custom logic → Form Request with custom rules.

Workflow

Step 1: Directory Structure

app/
  Http/
    Controllers/
      Api/
        V1/
          UserController.php
          OrderController.php
    Requests/
      StoreUserRequest.php
      UpdateUserRequest.php
    Resources/
      UserResource.php
  Models/
    User.php
    Order.php
  Services/
    UserService.php
    OrderService.php
  Jobs/
    ProcessOrderJob.php
  Exceptions/
    ConflictException.php
database/
  migrations/
    xxxx_create_users_table.php
  factories/
    UserFactory.php
  seeders/
    UserSeeder.php
routes/
  api.php
tests/
  Feature/
    UserTest.php
  Unit/
    UserServiceTest.php

Step 2: Eloquent Model

 'datetime',
            'password' => 'hashed',
            'is_active' => 'boolean',
            'created_at' => 'datetime:Y-m-d\TH:i:s\Z',
        ];
    }

    // Scopes
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeByRole($query, string $role)
    {
        return $query->where('role', $role);
    }

    // Relations
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    // Accessors
    public function getInitialsAttribute(): string
    {
        $parts = explode(' ', $this->name);
        return collect($parts)->map(fn($p) => strtoupper($p[0]))->implode('');
    }

    // Events
    protected static function booted(): void
    {
        static::created(function ($user) {
            event(new UserCreated($user));
        });
    }
}

Step 3: Form Request Validation

user()?->can('create-users') ?? false;
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'min:2', 'max:255'],
            'email' => ['required', 'email', Rule::unique('users')],
            'password' => ['required', 'string', 'min:8'],
            'role' => ['sometimes', Rule::in(['admin', 'user', 'moderator'])],
        ];
    }

    public function messages(): array
    {
        return [
            'email.unique' => 'This email is already registered.',
        ];
    }

    protected function prepareForValidation(): void
    {
        $this->merge([
            'email' => strtolower($this->email),
        ]);
    }
}

Step 4: Service Layer

exists()) {
            throw new ConflictException('Email already exists');
        }

        return DB::transaction(function () use ($data) {
            $user = User::create([
                'name' => $data['name'],
                'email' => $data['email'],
                'password' => Hash::make($data['password']),
                'role' => $data['role'] ?? 'user',
            ]);

            $this->notifications->sendWelcomeEmail($user);

            return $user;
        });
    }

    public function findById(string $id): ?User
    {
        return User::with('posts')->find($id);
    }

    public function paginate(int $perPage = 20): LengthAwarePaginator
    {
        return User::active()
            ->withCount('posts')
            ->orderBy('created_at', 'desc')
            ->paginate($perPage);
    }

    public function update(string $id, array $data): User
    {
        $user = User::findOrFail($id);
        $user->update($data);
        return $user->fresh();
    }

    public function delete(string $id): void
    {
        User::findOrFail($id)->delete();
    }
}

Step 5: API Resource (DTO)

 $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'role' => $this->role,
            'is_active' => $this->is_active,
            'posts_count' => $this->whenCounted('posts'),
            'created_at' => $this->created_at,
        ];
    }
}

Step 6: Thin Controller

userService->paginate();
        return response()->json([
            'data' => UserResource::collection($users),
            'meta' => [
                'current_page' => $users->currentPage(),
                'last_page' => $users->lastPage(),
                'total' => $users->total(),
            ],
        ]);
    }

    public function store(StoreUserRequest $request): JsonResponse
    {
        $user = $this->userService->create($request->validated());
        return response()->json([
            'data' => new UserResource($user),
        ], 201);
    }

    public function show(string $id): JsonResponse
    {
        $user = $this->userService->findById($id);
        abort_if(!$user, 404, 'User not found');
        return response()->json(['data' => new UserResource($user)]);
    }

    public function update(UpdateUserRequest $request, string $id): JsonResponse
    {
        $user = $this->userService->update($id, $request->validated());
        return response()->json(['data' => new UserResource($user)]);
    }

    public function destroy(string $id): JsonResponse
    {
        $this->userService->delete($id);
        return response()->json(null, 204);
    }
}

Step 7: Queue Job

reserveItems($this->order);
            $this->order->markAsProcessing();
        } catch (InsufficientInventoryException $e) {
            $this->order->markAsFailed($e->getMessage());
            $this->fail($e);
        }
    }

    public function failed(\Throwable $e): void
    {
        $this->order->markAsFailed($e->getMessage());
        event(new OrderFailed($this->order));
    }
}

Step 8: Exception Handler

expectsJson()) {
            return match (true) {
                $e instanceof ConflictException => response()->json([
                    'error' => ['code' => 'CONFLICT', 'message' => $e->getMessage()],
                ], 409),
                $e instanceof ValidationException => response()->json([
                    'error' => ['code' => 'VALIDATION_ERROR', 'details' => $e->errors()],
                ], 422),
                $e instanceof NotFoundHttpException => response()->json([
                    'error' => ['code' => 'NOT_FOUND', 'message' => 'Resource not found'],
                ], 404),
                $e instanceof HttpException => response()->json([
                    'error' => ['code' => 'ERROR', 'message' => $e->getMessage()],
                ], $e->getStatusCode()),
                default => response()->json([
                    'error' => ['code' => 'INTERNAL_ERROR', 'message' => 'An error occurred'],
                ], 500),
            };
        }

        return parent::render($request, $e);
    }
}

Implementation Patterns

Pattern: Caching with Cache Tags

public function findWithCache(string $id): ?User
{
    return Cache::tags(['users'])->remember("user.{$id}", 3600, function () use ($id) {
        return User::with('posts')->find($id);
    });
}

public function invalidateUserCache(string $id): void
{
    Cache::tags(['users'])->forget("user.{$id}");
}

Production Considerations

Eloquent Performance

  • Always use with() or load() to eager load — never lazy load in Blade
  • Use cursor() or chunk() for large datasets, never all()
  • Add indexes in migrations for all foreign keys and frequently queried columns
  • Use select to limit columns: User::select(['id', 'name', 'email'])
  • Avoid N+1: install Laravel Debugbar or Telescope in development to detect

Horizon/Queue Configuration

// config/horizon.php — production queue management
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['high', 'default', 'low'],
            'balance' => 'auto',
            'processes' => 3,
            'tries' => 3,
        ],
    ],
],

Anti-Patterns

| Anti-Pattern | Why | Fix | |-------------|-----|-----| | Business logic in controller | Untestable, violates SRP | Delegate to service class | | Global active() scope on User | Hidden filter | Explicit scopes in queries | | N+1 queries in Blade | 100+ SQL queries per page | Eager load with with() | | all() on large tables | Memory exhaustion | Use cursor(), chunk(), or paginate | | Events/Signals for non-decoupled concerns | Hard to trace flow | Use listeners for side effects | | dd()/dump() in committed code | Breaks API responses | Use logger instead |

Security Considerations

  • Hash::make() for passwords — never plain text or MD5/SHA
  • Form Request authorize() for permission checks
  • $guarded or $fillable on all models — never unguarded
  • CSRF protection enabled by default — never disable on state-changing routes
  • Rate limiting via RateLimiter facade or throttle middleware
  • SQL injection: Eloquent is safe (parameterized), but DB::raw() can be vulnerable
  • XSS: {{ }} Blade syntax auto-escapes; {!! !!} only for trusted HTML

Testing Strategies

// tests/Feature/UserControllerTest.php
class UserControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_create_user(): void
    {
        $response = $this->postJson('/api/v1/users', [
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'password' => 'password123',
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure(['data' => ['id', 'name', 'email']]);
    }

    public function test_duplicate_email_returns_conflict(): void
    {
        User::factory()->create(['email' => 'john@example.com']);

        $response = $this->postJson('/api/v1/users', [
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'password' => 'password123',
        ]);

        $response->assertStatus(409);
    }
}

Use RefreshDatabase or DatabaseTransactions trait for isolation. Use Http facade fake for external API calls. Use Queue::fake() to test job dispatching. Use Bus::fake() to test command dispatching.

Rules

  • Controllers are thin — validation in Form Requests, business logic in Services.
  • Eloquent models have $fillable, $casts, type-hinted relations, and query scopes.
  • Form Requests contain validation rules and authorization logic.
  • Service classes are constructor-injected into controllers.
  • Queue jobs use typed constructor properties and $tries/$backoff for retry config.
  • API routes return JSON responses with Resource classes for DTO transformation.
  • Exception handling via Handler::render() for consistent error responses.
  • Caching with Cache::tags() for invalidatable cache groups.
  • All DB queries use eager loading (with()) to prevent N+1.
  • Migrations are always backward-compatible — never drop columns without deprecation.

References

  • references/artisan-commands.md — Artisan Commands
  • references/eloquent-orm.md — Eloquent ORM Patterns
  • references/laravel-middleware-validation.md — Middleware and Validation
  • references/laravel-queues.md — Queue Configuration
  • references/laravel-service-layer.md — Service Layer Pattern
  • references/laravel-testing.md — Testing Laravel

Handoff

Hand off to backend/php/pure/SKILL.md for non-Laravel PHP patterns or backend/universal/api-response/SKILL.md for API response formatting.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.