yeashy/compliance

Pipeline Validation For Laravel Apps

Installs: 362

Dependents: 0

Suggesters: 0

Security: 0

Stars: 11

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/yeashy/compliance

v1.0.0-stable 2025-08-18 07:40 UTC

README

Latest Version on Packagist Total Downloads License

Yeashy Compliance is an elegant pipeline-based validation system for Laravel, designed to extend FormRequest validation with domain-driven, reusable, and expressive rule objects.

🚀 Features

  • ✅ Seamless integration with Laravel FormRequest
  • 🧩 Pipeline-based rule processing
  • 🎯 HTTP-method-specific rule handling (GET, POST, etc.)
  • 🔁 Composable and testable rule classes
  • 📦 Fully compatible with standard Laravel validation

📦 Installation

Install the package via Composer:

composer require yeashy/compliance

No additional service provider registration is required.

🧑‍💻 Getting Started

To use Compliance in your requests, simply extend the base ComplianceRequest instead of Laravel’s FormRequest.

Step 1: Create a Compliance Rule

A compliance rule is a class that extends Yeashy\Compliance\Rules\ComplianceRule and implements the validate() method.

use Yeashy\Compliance\Rules\ComplianceRule;

class EmailIsNotBlocked extends ComplianceRule
{
    protected string $key = 'email';
    protected string $message = 'This email address is blocked.';

    protected function validate(): void
    {
        if ($this->data->email === 'blocked@example.com') {
            $this->invalidateAndExit(); // Add error and stop the pipeline
        }
    }
}

Step 2: Apply the Rule in a Request

Extend ComplianceRequest and define the rules in the $compliances property, or specify them per HTTP method ($postCompliances, $getCompliances, etc.).

use Yeashy\Compliance\Requests\ComplianceRequest;

class RegisterRequest extends ComplianceRequest
{
    protected array $postCompliances = [
        \App\Compliance\Rules\EmailIsNotBlocked::class,
    ];

    public function rules(): array
    {
        return [
            'email' => ['required', 'email'],
            'password' => ['required'],
        ];
    }
}

That’s it! The request will now go through both Laravel’s standard validation and your custom compliance pipeline.

⚙️ How Compliance Rules Work

Each rule receives an object containing:

  • All input data from the request (Request::all())
  • Route parameters

The validate() method inside each rule is executed in sequence. You can:

  • Use invalidate($key, $message) to add an error and continue to the next rule.
  • Use invalidateAndExit() to add an error and stop the pipeline immediately.
  • Use skipNext() to stop the pipeline without adding an error (optional shortcut).

HTTP Method Specific Rules

Compliance rules can be defined globally for all methods:

protected array $compliances = [...];`

Or scoped to specific HTTP verbs:

protected array $postCompliances = [...];
protected array $getCompliances = [...];
// Supported: get, post, put, patch, delete, head, options

Error Merging

Compliance errors are automatically merged with Laravel’s validation errors and returned in the standard format. If a compliance rule sets a custom $statusCode, it will override the default HTTP 422 status.

✅ Best Practices

  • Rules should follow the Single Responsibility Principle: one rule — one concern.
  • Use meaningful keys ($key) to ensure correct field mapping in error responses.
  • Localize messages using __('...') whenever possible.
  • Prefer invalidateAndExit() for critical rules (e.g., credential checks).
  • Use skipNext() if the current rule makes the remaining ones irrelevant.

📂 Example

Rule: Ensure the user is not blocked

use Illuminate\Support\Facades\Auth;
use Yeashy\Compliance\Rules\ComplianceRule;

class UserIsNotBlocked extends ComplianceRule
{
    protected string $key = 'user';
    protected string $message = 'Your account has been blocked.';
    public int $statusCode = 403;

    protected function validate(): void
    {
        $user = Auth::user();

        if (! $user || $user->is_blocked) {
            $this->invalidateAndExit();
        }
    }
}

Usage in Request:

use Yeashy\Compliance\Requests\ComplianceRequest;

class DashboardRequest extends ComplianceRequest
{
    protected array $compliances = [
        \App\Compliance\Rules\UserIsNotBlocked::class,
        \App\Compliance\Rules\AccountIsVerified::class,
    ];

    protected array $getCompliances = [
        \App\Compliance\Rules\SubscriptionIsActive::class,
        \App\Compliance\Rules\UserHasAccessToResource::class,
    ];

    public function rules(): array
    {
        return [
            'resource_id' => ['required', 'uuid'],
        ];
    }
}

In this example:

  • $compliances defines global rules that apply to all HTTP methods.
  • $getCompliances defines additional rules applied only for GET requests.
  • All rules are processed in order, and execution stops if a rule uses invalidateAndExit().

🧪 Testing

You can test compliance rules in isolation:

public function test_email_is_not_blocked()
{
    $rule = new EmailIsNotBlocked();

    $data = (object) ['email' => 'blocked@example.com'];

    $rule->handle($data, fn($data) => $data);

    $this->assertNotEmpty($data->__errorMessages);
}

📄 License

The MIT License (MIT). Please see License File for more information.

🤝 Contributing

Contributions, issues and feature requests are welcome! Feel free to submit a PR or open an issue.