[{"data":1,"prerenderedAt":1048},["ShallowReactive",2],{"\u002Farticles\u002Fembrace-the-framework-order-fulfilment-with-collections":3,"article-series:embrace-the-framework":995},{"id":4,"title":5,"body":6,"description":978,"draft":979,"extension":980,"meta":981,"navigation":101,"path":982,"published":983,"seo":984,"seoDescription":985,"series":986,"seriesOrder":987,"stem":988,"tags":989,"updated":993,"__hash__":994},"articles\u002Farticles\u002Fembrace-the-framework-order-fulfilment-with-collections.md","Embrace the Framework: Make Order Fulfilment Clearer With Collections",{"type":7,"value":8,"toc":970},"minimark",[9,13,16,19,24,27,30,43,47,50,379,386,389,393,396,515,518,521,525,528,535,595,598,641,644,716,723,777,781,784,861,864,922,925,929,932,935,938,960,963,966],[10,11,12],"p",{},"A list of orders is rarely just a list of orders.",[10,14,15],{},"Once an application is doing real work, that list may need to tell us which orders can ship today, which are blocked by stock, which need manual review, and how that work should be divided between warehouses. It is a common piece of application logic, and it is surprisingly easy for it to become difficult to follow.",[10,17,18],{},"Laravel Collections are a great fit for this kind of work. They let us take a group of models and describe the decisions we need to make with them, one clear step at a time.",[20,21,23],"h2",{"id":22},"the-problem","The problem",[10,25,26],{},"Imagine a small ecommerce business preparing its daily warehouse pick lists. An order can be sent to the warehouse only when it has been paid for, has a shipping address, and every ordered item is in stock. Orders above $1,000 also need a quick manual review before they are released.",[10,28,29],{},"The outcome we want is straightforward:",[31,32,33,37,40],"ul",{},[34,35,36],"li",{},"a list of orders ready to ship, grouped by warehouse;",[34,38,39],{},"a list of orders blocked by stock; and",[34,41,42],{},"a list of high-value orders that need review.",[20,44,46],{"id":45},"a-functional-but-manual-approach","A functional but manual approach",[10,48,49],{},"Plain PHP can certainly handle this. A first version might look like this:",[51,52,57],"pre",{"className":53,"code":54,"language":55,"meta":56,"style":56},"language-php shiki shiki-themes github-light github-dark","$readyToShip = [];\n$blockedByStock = [];\n$requiresReview = [];\n\nforeach ($orders as $order) {\n    $allItemsInStock = true;\n\n    foreach ($order->items as $item) {\n        if (! $item->is_in_stock) {\n            $allItemsInStock = false;\n            break;\n        }\n    }\n\n    if (! $order->is_paid || $order->shipping_address === null) {\n        continue;\n    }\n\n    if (! $allItemsInStock) {\n        $blockedByStock[] = $order;\n        continue;\n    }\n\n    if ($order->total_in_cents >= 100000) {\n        $requiresReview[] = $order;\n        continue;\n    }\n\n    $readyToShip[$order->warehouse_id][] = $order;\n}\n","php","",[58,59,60,76,86,96,103,118,133,138,158,178,191,199,205,211,216,253,261,266,271,283,294,301,306,311,331,341,348,353,358,373],"code",{"__ignoreMap":56},[61,62,65,69,73],"span",{"class":63,"line":64},"line",1,[61,66,68],{"class":67},"sVt8B","$readyToShip ",[61,70,72],{"class":71},"szBVR","=",[61,74,75],{"class":67}," [];\n",[61,77,79,82,84],{"class":63,"line":78},2,[61,80,81],{"class":67},"$blockedByStock ",[61,83,72],{"class":71},[61,85,75],{"class":67},[61,87,89,92,94],{"class":63,"line":88},3,[61,90,91],{"class":67},"$requiresReview ",[61,93,72],{"class":71},[61,95,75],{"class":67},[61,97,99],{"class":63,"line":98},4,[61,100,102],{"emptyLinePlaceholder":101},true,"\n",[61,104,106,109,112,115],{"class":63,"line":105},5,[61,107,108],{"class":71},"foreach",[61,110,111],{"class":67}," ($orders ",[61,113,114],{"class":71},"as",[61,116,117],{"class":67}," $order) {\n",[61,119,121,124,126,130],{"class":63,"line":120},6,[61,122,123],{"class":67},"    $allItemsInStock ",[61,125,72],{"class":71},[61,127,129],{"class":128},"sj4cs"," true",[61,131,132],{"class":67},";\n",[61,134,136],{"class":63,"line":135},7,[61,137,102],{"emptyLinePlaceholder":101},[61,139,141,144,147,150,153,155],{"class":63,"line":140},8,[61,142,143],{"class":71},"    foreach",[61,145,146],{"class":67}," ($order",[61,148,149],{"class":71},"->",[61,151,152],{"class":67},"items ",[61,154,114],{"class":71},[61,156,157],{"class":67}," $item) {\n",[61,159,161,164,167,170,173,175],{"class":63,"line":160},9,[61,162,163],{"class":71},"        if",[61,165,166],{"class":67}," (",[61,168,169],{"class":71},"!",[61,171,172],{"class":67}," $item",[61,174,149],{"class":71},[61,176,177],{"class":67},"is_in_stock) {\n",[61,179,181,184,186,189],{"class":63,"line":180},10,[61,182,183],{"class":67},"            $allItemsInStock ",[61,185,72],{"class":71},[61,187,188],{"class":128}," false",[61,190,132],{"class":67},[61,192,194,197],{"class":63,"line":193},11,[61,195,196],{"class":71},"            break",[61,198,132],{"class":67},[61,200,202],{"class":63,"line":201},12,[61,203,204],{"class":67},"        }\n",[61,206,208],{"class":63,"line":207},13,[61,209,210],{"class":67},"    }\n",[61,212,214],{"class":63,"line":213},14,[61,215,102],{"emptyLinePlaceholder":101},[61,217,219,222,224,226,229,231,234,237,239,241,244,247,250],{"class":63,"line":218},15,[61,220,221],{"class":71},"    if",[61,223,166],{"class":67},[61,225,169],{"class":71},[61,227,228],{"class":67}," $order",[61,230,149],{"class":71},[61,232,233],{"class":67},"is_paid ",[61,235,236],{"class":71},"||",[61,238,228],{"class":67},[61,240,149],{"class":71},[61,242,243],{"class":67},"shipping_address ",[61,245,246],{"class":71},"===",[61,248,249],{"class":128}," null",[61,251,252],{"class":67},") {\n",[61,254,256,259],{"class":63,"line":255},16,[61,257,258],{"class":71},"        continue",[61,260,132],{"class":67},[61,262,264],{"class":63,"line":263},17,[61,265,210],{"class":67},[61,267,269],{"class":63,"line":268},18,[61,270,102],{"emptyLinePlaceholder":101},[61,272,274,276,278,280],{"class":63,"line":273},19,[61,275,221],{"class":71},[61,277,166],{"class":67},[61,279,169],{"class":71},[61,281,282],{"class":67}," $allItemsInStock) {\n",[61,284,286,289,291],{"class":63,"line":285},20,[61,287,288],{"class":67},"        $blockedByStock[] ",[61,290,72],{"class":71},[61,292,293],{"class":67}," $order;\n",[61,295,297,299],{"class":63,"line":296},21,[61,298,258],{"class":71},[61,300,132],{"class":67},[61,302,304],{"class":63,"line":303},22,[61,305,210],{"class":67},[61,307,309],{"class":63,"line":308},23,[61,310,102],{"emptyLinePlaceholder":101},[61,312,314,316,318,320,323,326,329],{"class":63,"line":313},24,[61,315,221],{"class":71},[61,317,146],{"class":67},[61,319,149],{"class":71},[61,321,322],{"class":67},"total_in_cents ",[61,324,325],{"class":71},">=",[61,327,328],{"class":128}," 100000",[61,330,252],{"class":67},[61,332,334,337,339],{"class":63,"line":333},25,[61,335,336],{"class":67},"        $requiresReview[] ",[61,338,72],{"class":71},[61,340,293],{"class":67},[61,342,344,346],{"class":63,"line":343},26,[61,345,258],{"class":71},[61,347,132],{"class":67},[61,349,351],{"class":63,"line":350},27,[61,352,210],{"class":67},[61,354,356],{"class":63,"line":355},28,[61,357,102],{"emptyLinePlaceholder":101},[61,359,361,364,366,369,371],{"class":63,"line":360},29,[61,362,363],{"class":67},"    $readyToShip[$order",[61,365,149],{"class":71},[61,367,368],{"class":67},"warehouse_id][] ",[61,370,72],{"class":71},[61,372,293],{"class":67},[61,374,376],{"class":63,"line":375},30,[61,377,378],{"class":67},"}\n",[10,380,381,382,385],{},"This works. It is also the kind of code that tends to grow awkwardly over time. It is doing several jobs at once, so a reader has to keep track of temporary state, ",[58,383,384],{},"continue"," statements, and the order in which each condition is checked.",[10,387,388],{},"If a new rule is added later, such as excluding orders with an expired delivery promise, there is one more branch to fit into an already busy loop.",[20,390,392],{"id":391},"start-with-the-question-being-asked","Start with the question being asked",[10,394,395],{},"With a Collection, we can make the first question more obvious:",[51,397,399],{"className":53,"code":398,"language":55,"meta":56,"style":56},"$ordersReadyToShip = $orders\n    ->filter(fn (Order $order) =>\n        $order->is_paid\n        && $order->shipping_address !== null\n        && $order->items->every(fn (OrderItem $item) => $item->is_in_stock)\n        && $order->total_in_cents \u003C 100000\n    );\n",[58,400,401,411,434,444,461,494,510],{"__ignoreMap":56},[61,402,403,406,408],{"class":63,"line":64},[61,404,405],{"class":67},"$ordersReadyToShip ",[61,407,72],{"class":71},[61,409,410],{"class":67}," $orders\n",[61,412,413,416,420,423,426,428,431],{"class":63,"line":78},[61,414,415],{"class":71},"    ->",[61,417,419],{"class":418},"sScJk","filter",[61,421,422],{"class":67},"(",[61,424,425],{"class":71},"fn",[61,427,166],{"class":67},[61,429,430],{"class":128},"Order",[61,432,433],{"class":67}," $order) =>\n",[61,435,436,439,441],{"class":63,"line":88},[61,437,438],{"class":67},"        $order",[61,440,149],{"class":71},[61,442,443],{"class":67},"is_paid\n",[61,445,446,449,451,453,455,458],{"class":63,"line":98},[61,447,448],{"class":71},"        &&",[61,450,228],{"class":67},[61,452,149],{"class":71},[61,454,243],{"class":67},[61,456,457],{"class":71},"!==",[61,459,460],{"class":128}," null\n",[61,462,463,465,467,469,472,474,477,479,481,483,486,489,491],{"class":63,"line":105},[61,464,448],{"class":71},[61,466,228],{"class":67},[61,468,149],{"class":71},[61,470,471],{"class":67},"items",[61,473,149],{"class":71},[61,475,476],{"class":418},"every",[61,478,422],{"class":67},[61,480,425],{"class":71},[61,482,166],{"class":67},[61,484,485],{"class":128},"OrderItem",[61,487,488],{"class":67}," $item) => $item",[61,490,149],{"class":71},[61,492,493],{"class":67},"is_in_stock)\n",[61,495,496,498,500,502,504,507],{"class":63,"line":120},[61,497,448],{"class":71},[61,499,228],{"class":67},[61,501,149],{"class":71},[61,503,322],{"class":67},[61,505,506],{"class":71},"\u003C",[61,508,509],{"class":128}," 100000\n",[61,511,512],{"class":63,"line":135},[61,513,514],{"class":67},"    );\n",[10,516,517],{},"The code now reads from left to right: take the orders and filter them to the ones ready to ship.",[10,519,520],{},"The benefit is not that a Collection always produces fewer lines. The benefit is that the important operation is visible. We are no longer manually building an array and managing the route each order takes through the loop.",[20,522,524],{"id":523},"split-the-work-into-useful-groups","Split the work into useful groups",[10,526,527],{},"Collections give us a few nice ways to separate a set of models without re-processing the original data repeatedly.",[10,529,530,531,534],{},"For example, ",[58,532,533],{},"partition"," divides a Collection into two Collections:",[51,536,538],{"className":53,"code":537,"language":55,"meta":56,"style":56},"[$ordersWithStock, $ordersBlockedByStock] = $orders\n    ->partition(fn (Order $order) =>\n        $order->items->every(fn (OrderItem $item) => $item->is_in_stock)\n    );\n",[58,539,540,549,565,591],{"__ignoreMap":56},[61,541,542,545,547],{"class":63,"line":64},[61,543,544],{"class":67},"[$ordersWithStock, $ordersBlockedByStock] ",[61,546,72],{"class":71},[61,548,410],{"class":67},[61,550,551,553,555,557,559,561,563],{"class":63,"line":78},[61,552,415],{"class":71},[61,554,533],{"class":418},[61,556,422],{"class":67},[61,558,425],{"class":71},[61,560,166],{"class":67},[61,562,430],{"class":128},[61,564,433],{"class":67},[61,566,567,569,571,573,575,577,579,581,583,585,587,589],{"class":63,"line":88},[61,568,438],{"class":67},[61,570,149],{"class":71},[61,572,471],{"class":67},[61,574,149],{"class":71},[61,576,476],{"class":418},[61,578,422],{"class":67},[61,580,425],{"class":71},[61,582,166],{"class":67},[61,584,485],{"class":128},[61,586,488],{"class":67},[61,588,149],{"class":71},[61,590,493],{"class":67},[61,592,593],{"class":63,"line":98},[61,594,514],{"class":67},[10,596,597],{},"That gives the warehouse team a useful exception list immediately. We can then work with the orders that do have stock:",[51,599,601],{"className":53,"code":600,"language":55,"meta":56,"style":56},"[$highValueOrders, $standardOrders] = $ordersWithStock\n    ->partition(fn (Order $order) => $order->total_in_cents >= 100000);\n",[58,602,603,613],{"__ignoreMap":56},[61,604,605,608,610],{"class":63,"line":64},[61,606,607],{"class":67},"[$highValueOrders, $standardOrders] ",[61,609,72],{"class":71},[61,611,612],{"class":67}," $ordersWithStock\n",[61,614,615,617,619,621,623,625,627,630,632,634,636,638],{"class":63,"line":78},[61,616,415],{"class":71},[61,618,533],{"class":418},[61,620,422],{"class":67},[61,622,425],{"class":71},[61,624,166],{"class":67},[61,626,430],{"class":128},[61,628,629],{"class":67}," $order) => $order",[61,631,149],{"class":71},[61,633,322],{"class":67},[61,635,325],{"class":71},[61,637,328],{"class":128},[61,639,640],{"class":67},");\n",[10,642,643],{},"Finally, the ready orders can be grouped by where they need to go:",[51,645,647],{"className":53,"code":646,"language":55,"meta":56,"style":56},"$ordersByWarehouse = $standardOrders\n    ->filter(fn (Order $order) =>\n        $order->is_paid && $order->shipping_address !== null\n    )\n    ->groupBy('warehouse_id');\n",[58,648,649,659,675,696,701],{"__ignoreMap":56},[61,650,651,654,656],{"class":63,"line":64},[61,652,653],{"class":67},"$ordersByWarehouse ",[61,655,72],{"class":71},[61,657,658],{"class":67}," $standardOrders\n",[61,660,661,663,665,667,669,671,673],{"class":63,"line":78},[61,662,415],{"class":71},[61,664,419],{"class":418},[61,666,422],{"class":67},[61,668,425],{"class":71},[61,670,166],{"class":67},[61,672,430],{"class":128},[61,674,433],{"class":67},[61,676,677,679,681,683,686,688,690,692,694],{"class":63,"line":88},[61,678,438],{"class":67},[61,680,149],{"class":71},[61,682,233],{"class":67},[61,684,685],{"class":71},"&&",[61,687,228],{"class":67},[61,689,149],{"class":71},[61,691,243],{"class":67},[61,693,457],{"class":71},[61,695,460],{"class":128},[61,697,698],{"class":63,"line":98},[61,699,700],{"class":67},"    )\n",[61,702,703,705,708,710,714],{"class":63,"line":105},[61,704,415],{"class":71},[61,706,707],{"class":418},"groupBy",[61,709,422],{"class":67},[61,711,713],{"class":712},"sZZnC","'warehouse_id'",[61,715,640],{"class":67},[10,717,718,719,722],{},"At this point, ",[58,720,721],{},"$ordersByWarehouse"," is a Collection where each value is another Collection of orders. That makes dispatching warehouse work clear too:",[51,724,726],{"className":53,"code":725,"language":55,"meta":56,"style":56},"$ordersByWarehouse->each(\n    fn (Collection $orders, int $warehouseId) =>\n        PrepareWarehousePickList::dispatch($warehouseId, $orders)\n);\n",[58,727,728,740,759,773],{"__ignoreMap":56},[61,729,730,732,734,737],{"class":63,"line":64},[61,731,721],{"class":67},[61,733,149],{"class":71},[61,735,736],{"class":418},"each",[61,738,739],{"class":67},"(\n",[61,741,742,745,747,750,753,756],{"class":63,"line":78},[61,743,744],{"class":71},"    fn",[61,746,166],{"class":67},[61,748,749],{"class":128},"Collection",[61,751,752],{"class":67}," $orders, ",[61,754,755],{"class":71},"int",[61,757,758],{"class":67}," $warehouseId) =>\n",[61,760,761,764,767,770],{"class":63,"line":88},[61,762,763],{"class":128},"        PrepareWarehousePickList",[61,765,766],{"class":71},"::",[61,768,769],{"class":418},"dispatch",[61,771,772],{"class":67},"($warehouseId, $orders)\n",[61,774,775],{"class":63,"line":98},[61,776,640],{"class":67},[20,778,780],{"id":779},"collections-make-reporting-less-painful-too","Collections make reporting less painful too",[10,782,783],{},"The same order data can answer useful operational questions without a new loop for every total.",[51,785,787],{"className":53,"code":786,"language":55,"meta":56,"style":56},"$summary = [\n    'orders_ready_to_ship' => $ordersReadyToShip->count(),\n    'orders_blocked_by_stock' => $ordersBlockedByStock->count(),\n    'ready_to_ship_value' => $ordersReadyToShip->sum('total_in_cents'),\n];\n",[58,788,789,799,818,834,856],{"__ignoreMap":56},[61,790,791,794,796],{"class":63,"line":64},[61,792,793],{"class":67},"$summary ",[61,795,72],{"class":71},[61,797,798],{"class":67}," [\n",[61,800,801,804,807,810,812,815],{"class":63,"line":78},[61,802,803],{"class":712},"    'orders_ready_to_ship'",[61,805,806],{"class":71}," =>",[61,808,809],{"class":67}," $ordersReadyToShip",[61,811,149],{"class":71},[61,813,814],{"class":418},"count",[61,816,817],{"class":67},"(),\n",[61,819,820,823,825,828,830,832],{"class":63,"line":88},[61,821,822],{"class":712},"    'orders_blocked_by_stock'",[61,824,806],{"class":71},[61,826,827],{"class":67}," $ordersBlockedByStock",[61,829,149],{"class":71},[61,831,814],{"class":418},[61,833,817],{"class":67},[61,835,836,839,841,843,845,848,850,853],{"class":63,"line":98},[61,837,838],{"class":712},"    'ready_to_ship_value'",[61,840,806],{"class":71},[61,842,809],{"class":67},[61,844,149],{"class":71},[61,846,847],{"class":418},"sum",[61,849,422],{"class":67},[61,851,852],{"class":712},"'total_in_cents'",[61,854,855],{"class":67},"),\n",[61,857,858],{"class":63,"line":105},[61,859,860],{"class":67},"];\n",[10,862,863],{},"If the finance or operations team needs a breakdown by payment method, the intent remains easy to follow:",[51,865,867],{"className":53,"code":866,"language":55,"meta":56,"style":56},"$revenueByPaymentMethod = $ordersReadyToShip\n    ->groupBy('payment_method')\n    ->map(fn (Collection $orders) => $orders->sum('total_in_cents'));\n",[58,868,869,879,893],{"__ignoreMap":56},[61,870,871,874,876],{"class":63,"line":64},[61,872,873],{"class":67},"$revenueByPaymentMethod ",[61,875,72],{"class":71},[61,877,878],{"class":67}," $ordersReadyToShip\n",[61,880,881,883,885,887,890],{"class":63,"line":78},[61,882,415],{"class":71},[61,884,707],{"class":418},[61,886,422],{"class":67},[61,888,889],{"class":712},"'payment_method'",[61,891,892],{"class":67},")\n",[61,894,895,897,900,902,904,906,908,911,913,915,917,919],{"class":63,"line":88},[61,896,415],{"class":71},[61,898,899],{"class":418},"map",[61,901,422],{"class":67},[61,903,425],{"class":71},[61,905,166],{"class":67},[61,907,749],{"class":128},[61,909,910],{"class":67}," $orders) => $orders",[61,912,149],{"class":71},[61,914,847],{"class":418},[61,916,422],{"class":67},[61,918,852],{"class":712},[61,920,921],{"class":67},"));\n",[10,923,924],{},"This is the kind of code that is pleasant to revisit later. The business question is visible in the variable name, and the transformation that answers it is visible in the Collection chain.",[20,926,928],{"id":927},"do-not-turn-every-chain-into-a-puzzle","Do not turn every chain into a puzzle",[10,930,931],{},"Collections are not an excuse to put all of an application's business rules into one enormous chain.",[10,933,934],{},"When a callback starts carrying a lot of domain knowledge, give that knowledge a name. A small private method, a query scope, or a custom Collection method can make the code much easier to understand.",[10,936,937],{},"For example, this is a useful point to stop repeating the same shipping rules:",[51,939,941],{"className":53,"code":940,"language":55,"meta":56,"style":56},"$ordersReadyToShip = $orders->readyToShip();\n",[58,942,943],{"__ignoreMap":56},[61,944,945,947,949,952,954,957],{"class":63,"line":64},[61,946,405],{"class":67},[61,948,72],{"class":71},[61,950,951],{"class":67}," $orders",[61,953,149],{"class":71},[61,955,956],{"class":418},"readyToShip",[61,958,959],{"class":67},"();\n",[10,961,962],{},"That is where custom Collections become particularly useful. Instead of merely transforming a list, we can teach a collection of orders what it means to be ready to ship.",[10,964,965],{},"That is the next step in this series.",[967,968,969],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":56,"searchDepth":78,"depth":78,"links":971},[972,973,974,975,976,977],{"id":22,"depth":78,"text":23},{"id":45,"depth":78,"text":46},{"id":391,"depth":78,"text":392},{"id":523,"depth":78,"text":524},{"id":779,"depth":78,"text":780},{"id":927,"depth":78,"text":928},"A practical look at using Laravel Collections to turn a confusing order fulfilment task into readable, testable code.",false,"md",{},"\u002Farticles\u002Fembrace-the-framework-order-fulfilment-with-collections","2026-07-25",{"title":5,"description":978},"Learn how Laravel Collections simplify order fulfilment by filtering, grouping, and summarising real application data.","embrace-the-framework","2","articles\u002Fembrace-the-framework-order-fulfilment-with-collections",[990,55,991,992],"laravel","collections","ecommerce",null,"6SHSare7SrztSlmQ3x2WXxn7fb0pjEAnpxt3Gchfs-w",[996,1001,1006,1011,1012,1017,1022,1027,1032,1036,1040,1044],{"path":997,"title":998,"published":999,"series":986,"seriesOrder":1000},"\u002Farticles\u002Fembrace-the-framework-custom-collections-for-subscriptions","Embrace the Framework: Put Subscription Business Rules in a Custom Collection","2026-07-28","3",{"path":1002,"title":1003,"published":1004,"series":986,"seriesOrder":1005},"\u002Farticles\u002Fembrace-the-framework-customer-eligibility-with-custom-collections","Embrace the Framework: Make Eligibility Rules Read Like Business Policy","2026-08-04","6",{"path":1007,"title":1008,"published":1009,"series":986,"seriesOrder":1010},"\u002Farticles\u002Fembrace-the-framework-operational-reports-with-collections","Embrace the Framework: Build Clear Operational Reports With Collections","2026-08-02","5",{"path":982,"title":5,"published":983,"series":986,"seriesOrder":987},{"path":1013,"title":1014,"published":1015,"series":986,"seriesOrder":1016},"\u002Farticles\u002Fembrace-the-framework-order-processing-pipeline-that-can-grow","Embrace the Framework: Build an Order Processing Pipeline That Can Grow","2026-08-06","7",{"path":1018,"title":1019,"published":1020,"series":986,"seriesOrder":1021},"\u002Farticles\u002Fembrace-the-framework-order-processing-with-pipelines","Embrace the Framework: Break Order Processing Into Steps With Pipelines","2026-07-31","4",{"path":1023,"title":1024,"published":1025,"series":986,"seriesOrder":1026},"\u002Farticles\u002Fembrace-the-framework-supplier-imports-with-collections-and-pipelines","Embrace the Framework: Combine Collections and Pipelines for Reliable Supplier Imports","2026-08-08","8",{"path":1028,"title":1029,"published":1030,"series":986,"seriesOrder":1031},"\u002Farticles\u002Fembrace-the-framework-why-working-with-laravel-beats-working-around-it","Embrace the Framework: Why Working With Laravel Beats Working Around It","2026-07-23","1",{"path":1033,"title":1034,"published":1035,"series":993,"seriesOrder":993},"\u002Farticles\u002Fsimple-search-helper","A Simple Laravel Search Helper","2023-08-06",{"path":1037,"title":1038,"published":1039,"series":993,"seriesOrder":993},"\u002Farticles\u002Fsvg-tidy-local-svg-optimiser","SVG Tidy: Clean and Optimise SVGs Locally","2026-07-21",{"path":1041,"title":1042,"published":1043,"series":993,"seriesOrder":993},"\u002Farticles\u002Ftools-i-use","Tools I Use","2024-05-26",{"path":1045,"title":1046,"published":1047,"series":993,"seriesOrder":993},"\u002Farticles\u002Fwelcome","Welcome","2023-08-05",1785659753486]