DEV Community

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

Posted on

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.

Top comments (1)

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.