Eloquent Deep Dive

September 29, 2024

Eloquent Deep Dive

I encountered another unique problem that I've been struggling to find a great solution for. This ties back to the other day when I talked about working with databases you don't maintain or have control over.

Here is the situation. I have one to one relationship I am trying to define; an Order has Shipping. In both tables there is an INVOICE column that is defined as an nvarchar(15). In the Order table, the INVOICE values are front padded with however many extra spaces are needed in order to fill the 15 characters, ' 265039'. While in the Shipping table, the INVOICE values are as you’d expect '265039'

Because of this the standard hasOne and belongsTo relationships will not work. They will create queries that resemble the following.

-- Will return no results since Shipping INVOICE does not have the padding
SELECT
  *
FROM
  [SHIPPING]
WHERE
  [SHIPPING].[INVOICE] = '          12345';

-- Will also return no results since Order INVOICE values have paddded
SELECT
  *
FROM
  [ORDERS]
WHERE
  [ORDERS].[INVOICE] = '12345'

This led me to taking a deep dive into how Eloquent builds up the queries for these relationships.

My somewhat viable solution

One thing I have been able to do with mild success is on the Shipping and Order models is add an invoice attribute that will either pad or trim the Invoice value when it is accessed

// Shipping.php
public function invoice(): Attribute  
{  
    return Attribute::make(  
        get: fn(string $value) => Str::padLeft($value, 15)  
    );
}

// Order.php
public function invoice(): Attribute  
{  
    return Attribute::make(  
        get: fn(string $value) => Str::ltrim(Str::rtrim($value))  
    );
}

I haven't fully tested or committed to this just yet, just what I am currently exploring. So far this does allow me to call the relationship off of each model.

Order::find($orderId)->shipping;
Shipping::find($shipingId)->order

However this does not currently work with eager loading.

Order::find($orderId)->with("shipping");
Shipping::find($shipingId)->with("order")

© 2024 Terrence Eisenhower. All rights reserved.