laravel Form Request = if button was clicked

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Laravel Form Requests: Determining Action Based on Submitted Data

Dealing with conditional validation logic—where the rules for a field depend entirely on which action (Save, Update, Delete) the user intends to perform—is a very common requirement in web applications. When using Laravel's powerful Form Request system, developers often run into this challenge: how do we tell the request which button was clicked so we can apply dynamic validation rules?

This guide will walk you through why directly checking $_POST inside your Form Request is discouraged and show you the proper, idiomatic Laravel way to handle context-aware validation.

The Pitfall of Direct Superglobal Access in Form Requests

You attempted to solve this by accessing the global $_POST array within your rules() method:

// Incorrect approach attempt
public function rules()
{
    $myrule = [ 'name' => 'required', 'age' => 'required' ];

    if (isset($_POST['save'])) // This is problematic
    {
        $myrule['application_form'] = 'required';
    }
    // ... and so on
    return $myrule;
}

While this code might seem to work initially, it violates the principles of separation of concerns that Laravel encourages. Form Requests are designed to validate data sent via the request object itself, not raw superglobals. Relying on $_POST makes your validation logic tightly coupled to the HTTP layer and less portable. Furthermore, when using Form Requests, you should aim to keep the validation rules as declarative as possible, rather than implementing complex branching logic inside the rule definition itself.

The Correct Approach: Contextual Validation via Request Data

The most robust way to solve this is to assume that the necessary context (which action was requested) is sent along with the form data. Instead of checking the raw post data, you should check for a specific field that signals the intent.

In your case, if you have separate Save and Update actions, these actions must typically be represented by hidden input fields or separate, distinct POST requests where the context is explicitly named.

Step 1: Structure Your Input Data Correctly

Ensure that when the user submits the form, they are sending a clear indicator of the intended action. A common pattern is to include a hidden field or a specific field which dictates the mode.

For example, instead of relying on separate $_POST['save'] checks, you should check for the value of a field within the request data.

Step 2: Implementing Conditional Rules in rules()

If your form always submits data keyed by certain names (e.g., name, age, and a mode selector), you can use Laravel's built-in conditional rule syntax, which is cleaner than manual PHP branching.

Let’s assume you have a field called action that can be either 'save' or 'update'.

// App\Http\Requests\RegistrationRequest.php

public function rules()
{
    $rules = [ 
        'name' => 'required', 
        'age' => 'required',
        'application_form' => 'required' // Default rule, will be conditionally modified
    ];

    // Check the submitted data for the action type
    if ($this->input('action') === 'save') {
        // If 'save' is selected, application_form must be present.
        $rules['application_form'] = 'required';
    } elseif ($this->input('action') === 'update') {
        // If 'update' is selected, we might allow the field to be optional if it wasn't provided (e.g., if you are only updating some fields).
        $rules['application_form'] = 'required_without:is_application_form'; // Example of conditional rule logic
    }

    return $rules;
}

Note on the example above: Although we are still using an if/elseif block, we are now checking $this->input('action'), which safely retrieves data from the request object, making the process much safer and more aligned with Laravel's architecture. This pattern is perfectly acceptable when complex, multi-stage logic is required within validation.

Best Practice: Decoupling Logic in the Controller

While conditional rules can be placed in the Request, for very complex scenarios, a cleaner approach is to keep the Request focused purely on validation and move the business logic (determining the specific rules) into the Controller.

In your controller method, you can inspect the request data first and then dynamically build the validation rules:

// In your Controller method
public function store(RegistrationRequest $request)
{
    $data = $request->validated();
    $rules = $request->rules(); // Get the base rules

    if ($request->input('action') === 'save') {
        // Apply save-specific logic here
        $rules['application_form'] = 'required';
    } elseif ($request->input('action') === 'update') {
        // Apply update-specific logic here
        $rules['application_form'] = 'required_without:is_application_form';
    }

    // Re-validate using the dynamically generated rules if necessary, 
    // or ensure your initial request setup handles this dynamic change.
    // For simple validation changes, modifying $request->validate() might be cleaner.
    $validated = $request->validate($rules);

    // ... proceed with saving data
}

Conclusion

When building robust applications in Laravel, always prioritize using the framework's intended mechanisms over direct access to raw PHP superglobals like $_POST. While you can achieve conditional validation by inspecting the request data within your Form Request, it is often cleaner and more maintainable to keep complex decision-making logic residing in the Controller where it interfaces with the business layer. By focusing on validated input rather than raw HTTP data, you ensure your code remains scalable and adheres to Laravel's architectural philosophy, making your application stronger, much like following best practices outlined by teams at laravelcompany.com.