DEV Community

Zubair Mohsin
Zubair Mohsin

Posted on

Refactoring "if" statements with lookup arrays in PHP/Laravel

Let's dive right into an example.

I was working with third party JSON data which arrives from Webhook request. That data contains information about a Customer. Our interest was to get the "Phone Number" of that customer.

NOTE: this is third party data and we have no control over it.

There were four possible places where we could find Phone Number in that data.

  • Directly on incoming data object ( first level )
  • In "Customer" object inside data object
  • In "shipping_address" object inside data object
  • In "billing_address" object

These objects may or may not exist all in same time in a Webhook therefore I had to check with property_exists.

    protected static function extractPhone(object $webhookData): ?string 
    {
        if($webhookData->phone){
            return $webhookData->phone;
        }


        if(property_exists($webhookData,'customer') && $webhookData->customer->phone){
            return $webhookData->customer->phone;
        }

        if(property_exists($webhookData, 'shipping_address') && $webhookData->shipping_address->phone){
            return $webhookData->shipping_address->phone;
        }

        if(property_exists($webhookData, 'billing_address') && $webhookData->billing_address->phone){
            return $webhookData->billing_address->phone;
        }

        return null;
    }

Now let's refactor this code with "lookup" array.

We can make an array of "properties" that we need to check, right?


$lookupProperties = ['customer', 'shipping_address', 'billing_address'];

and then loop over these properties like below:

foreach ($lookupProperties as $lookupProperty){
    if(property_exists($lookupProperty, $webhookData) && $webhookData->{$lookupProperty}->phone){
                return $webhookData->{$lookupProperty}->phone;
     }
}

Now our method looks like below:

    protected static function extractPhone(object $webhookData): ?string 
    {
        if($webhookData->phone){
            return $webhookData->phone;
        }

        $lookupProperties = ['customer', 'shipping_address', 'billing_address'];

        foreach ($lookupProperties as $lookupProperty){
            if(property_exists($lookupProperty, $webhookData) && $webhookData->{$lookupProperty}->phone){
                return $webhookData->{$lookupProperty}->phone;
            }
        }

        return null;
    }

Less lines of code and we have the ability to just add new property in $lookupProperties if third party data changes in future.

Oldest comments (2)

Collapse
 
sznroe profile image
Sujan Rai

Thanks

Collapse
 
aleksikauppila profile image
Aleksi Kauppila

That request data looks to be a handful to deal with and raises some questions about the design of the data:

  • Why phone number in top level?
  • Why phone number in billing_address?
  • Why phone number in shipping_address?
  • Why the duplication?

After we've accepted the fact the data is what it is, we still have at least one big issue to handle.

  • What if the data is not consistent? What if we find two different phone numbers in the data? Which one do we prioritize over another.

To me it seems there's not much room to move around the problem. We'll have to parse the data somehow and it's going to be messy.

The trade off looks to be around "explicit vs. dynamic" algorithm.