DEV Community

Cover image for Mastering Conditional Logic in Laravel with `when()` and `unless()` Methods: Real-Life Examples
Asfia Aiman
Asfia Aiman

Posted on

2

Mastering Conditional Logic in Laravel with `when()` and `unless()` Methods: Real-Life Examples

Laravel is a powerful PHP framework known for its elegant syntax and robust features. One such feature introduced in Laravel 11.35.0 is the when() and unless() methods, part of the Conditionable trait. These methods provide a more readable, efficient way to handle conditional logic, improving the maintainability of your code. In this article, we’ll explore how to use these methods in real-life scenarios, demonstrating how they can streamline complex conditional logic in Laravel applications.

1. Dynamic Role Assignment Based on User Input

Imagine you’re building a user registration form where the user selects a role. Depending on the role, you want to assign different permissions or actions after creating the user.

Without when():

if ($request->has('role')) {
    $user->assignRole($request->input('role'));
}
Enter fullscreen mode Exit fullscreen mode

With when():

$user->when($request->has('role'), function ($user) use ($request) {
    $user->assignRole($request->input('role'));
});
Enter fullscreen mode Exit fullscreen mode

In this case, we only assign a role if the role input is present. The when() method makes it concise, and the block of code only executes when the condition is true.

2. Dynamic Validation Rules

Suppose you’re building a form where certain fields should only be validated if a specific condition is met. For example, the email field should only be required if the user selects the "newsletter" option.

Without when():

$rules = [
    'email' => 'nullable',
];

if ($request->has('newsletter')) {
    $rules['email'] = 'required|email';
}

$request->validate($rules);
Enter fullscreen mode Exit fullscreen mode

With when():

$request->when($request->has('newsletter'), function () use ($request) {
    $request->validate([
        'email' => 'required|email',
    ]);
});
Enter fullscreen mode Exit fullscreen mode

This is a cleaner and more readable way to apply conditional validation logic using when().

3. Conditional Data Merging for Specific Operations

In an e-commerce platform, you might want to apply a discount only if a specific coupon code is provided. Let's merge the discount data dynamically based on whether the coupon exists.

Without when():

$data = [
    'total_price' => $cart->totalPrice(),
];

if ($request->has('coupon_code')) {
    $coupon = Coupon::where('code', $request->input('coupon_code'))->first();
    if ($coupon) {
        $data['discount'] = $coupon->discount_amount;
    }
}

return response()->json($data);
Enter fullscreen mode Exit fullscreen mode

With when():

$data = [
    'total_price' => $cart->totalPrice(),
];

$data = $data->when($request->has('coupon_code'), function ($data) use ($request) {
    $coupon = Coupon::where('code', $request->input('coupon_code'))->first();
    if ($coupon) {
        $data['discount'] = $coupon->discount_amount;
    }
    return $data;
});

return response()->json($data);
Enter fullscreen mode Exit fullscreen mode

Here, we apply a conditional discount based on the coupon code in a more streamlined and chainable way.

4. Simplifying Conditional Logic for User Status

Let’s say you have a system where you want to send a different message depending on whether a user is active or inactive.

Without unless():

if (!$user->isActive()) {
    return "Your account is inactive. Please contact support.";
} else {
    return "Welcome back!";
}
Enter fullscreen mode Exit fullscreen mode

With unless():

return $user->unless($user->isActive(), function () {
    return "Your account is inactive. Please contact support.";
})->otherwise(function () {
    return "Welcome back!";
});
Enter fullscreen mode Exit fullscreen mode

Using unless() here helps condense the conditional logic into a single return statement.

5. Combining when() and unless() for Complex Flows

You can also combine when() and unless() for more complex conditional flows. For example, handling different user types (admin, guest, etc.) and showing them specific content.

$variable->when($user->isAdmin(), function ($variable) {
    return $variable->adminDashboard();
})->unless($user->isAdmin(), function ($variable) {
    return $variable->guestDashboard();
});
Enter fullscreen mode Exit fullscreen mode

6. Payment Gateway Integration Based on User's Payment Method

Imagine you’re implementing a payment system where the payment method chosen by the user determines the flow of execution, such as whether to use a credit card, PayPal, or Bitcoin.

Without when():

if ($request->input('payment_method') == 'credit_card') {
    // Handle credit card payment logic
} elseif ($request->input('payment_method') == 'paypal') {
    // Handle PayPal payment logic
} elseif ($request->input('payment_method') == 'bitcoin') {
    // Handle Bitcoin payment logic
}
Enter fullscreen mode Exit fullscreen mode

With when():

$request->when($request->input('payment_method') == 'credit_card', function () {
    // Handle credit card payment logic
})->when($request->input('payment_method') == 'paypal', function () {
    // Handle PayPal payment logic
})->when($request->input('payment_method') == 'bitcoin', function () {
    // Handle Bitcoin payment logic
});
Enter fullscreen mode Exit fullscreen mode

This makes your payment handling more readable and simplifies the conditional logic for payment method selection.

7. Real Estate Property Price Calculation with Discounts

For a real estate application, if a user is a first-time buyer or using a special promo code, you might apply a discount to the property price.

Without when():

$price = $property->price;

if ($request->has('first_time_buyer')) {
    $price -= 5000; // Discount for first-time buyers
}

if ($request->has('promo_code')) {
    $promo = PromoCode::where('code', $request->input('promo_code'))->first();
    if ($promo) {
        $price -= $promo->discount;
    }
}

return response()->json(['price' => $price]);
Enter fullscreen mode Exit fullscreen mode

With when():

$price = $property->price;

$price = $price->when($request->has('first_time_buyer'), function ($price) {
    return $price - 5000; // Discount for first-time buyers
});

$price = $price->when($request->has('promo_code'), function ($price) use ($request) {
    $promo = PromoCode::where('code', $request->input('promo_code'))->first();
    return $promo ? $price - $promo->discount : $price;
});

return response()->json(['price' => $price]);
Enter fullscreen mode Exit fullscreen mode

This way, the code for calculating the price is cleaner and easier to maintain.

8. Medical Appointments with Insurance Verification

In a medical app, an appointment's payment might depend on whether the user has insurance, and you may need to verify it if provided.

Without when():

$payment = $appointment->cost;

if ($request->has('insurance_provider')) {
    $insurance = Insurance::where('provider', $request->input('insurance_provider'))->first();
    if ($insurance) {
        $payment -= $insurance->coverage;
    }
}

return response()->json(['payment' => $payment]);
Enter fullscreen mode Exit fullscreen mode

With when():

$payment = $appointment->cost;

$payment = $payment->when($request->has('insurance_provider'), function ($payment) use ($request) {
    $insurance = Insurance::where('provider', $request->input('insurance_provider'))->first();
    return $insurance ? $payment - $insurance->coverage : $payment;
});

return response()->json(['payment' => $payment]);
Enter fullscreen mode Exit fullscreen mode

This approach simplifies checking for insurance coverage and reduces clutter.

9. Bitcoin Price Adjustment Based on Market Conditions

Imagine you're building an app that allows users to buy Bitcoin, and the price fluctuates based on market conditions. If the market is volatile, you might want to add a fee to the price.

Without when():

$price = $bitcoin->currentPrice();

if ($market->isVolatile()) {
    $price += 100; // Add a volatility fee
}

return response()->json(['price' => $price]);
Enter fullscreen mode Exit fullscreen mode

With when():

$price = $bitcoin->currentPrice();

$price = $price->when($market->isVolatile(), function ($price) {
    return $price + 100; // Add a volatility fee
});

return response()->json(['price' => $price]);
Enter fullscreen mode Exit fullscreen mode

This simplifies the logic of applying a fee based on market volatility.

10. Conditional Product Availability in an E-commerce Store

Suppose you are building an e-commerce platform where products can only be shipped within certain regions. You want to check whether the product is available for a customer's location.

Without when():

$shippingFee = 0;

if ($customer->location == 'international') {
    $shippingFee = $product->internationalShippingFee();
} else {
    $shippingFee = $product->domesticShippingFee();
}

return response()->json(['shipping_fee' => $shippingFee]);
Enter fullscreen mode Exit fullscreen mode

With when():

$shippingFee = $product->domesticShippingFee();

$shippingFee = $shippingFee->when($customer->location == 'international', function ($shippingFee) use ($product) {
    return $product->internationalShippingFee();
});

return response()->json(['shipping_fee' => $shippingFee]);
Enter fullscreen mode Exit fullscreen mode

The when() method simplifies the conditional logic for determining shipping fees based on the customer's location.

11. Medical Treatment Plan Based on Patient's Health Conditions

Consider a healthcare application that assigns a treatment plan based on the patient's diagnosed health conditions. If the patient has a chronic condition, a long-term treatment plan might be suggested.

Without when():

$treatmentPlan = 'Standard Plan';

if ($patient->hasChronicCondition()) {
    $treatmentPlan = 'Chronic Care Plan';
}

return response()->json(['treatment_plan' => $treatmentPlan]);
Enter fullscreen mode Exit fullscreen mode

With when():

$treatmentPlan = 'Standard Plan';

$treatmentPlan = $treatmentPlan->when($patient->hasChronicCondition(), function ($treatmentPlan) {
    return 'Chronic Care Plan';
});

return response()->json(['treatment_plan' => $treatmentPlan]);
Enter fullscreen mode Exit fullscreen mode

This approach helps streamline the decision-making logic and makes it easier to handle more conditions in the future.


These examples demonstrate how the when() and unless() methods can be applied across various domains like payments, Bitcoin, real estate, and healthcare, making your Laravel code more readable, maintainable, and elegant. By embracing these methods, you can write cleaner code and enhance the maintainability of your Laravel applications.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (3)

Collapse
 
xwero profile image
david duymelinck • Edited

Seeing the examples the when and unless methods don't blow me out of the water.
I don't understand what is wrong with the using if statements? Most of the examples could be ternary statements.

$rules = [
    'email' =>  $request->has('newsletter') ?  'required|email'  : 'nullable',
];

$request->validate($rules);

// instead of
$rules = [
    'email' => 'nullable',
];

if ($request->has('newsletter')) {
    $rules['email'] = 'required|email';
}

$request->validate($rules);
Enter fullscreen mode Exit fullscreen mode

I also spotted an error in one of the examples.

$data = [
    'total_price' => $cart->totalPrice(),
];
// returns error
$data = $data->when($request->has('coupon_code'), // ...
// working
$data = collect($data)->when($request->has('coupon_code'), // ...
Enter fullscreen mode Exit fullscreen mode

I trained myself to write positive if statements, so the unless method is lost on me.
I don't see how the functions make code more readable, maintainable or elegant.
The methods make code even harder to read if you use the third parameter.

return $user->unless($user->isActive(), function () {
    return "Your account is inactive. Please contact support.";
})->otherwise(function () {
    return "Welcome back!";
});
// can be written as
return $user->unless($user->isActive(), 
 fn() => "Your account is inactive. Please contact support.",
fn() => "Welcome back!"
);
// plain php
return $user->isActive() ? "Welcome back!" :  "Your account is inactive. Please contact support.";
Enter fullscreen mode Exit fullscreen mode

Thank you for the post! I will keep writing php.

Collapse
 
asfiaaiman profile image
Asfia Aiman

Hello David,

yes you can use multiple if statements, ternary or switch cases where you want. However, this when() and unless() is another way of writing it, nothing else.

return $user->unless($user->isActive(),
fn() => "Your account is inactive. Please contact support.",
fn() => "Welcome back!"
);

is a cleaner way however, I personally believe that it is not reading friendly, so I do not prefer using it.

Collapse
 
xwero profile image
david duymelinck • Edited

I can understand the readability argument. A lot of people find a fluent API more readable.
My previous comment was more about preferences, and those are a million in a bunch.

So I want to give more rooted reasons why not to use the methods.

The when an unless methods are two function calls that have no other added value than readability. One of the low hanging fruits during code optimalisation is reducing function calls.

You also are writing more code instead of less because of the anonymous functions.

And you need to start with a class that has a Conditionable trait. I see people using this and make the context of the flow confusing because they bind it to an unrelated instance.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs