Skip to main content

StoreFlowRequest

Form request class for validating Flow creation data. This request handles validation for creating new workflow flows with multi-language support, date ranges, and cross-field validation.

Namespace

JobMetric\Flow\Http\Requests\Flow\StoreFlowRequest

Overview

The StoreFlowRequest validates incoming data when creating a new Flow entity. It ensures:

  • Required fields are present
  • Multi-language translations are valid
  • Date ranges are logical (active_from before or equal to active_to)
  • Field types and constraints are correct
  • Translation uniqueness across flows

Validation Rules

Required Fields

FieldRuleDescription
translationrequired|arrayMulti-language translation data
translation.{locale}required|arrayTranslation data for each active locale
translation.{locale}.namerequired|stringFlow name in each locale (must be unique)
subject_typerequired|string|max:255Model class name that uses this flow

Optional Fields

FieldRuleDescription
subject_scopenullable|string|max:255Optional scope identifier
subject_collectionnullable|string|max:255Optional collection identifier
versionsometimes|integer|min:1Flow version number (defaults to 1)
is_defaultsometimes|booleanWhether this is the default flow
statussometimes|booleanActive/inactive status
active_fromnullable|dateStart date for active window
active_tonullable|dateEnd date for active window
channelnullable|string|max:64Channel identifier
orderingsometimes|integer|min:0Display order
rollout_pctnullable|integer|between:0,100Rollout percentage (0-100)
environmentnullable|string|max:64Environment identifier
translation.{locale}.descriptionnullable|stringOptional description in each locale

Cross-Field Validation

The request includes custom validation in withValidator():

Active Window Validation

If both active_from and active_to are provided, active_from must be before or equal to active_to:

// ✅ Valid
'active_from' => '2024-01-01',
'active_to' => '2024-12-31',

// ❌ Invalid
'active_from' => '2024-12-31',
'active_to' => '2024-01-01',

Translation Validation

Name Uniqueness

The translation.{locale}.name field is validated for uniqueness using TranslationFieldExistRule:

  • Checks if a flow with the same name already exists in the same locale
  • Prevents duplicate flow names within the same language
  • Trims whitespace before validation

Required Locales

All active locales (from Language::getActiveLocales()) must have translation data:

// If active locales are ['en', 'fa']
// Both must be provided:
'translation' => [
'en' => ['name' => 'Order Processing'],
'fa' => ['name' => 'پردازش سفارش'],
]

Usage Examples

Basic Flow Creation

use JobMetric\Flow\Http\Requests\Flow\StoreFlowRequest;
use JobMetric\Flow\Facades\Flow;

// In controller
public function store(StoreFlowRequest $request)
{
$validated = $request->validated();

$flow = Flow::store($validated);

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

Complete Request Data

$requestData = [
'translation' => [
'en' => [
'name' => 'Order Processing Workflow',
'description' => 'Handles order processing from creation to delivery',
],
'fa' => [
'name' => 'گردش کار پردازش سفارش',
'description' => 'پردازش سفارش از ایجاد تا تحویل',
],
],
'subject_type' => 'App\Models\Order',
'subject_scope' => 'ecommerce',
'version' => 1,
'is_default' => true,
'status' => true,
'active_from' => '2024-01-01',
'active_to' => '2024-12-31',
'channel' => 'web',
'ordering' => 0,
'rollout_pct' => 100,
'environment' => 'production',
];

Minimal Request Data

$requestData = [
'translation' => [
'en' => ['name' => 'Simple Workflow'],
],
'subject_type' => 'App\Models\Document',
];

With Active Window

$requestData = [
'translation' => [
'en' => ['name' => 'Seasonal Workflow'],
],
'subject_type' => 'App\Models\Product',
'active_from' => '2024-06-01',
'active_to' => '2024-08-31', // Summer season
];

Custom Attributes

The request provides custom attribute names for validation error messages:

// Error messages will use these labels:
'translation' => 'Translation'
'translation.*.name' => 'Name'
'subject_type' => 'Subject Type'
'active_from' => 'Active From'
// ... etc

Authorization

The authorize() method returns true by default. Override in your application if you need custom authorization logic:

// In your custom request class extending StoreFlowRequest
public function authorize(): bool
{
return $this->user()->can('create', Flow::class);
}

Integration with Flow Service

The request is automatically used by the Flow::store() method:

use JobMetric\Flow\Facades\Flow;

// The service automatically validates using StoreFlowRequest
$flow = Flow::store([
'translation' => [...],
'subject_type' => 'App\Models\Order',
// ... other fields
]);

Error Handling

Validation Errors

When validation fails, Laravel returns a JSON response with error messages:

{
"message": "The given data was invalid.",
"errors": {
"translation.en.name": [
"The translation.en.name field is required."
],
"subject_type": [
"The subject type field is required."
],
"active_from": [
"The active from must be before active to."
]
}
}

Handling in Controllers

public function store(StoreFlowRequest $request)
{
try {
$flow = Flow::store($request->validated());
return response()->json($flow, 201);
} catch (\Exception $e) {
return response()->json([
'message' => 'Failed to create flow',
'error' => $e->getMessage()
], 500);
}
}

Best Practices

  1. Always provide all active locales: Ensure translation data exists for all active locales

    // ✅ Good
    $locales = Language::getActiveLocales();
    foreach ($locales as $locale) {
    $data['translation'][$locale] = ['name' => '...'];
    }
  2. Validate date ranges: Always ensure active_from is before or equal to active_to when both are provided

    // ✅ Good
    if ($from && $to && strtotime($from) > strtotime($to)) {
    // Handle error
    }
  3. Use meaningful names: Flow names should be descriptive and unique

    // ✅ Good
    'name' => 'Order Processing Workflow v2'

    // ❌ Bad
    'name' => 'Flow 1'
  4. Set appropriate defaults: Use is_default and status appropriately

    // Only one flow per subject_type should be default
    'is_default' => true, // Only for the primary flow
    'status' => true, // Active flows only