1

I have a relatively complex array in PHP that needs to be sorted in a specific way but the number of filters and sorts is a bit on the complex side that a simple solution seems to be escaping me.

The Problem: We have products in an order that need to be filtered into "shipto" groups based on the following criteria: Date the product can be shipped, if the product can be grouped with other products, and in which warehouse(s) the product can be shipped from. If 2 products have the same date, warehouse, and allow grouping then they are placed together in the same "shipto".

Current Solution (Not fully realized)

When I extract an order I traverse the items in it and build an array with the following information (FYI, this probably contains more info than I need to solve this problem)

$allProducts = array();
$today = date("Ymd");

/* If the product is being shipped now, put in the Today ShipTo dated 00000000 */
if (($today > $start) && ($today < $end)) {
    array_push($allProducts, array('ship' => '00000000', 'defaultwarehouse' => $defaultwarehouse, 'warehouse' => $warehouse, 'group' => $group,'product' => $product, 'start_month' => $start_month, 'start_day' => $start_day, 'end_month' => $end_month, 'end_day' => $end_day, 'description' => $description, 'qty_ordered' => $qty_ordered, 'row_total' => $row_total, 'price' => $price, 'tax_amount' => $tax_amount, 'shipping_group' => $shippingGroup, 'today' => $today, 'end' => $end, 'start' => $start ) );
} else {
    /* If the product is not being shipped today, put in a Group that matches the starts date for the ShipTo */
    array_push($allProducts, array('ship' => $start, 'defaultwarehouse' => $defaultwarehouse, 'warehouse' => $warehouse, 'group' => $group, 'product' => $product, 'start_month' => $start_month, 'start_day' => $start_day, 'end_month' => $end_month, 'end_day' => $end_day, 'description' => $description, 'qty_ordered' => $qty_ordered, 'row_total' => $row_total, 'price' => $price, 'tax_amount' => $tax_amount, 'shipping_group' => $shippingGroup, 'today' => $today, 'end' => $end, 'start' => $start  ));
}
endif;

Where $defaultwarehouse is a number representing the default warehouse (i.e. 1), $warehouse is all of the possible warehouses a product can be in (i.e. 1,2), $start is the date a product can first be shipped (i.e. 20121201 for Dec 1, 2012; Ymd, 00000000 represents today so they can be numerically sorted) and $group is a boolean saying if the product can or can not be shipped with other items (i.e. 1 for yes, 0 for no)

My original idea here was to sort the array based on group, then on warehouse, then on start date. I would then traverse the array to build the "shipto"s and when certain components of the array change (like Warehouse or Start) I would close the previous shipto and start a new one. If I take Group and Multiple Warehouses out of the equation I can get this logic to work. But my task requires I have them in so I am running into the following complications.

First, after I sort by Group, I really want to do 2 sub-sorts of Group=Yes and Group=No for the rest of the filters. This lead me to think that maybe I should be separating the array into 2 arrays and sorting them similarly but separately. It seems inefficient to do it this way but I am not sure.

Second, since warehouse can be a comma separated value, how can I filter on that and get the proper matches. i.e. if I have 3 products where their warehouse value is 1:1,2:3 this should group into 2 shiptos. One for 1:1,2 and a Second for 3.

Thoughts on the problem

My feeling is the way I am thinking about this problem with filtering the items into a traversable array may not be the best way to tackle it. It may be that I need to push the order items individually into a new "Shipments" array that checks each item against all current "Shipments". But I am also not exactly sure on how that would work. Or there may be a different way I am not thinking about at all about how to achieve this.

Example Array Data (Extra Data removed for simplicity):

[0]=> 
 'ship' => 00000000
 'defaultwarehouse' => 1
 'warehouse' => 1
 'group' => 1
 'sku' => 'ABC123'
[1]=>
 'ship' => 00000000
 'defaultwarehouse' => 1
 'warehouse' => 1,2
 'group' => 1
 'sku' => 'DEF234'
[2]=>
 'ship' => 00000000
 'defaultwarehouse' => 2
 'warehouse' => 1,2
 'group' => 1
 'sku' => 'GHI567'
[3]=>
 'ship' => 20121220
 'defaultwarehouse' => 1
 'warehouse' => 1,2
 'group' => 1
 'sku' => 'JKL890'
[4]=>
 'ship' => 20121220
 'defaultwarehouse' => 1
 'warehouse' => 1,2
 'group' => 1
 'sku' => 'MNO123'
[5]=>
 'ship' => 20130401
 'defaultwarehouse' => 1
 'warehouse' => 1
 'group' => 1
 'sku' => 'PQR456'
[6]=>
 'ship' => 20130401
 'defaultwarehouse' => 1
 'warehouse' => 1
 'group' => 0
 'sku' => 'STU789'

This should result in 5 "shipto" groups:

shipto[1] => ABC123, DEF234 (Base "group" for all other comparisons)
shipto[2] => GHI567 (Default warehouse does not match, previous shiptos)
shipto[3] => JKL890, MNO123 (Different shipping date)
shipto[4] => PRQ456 (Different shipping date from all others)
shipto[5] => STU789 (Can not be grouped with other shipments)
1
  • XML anyone? XPath is much more powerful and was built for complex querying. Unless we're talking multi-MB data here. Commented Dec 3, 2012 at 17:16

2 Answers 2

1

Is it possible for you to store the data in a database or somewhere similar? It sounds like your data is pretty complex, and storing it in a database would make the sorting you're looking to do a lot easier.

Sign up to request clarification or add additional context in comments.

3 Comments

The items are already being exported from a database as it is associated with the order. Those individual items are then being given the additional data from other tables for the group, shipping dates, and warehouse parts. I am not sure if re-inserting them temporarily into the database is a viable possibility.
Hmmm...can you restructure your queries so that the the sorting is done for you coming out of the database? And maybe use a different query so that the data comes out grouped how you need it? I say this because it is typically easier to get all the data sorted for you up front rather than try to do it in a home grown algorithm in your own code.
SOrry for the delay but I will look into the options I have. My feeling is that the additional data would force a reinsertion selection but that may be no worse than home grown. Thanks!
0

In the end this problem got even more complex and I generally threw away the concept of being able to sort logically and applying sub-sorts to a single array or SQL query. The business logic changed so much that keeping this all straight made no sense in one dimension.

The final logic applies 4 levels of filtering so what I did was isolate each step of logic and filter the previous array into a new array with the orders in their proper place. It is NOT the most efficient way to handle this but it is very readable and allows me to clearly see how each order is getting sorted at each step of the process. The "sorted" array is 4 levels deep but allows me to cherry pick each shipment for proper display.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.