imsus/skills · Archived

laravel-fp

Guides the agent to write Laravel applications using functional programming principles. Covers FP patterns for models, controllers, validation, jobs, CLI commands, services, and helpers while maintaining Laravel's folder structure and never removing existing classes.

First seen Jun 18, 2026

Installation

$ npx skills add imsus/skills --skill laravel-fp

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
LicenseMIT
More metadata
author
Imam Susanto
version
1.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,714 B
  • docs SUMMARY.md 285 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Laravel Functional Programming Guide

This skill guides agents to write Laravel applications using functional programming (FP) principles while respecting Laravel's conventions.

Core Principles

  1. Immutability: Never mutate data; create new instances instead
  2. Pure Functions: Functions should have no side effects and return consistent outputs for same inputs
  3. Higher-Order Functions: Use map, filter, reduce, and other collection operations
  4. Function Composition: Combine small functions to build complex behavior
  5. Avoid Global State: Minimize use of facades and static helpers in core logic
  6. Type Safety: Use PHP type declarations and value objects

Best Practices

Declare Strict Types

Always enable strict typing in PHP files:

<?php

declare(strict_types=1);

namespace App\Data;
// ...

Why:

  • Type coercion is disabled (1 !== '1')
  • Better type safety
  • Clearer error messages
  • Prevents silent bugs

Single Responsibility

Each function/class should do one thing:

// ❌ Bad - does too much
function createUser(array $data): array
{
    $validated = validate($data);
    $user = User::create($validated);
    sendWelcomeEmail($user);
    return $user->toArray();
}

// ✅ Good - single responsibility
function validateUserData(array $data): Result { ... }
function persistUser(array $data): User { ... }
function notifyUser(User $user): void { ... }

Prefer Composition Over Inheritance

// ❌ Inheritance - tightly coupled
class AdminUser extends User
{
    public function deleteEverything() { ... }
}

// ✅ Composition - flexible
class UserService
{
    public function __construct(
        private AuthorizationService $auth,
        private NotificationService $notify,
    ) {}

    public function deleteUser(User $user): Result { ... }
}

Avoid Side Effects in Pure Functions

// ❌ Side effect - modifies global state
function registerUser(array $data): User
{
    $user = User::create($data);
    session()->flash('success', 'User created'); // Side effect!
    return $user;
}

// ✅ Pure - no side effects
function createUser(array $data): Result
{
    return Result::success(User::create($data));
}

// Controller handles side effects
$result = $this->userService->createUser($data);
$result->then(fn($user) => session()->flash('success', 'User created'));

Recommended Packages

composer require spatie/laravel-data     # Data transfer objects (RECOMMENDED)
composer require fp4php/functional       # Monads (Option, Either, Result) - NOT for Collection operations

Use Laravel built-ins for:

  • Collection - map, filter, reduce, etc.
  • Number facade - formatting
  • str() helper - UUID, slugs, strings
  • illuminate/validation - validation
  • Bus/Queue - commands/jobs

Folder Structure (Preserve Laravel Boilerplate)

app/
├── Console/          # Keep existing - use FP in commands
├── Data/             # Spatie Laravel Data objects (NEW)
├── Exceptions/       # Keep existing - functional exception handling
├── Http/
│   ├── Controllers/  # Functional controllers
│   ├── Middleware/   # Keep existing - compose middleware functionally
│   └── Requests/     # Functional form requests
├── Jobs/             # Pure job classes
├── Models/           # Keep existing - enhance with FP patterns
├── Providers/        # Keep existing
├── Repositories/     # Functional repositories
├── Services/         # Functional services
├── Support/          # Helpers, Result, Maybe monads
└── Traits/           # FP traits

Quick Reference Patterns

Result Monad Pattern (using fp4php/functional)

<?php declare(strict_types=1);

namespace App\Support;

use Fp4php\Functional\Result\Result;
use Fp4php\Functional\Result\Success;
use Fp4php\Functional\Result\Failure;

// Usage in controller:
return $this->validateRequest($request)
    ->andThen(fn($data) => User::create($data))
    ->map(fn($user) => response()->json($user, 201))
    ->getOrElse(fn($error) => response()->json(['error' => $error], 500));

Why fp4php/functional?

  • Laravel doesn't have a Result monad
  • Provides map, filter, flatMap, getOrElse, etc.
  • Composable error handling without exceptions

Collection Pipeline

// ✅ Functional - prefer
User::where('is_active', true)
    ->get()
    ->filter(fn($u) => $u->role === 'admin')
    ->map(fn($u) => ['id' => $u->id, 'name' => $u->name])
    ->toArray();

Data Objects

// app/Data/UserData.php
class UserData extends Data
{
    public function __construct(
        public string $email,
        public string $name,
        public ?int $id = null,
    ) {}
}

// In controller:
return UserData::from(User::create($data->toArray()));

Progressive Disclosure

Load detailed references when needed:

Topic File
Models, Controllers, Services [REFERENCE.md](references/REFERENCE.md)
Validation patterns [VALIDATION.md](references/VALIDATION.md)
Spatie Data objects [DATAOBJECTS.md](references/DATAOBJECTS.md)
Value objects [VALUEOBJECTS.md](references/VALUEOBJECTS.md)
Helper functions [HELPERS.md](references/HELPERS.md)
CLI commands [CLI.md](references/CLI.md)

Key Patterns

Functional Controller

See [REFERENCE.md](references/REFERENCE.md#controllers) for full controller patterns with Result monad, validation, and error handling.

Functional Jobs

See [REFERENCE.md](references/REFERENCE.md#jobs) for pure job pattern with batch processing and Laravel native commands.

Functional Services

See [REFERENCE.md](references/REFERENCE.md#services) for service layer with dependency injection and pure functions.

Things to Avoid

  1. Mutating collections in place - Use map, filter, reject which return new collections
  2. Direct facade calls in business logic - Inject services instead
  3. Global state - Pass dependencies explicitly
  4. Procedural code in controllers - Extract to services
  5. Side effects in models - Keep models anemic (data only)
  6. Static helpers - Use dependency injection

Never Remove Existing Classes

When refactoring existing Laravel code:

  • Add new classes alongside existing ones
  • Extend rather than replace
  • Deprecate with warning comments
  • Use traits to inject FP patterns into existing classes
  • Never delete models, controllers, or other core classes

References