Skip to main content

StoreEventSystemRequest

The StoreEventSystemRequest is a form request class that validates and normalizes input data when creating or storing event-listener bindings in the Event System. It ensures data integrity by validating event and listener class names, priority values, and other required fields before storing them in the database.

Namespace

JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest

Overview

StoreEventSystemRequest provides comprehensive validation and data normalization for event system bindings. It:

  • Validates all required fields before storing event-listener bindings
  • Checks class existence for event and listener classes using ClassExistRule
  • Normalizes input data with default values and type conversions
  • Provides translated attributes for better error messages
  • Supports DTO conversion for programmatic usage outside HTTP requests
  • Ensures uniqueness of event binding names

Available Methods

authorize()

Determines if the user is authorized to make this request.

public function authorize(): bool
{
return true; // Default: allows all requests
}

Override for authorization:

namespace App\Http\Requests;

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest as BaseRequest;

class StoreEventSystemRequest extends BaseRequest
{
public function authorize(): bool
{
return $this->user()->can('create', \JobMetric\EventSystem\Models\Event::class);
}
}

rules()

Get the validation rules that apply to the request.

public function rules(): array
{
return [
'name' => 'required|string|max:255|unique:events,name',
'description' => 'string|nullable',
'event' => [
'required',
'string',
new ClassExistRule
],
'listener' => [
'required',
'string',
new ClassExistRule
],
'priority' => 'integer|nullable',
'status' => 'boolean'
];
}

normalize()

Normalize raw input when validating outside Laravel's FormRequest pipeline.

public static function normalize(array $data): array
{
$data['priority'] = $data['priority'] ?? 0;

if (($data['description'] ?? null) === '') {
$data['description'] = null;
}

return $data;
}

Usage:

// Normalize data before validation
$normalized = StoreEventSystemRequest::normalize($input);
$dto = dto($normalized, StoreEventSystemRequest::class);

prepareForValidation()

Laravel's native pipeline calls this when using the FormRequest normally.

protected function prepareForValidation(): void
{
$this->merge(static::normalize($this->all()));
}

This method automatically normalizes data when the request is used in controllers.

attributes()

Get custom attributes for validator errors.

public function attributes(): array
{
return [
'name' => trans('event-system::base.fields.name'),
'description' => trans('event-system::base.fields.description'),
'event' => trans('event-system::base.fields.event'),
'listener' => trans('event-system::base.fields.listener'),
'priority' => trans('event-system::base.fields.priority'),
'status' => trans('event-system::base.fields.status'),
];
}

Validation Rules

Field Details

FieldTypeRequiredRulesDefaultDescription
namestringYesrequired|string|max:255|unique:events,name-Unique identifier for the event-listener binding
descriptionstringNostring|nullablenullOptional description for the binding
eventstringYesrequired|string|ClassExistRule-Fully qualified event class name
listenerstringYesrequired|string|ClassExistRule-Fully qualified listener class name
priorityintegerNointeger|nullable0Execution priority (lower = earlier)
statusbooleanNobooleantrueActive status of the binding

name Field

Unique name identifier for the event-listener binding.

Rules:

  • required: Must be provided
  • string: Must be a string
  • max:255: Maximum 255 characters
  • unique:events,name: Must be unique in the events table

Examples:

'name' => 'user.created'
'name' => 'order.completed'
'name' => 'notification.send'

Validation Errors:

{
"name": [
"The name field is required.",
"The name has already been taken."
]
}

description Field

Optional description for the event binding.

Rules:

  • string: Must be a string if provided
  • nullable: Can be null or omitted

Examples:

'description' => 'Send welcome email when user registers'
'description' => null
'description' => '' // Normalized to null

event Field

Fully qualified class name of the event.

Rules:

  • required: Must be provided
  • string: Must be a string
  • ClassExistRule: Class must exist and be loadable

Examples:

'event' => 'App\Events\UserCreated'
'event' => App\Events\OrderCompleted::class
'event' => 'JobMetric\EventSystem\Events\EventSystemStoredEvent'

Validation Errors:

{
"event": [
"The event field is required.",
"The event class does not exist."
]
}

listener Field

Fully qualified class name of the listener.

Rules:

  • required: Must be provided
  • string: Must be a string
  • ClassExistRule: Class must exist and be loadable

Examples:

'listener' => 'App\Listeners\SendWelcomeEmail'
'listener' => App\Listeners\ProcessOrder::class
'listener' => 'App\Listeners\NotifyAdmin'

Validation Errors:

{
"listener": [
"The listener field is required.",
"The listener class does not exist."
]
}

priority Field

Execution priority of the listener. Lower values execute earlier.

Rules:

  • integer: Must be an integer if provided
  • nullable: Can be null or omitted
  • Default: 0 (set by normalize())

Examples:

'priority' => 10  // Executes after priority 0-9
'priority' => 0 // Executes first
'priority' => null // Normalized to 0

Priority Behavior:

  • Lower priority values execute earlier
  • Higher priority values execute later
  • Default priority is 0

status Field

Active status of the event binding.

Rules:

  • boolean: Must be true or false
  • Default: true (if not provided, Laravel may set to false)

Examples:

'status' => true  // Active
'status' => false // Disabled

Data Normalization

The request automatically normalizes data through the normalize() method:

Priority Normalization

// If priority is not provided, defaults to 0
$data['priority'] = $data['priority'] ?? 0;

// Examples:
['priority' => null] → ['priority' => 0]
['priority' => 10] → ['priority' => 10]
[] → ['priority' => 0] // Added

Description Normalization

// Empty strings are converted to null
if (($data['description'] ?? null) === '') {
$data['description'] = null;
}

// Examples:
['description' => ''] → ['description' => null]
['description' => 'Text'] → ['description' => 'Text']
['description' => null] → ['description' => null]

Usage Examples

Example 1: Basic Controller Usage

Use in a controller method:

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest;
use JobMetric\EventSystem\Facades\EventSystem;

class EventSystemController extends Controller
{
public function store(StoreEventSystemRequest $request)
{
$response = EventSystem::store($request->validated());

if ($response->isSuccess()) {
return redirect()
->route('admin.events.index')
->with('success', $response->getMessage());
}

return back()
->withErrors($response->getErrors())
->withInput();
}
}

Example 2: API Controller

Return JSON responses for API:

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest;
use JobMetric\EventSystem\Facades\EventSystem;

class EventSystemController extends Controller
{
public function store(StoreEventSystemRequest $request)
{
$response = EventSystem::store($request->validated());

if ($response->isSuccess()) {
return response()->json([
'success' => true,
'message' => $response->getMessage(),
'data' => $response->getData(),
], 201);
}

return response()->json([
'success' => false,
'message' => $response->getMessage(),
'errors' => $response->getErrors(),
], 422);
}
}

Example 3: Programmatic Usage with DTO

Convert array to validated DTO:

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest;
use JobMetric\EventSystem\Facades\EventSystem;

// Prepare input data
$input = [
'name' => 'user.created',
'description' => 'Send welcome email when user registers',
'event' => App\Events\UserCreated::class,
'listener' => App\Listeners\SendWelcomeEmail::class,
'priority' => 10,
'status' => true,
];

// Convert to validated DTO
$dto = dto($input, StoreEventSystemRequest::class);

// Use validated data
$response = EventSystem::store($dto);

Example 4: Batch Creation

Create multiple event bindings:

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest;
use JobMetric\EventSystem\Facades\EventSystem;

$bindings = [
[
'name' => 'user.created',
'event' => App\Events\UserCreated::class,
'listener' => App\Listeners\SendWelcomeEmail::class,
],
[
'name' => 'order.completed',
'event' => App\Events\OrderCompleted::class,
'listener' => App\Listeners\SendOrderConfirmation::class,
'priority' => 5,
],
];

foreach ($bindings as $binding) {
$dto = dto($binding, StoreEventSystemRequest::class);
EventSystem::store($dto);
}

Example 5: Custom Authorization

Override authorization:

namespace App\Http\Requests;

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest as BaseRequest;

class StoreEventSystemRequest extends BaseRequest
{
public function authorize(): bool
{
// Only admins can create event bindings
return $this->user()->hasRole('admin');
}

public function rules(): array
{
$rules = parent::rules();

// Add custom validation
$rules['name'] = array_merge(
explode('|', $rules['name']),
['regex:/^[a-z0-9._-]+$/']
);

return $rules;
}
}

Example 6: Conditional Validation

Add conditional rules:

namespace App\Http\Requests;

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest as BaseRequest;
use Illuminate\Validation\Rule;

class StoreEventSystemRequest extends BaseRequest
{
public function rules(): array
{
$rules = parent::rules();

// Add conditional validation based on user role
if ($this->user()->hasRole('admin')) {
$rules['priority'] = array_merge(
explode('|', $rules['priority']),
['max:100']
);
}

return $rules;
}
}

Example 7: Custom Error Messages

Override error messages:

namespace App\Http\Requests;

use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest as BaseRequest;

class StoreEventSystemRequest extends BaseRequest
{
public function messages(): array
{
return [
'name.required' => 'The event binding name is required.',
'name.unique' => 'This event binding name is already in use.',
'event.required' => 'You must specify an event class.',
'listener.required' => 'You must specify a listener class.',
'event' => 'The event class does not exist or cannot be loaded.',
'listener' => 'The listener class does not exist or cannot be loaded.',
];
}
}

Example 8: Integration with Event System Service

Complete integration example:

namespace App\Services;

use JobMetric\EventSystem\Facades\EventSystem;
use JobMetric\EventSystem\Http\Requests\StoreEventSystemRequest;

class EventBindingService
{
public function createBinding(array $data): array
{
// Validate and normalize
$dto = dto($data, StoreEventSystemRequest::class);

// Store binding
$response = EventSystem::store($dto);

if ($response->isSuccess()) {
return [
'success' => true,
'message' => $response->getMessage(),
'data' => $response->getData()->toArray(),
];
}

return [
'success' => false,
'message' => $response->getMessage(),
'errors' => $response->getErrors(),
];
}
}

Validation Flow

HTTP Request Flow

// 1. Request arrives at controller
public function store(StoreEventSystemRequest $request)

// 2. Laravel calls authorize()
$request->authorize(); // Returns true by default

// 3. Laravel calls prepareForValidation()
$request->prepareForValidation(); // Normalizes data

// 4. Laravel validates using rules()
$request->rules(); // Returns validation rules

// 5. If validation passes, returns validated data
$request->validated(); // Returns normalized, validated array

// 6. If validation fails, redirects back with errors

Programmatic Flow

// 1. Prepare input data
$input = ['name' => 'user.created', ...];

// 2. Normalize data (optional, but recommended)
$normalized = StoreEventSystemRequest::normalize($input);

// 3. Convert to DTO (validates automatically)
$dto = dto($normalized, StoreEventSystemRequest::class);

// 4. Use validated DTO
EventSystem::store($dto);

Error Handling

Validation Errors

When validation fails, the request returns errors:

{
"errors": {
"name": [
"The name field is required."
],
"event": [
"The event field is required.",
"The event class does not exist."
],
"listener": [
"The listener class does not exist."
]
}
}

Handling in Controller

public function store(StoreEventSystemRequest $request)
{
// If we reach here, validation passed
$validated = $request->validated();

// Use validated data
$response = EventSystem::store($validated);

return response()->json($response);
}

Handling Validation Failures

Laravel automatically handles validation failures:

// If validation fails, Laravel:
// 1. Redirects back (for web requests)
// 2. Returns 422 JSON response (for API requests)
// 3. Includes validation errors in response

Best Practices

1. Always Use Type Hints

// Good
public function store(StoreEventSystemRequest $request)

// Avoid
public function store(Request $request)

2. Use DTO for Programmatic Usage

// Good: Normalize and validate
$dto = dto($input, StoreEventSystemRequest::class);

// Avoid: Direct array usage
EventSystem::store($input); // May fail validation

3. Override Authorization

// Good: Check permissions
public function authorize(): bool
{
return $this->user()->can('create', Event::class);
}

4. Provide Custom Messages

// Good: User-friendly messages
public function messages(): array
{
return [
'name.unique' => 'This event binding name is already in use.',
];
}

5. Use Class Constants

// Good: Use class constants
'event' => App\Events\UserCreated::class

// Avoid: String literals
'event' => 'App\Events\UserCreated'

Common Mistakes

Mistake 1: Not Using DTO for Programmatic Usage

// Bad: Direct array usage
EventSystem::store($input);

// Good: Validate first
$dto = dto($input, StoreEventSystemRequest::class);
EventSystem::store($dto);

Mistake 2: Forgetting Authorization

// Bad: No authorization check
public function authorize(): bool
{
return true; // Allows anyone
}

// Good: Check permissions
public function authorize(): bool
{
return $this->user()->can('create', Event::class);
}

Mistake 3: Not Handling Normalization

// Bad: May have empty strings
$input = ['description' => ''];

// Good: Normalize first
$normalized = StoreEventSystemRequest::normalize($input);

Mistake 4: Using Wrong Class Names

// Bad: Typo in class name
'event' => 'App\Events\UserCreatd' // Missing 'e'

// Good: Use class constants
'event' => App\Events\UserCreated::class