Skip to content
Back to skills

068 Php 39c4e9e9

ASecurity

```php <?php

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
businessphpapidatabase

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 068-php_39c4e9e9 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 068 Php 39c4e9e9?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 068 Php 39c4e9e9
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-068-php-39c4e9e9/badge)](https://www.skillsdirectory.com/skills/tools-only-068-php-39c4e9e9)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Laravel Patterns

## Service Layer Pattern

```php
<?php

declare(strict_types=1);

namespace App\Services;

use App\DTOs\CreateUserData;
use App\Models\User;
use App\Repositories\UserRepositoryInterface;
use Illuminate\Support\Facades\Hash;

final readonly class UserService
{
    public function __construct(
        private UserRepositoryInterface $userRepository,
        private EmailService $emailService,
    ) {}

    public function createUser(CreateUserData $data): User
    {
        $user = $this->userRepository->create([
            'name' => $data->name,
            'email' => $data->email,
            'password' => Hash::make($data->password),
        ]);

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

        return $user;
    }

    public function suspendUser(int $userId, string $reason): void
    {
        $user = $this->userRepository->findOrFail($userId);

        $this->userRepository->update($user->id, [
            'status' => UserStatus::SUSPENDED,
            'suspension_reason' => $reason,
            'suspended_at' => now(),
        ]);

        $this->emailService->sendSuspensionNotice($user, $reason);
    }
}
```

## Repository Pattern

```php
<?php

declare(strict_types=1);

namespace App\Repositories;

use App\Models\User;
use Illuminate\Database\Eloquent\Collection;

interface UserRepositoryInterface
{
    public function findOrFail(int $id): User;
    public function findByEmail(string $email): ?User;
    public function create(array $data): User;
    public function update(int $id, array $data): User;
    public function delete(int $id): void;
    public function getActive(): Collection;
}

final class UserRepository implements UserRepositoryInterface
{
    public function findOrFail(int $id): User
    {
        return User::findOrFail($id);
    }

    public function findByEmail(string $email): ?User
    {
        return User::where('email', $email)->first();
    }

    public function create(array $data): User
    {
        return User::create($data);
    }

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

    public function delete(int $id): void
    {
        $this->findOrFail($id)->delete();
    }

    public function getActive(): Collection
    {
        return User::where('status', UserStatus::ACTIVE)
            ->orderBy('created_at', 'desc')
            ->get();
    }
}
```

## Form Requests with Enums

```php
<?php

declare(strict_types=1);

namespace App\Http\Requests;

use App\Enums\UserRole;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Validation\Rules\Password;

final class CreateUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()?->can('create', User::class) ?? false;
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'unique:users,email'],
            'password' => ['required', Password::min(8)->mixedCase()->numbers()],
            'role' => ['required', new Enum(UserRole::class)],
            'settings' => ['sometimes', 'array'],
            'settings.theme' => ['string', Rule::in(['light', 'dark'])],
        ];
    }

    public function toDto(): CreateUserData
    {
        return new CreateUserData(
            name: $this->validated('name'),
            email: $this->validated('email'),
            password: $this->validated('password'),
            role: UserRole::from($this->validated('role')),
        );
    }
}
```

## API Resources

```php
<?php

declare(strict_types=1);

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

/**
 * @mixin \App\Models\User
 */
final class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'status' => $this->status->value,
            'role' => $this->role->value,
            'created_at' => $this->created_at->toIso8601String(),

            // Conditional relationships
            'posts' => PostResource::collection($this->whenLoaded('posts')),
            'profile' => new ProfileResource($this->whenLoaded('profile')),

            // Conditional attributes
            'is_admin' => $this->when($this->role === UserRole::ADMIN, true),

            // Pivot data
            'team_role' => $this->whenPivotLoaded('team_user', fn() =>
                $this->pivot->role
            ),
        ];
    }
}

final class UserCollection extends ResourceCollection
{
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'meta' => [
                'total' => $this->total(),
                'per_page' => $this->perPage(),
            ],
        ];
    }
}
```

## Controllers with DTOs

```php
<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\CreateUserRequest;
use App\Http\Resources\UserResource;
use App\Services\UserService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;

final class UserController extends Controller
{
    public function __construct(
        private readonly UserService $userService,
    ) {}

    public function index(): AnonymousResourceCollection
    {
        $users = User::with('profile')
            ->where('status', UserStatus::ACTIVE)
            ->paginate(20);

        return UserResource::collection($users);
    }

    public function store(CreateUserRequest $request): JsonResponse
    {
        $user = $this->userService->createUser($request->toDto());

        return (new UserResource($user))
            ->response()
            ->setStatusCode(201);
    }

    public function show(User $user): UserResource
    {
        $user->load(['posts', 'profile']);
        return new UserResource($user);
    }

    public function destroy(User $user): JsonResponse
    {
        $this->authorize('delete', $user);

        $this->userService->deleteUser($user->id);

        return response()->json(null, 204);
    }
}
```

## Jobs & Queues

```php
<?php

declare(strict_types=1);

namespace App\Jobs;

use App\Models\User;
use App\Services\EmailService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

final class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $timeout = 30;

    public function __construct(
        private readonly int $userId,
    ) {}

    public function handle(EmailService $emailService): void
    {
        $user = User::findOrFail($this->userId);
        $emailService->sendWelcomeEmail($user);
    }

    public function failed(\Throwable $exception): void
    {
        \Log::error('Failed to send welcome email', [
            'user_id' => $this->userId,
            'error' => $exception->getMessage(),
        ]);
    }
}

// Dispatching jobs
SendWelcomeEmail::dispatch($user->id);
SendWelcomeEmail::dispatch($user->id)->delay(now()->addMinutes(5));
SendWelcomeEmail::dispatch($user->id)->onQueue('emails');
```

## Event Listeners

```php
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final readonly class UserRegistered
{
    use Dispatchable, SerializesModels;

    public function __construct(
        public User $user,
    ) {}
}

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Jobs\SendWelcomeEmail;
use Illuminate\Contracts\Queue\ShouldQueue;

final class SendWelcomeNotification implements ShouldQueue
{
    public function handle(UserRegistered $event): void
    {
        SendWelcomeEmail::dispatch($event->user->id);
    }
}

// In EventServiceProvider
protected $listen = [
    UserRegistered::class => [
        SendWelcomeNotification::class,
        UpdateUserStatistics::class,
    ],
];
```

## Quick Reference

| Pattern | Purpose | File Location |
|---------|---------|---------------|
| Service | Business logic | `app/Services/` |
| Repository | Data access | `app/Repositories/` |
| Form Request | Validation | `app/Http/Requests/` |
| Resource | API responses | `app/Http/Resources/` |
| Job | Async tasks | `app/Jobs/` |
| Event | Domain events | `app/Events/` |
| DTO | Data transfer | `app/DTOs/` |
| Policy | Authorization | `app/Policies/` |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.