In this article
Introduction
There may be times when you are working with arrays in your PHP code and need to switch the order of two items. If you're using an array that uses integers as keys, this can be a pretty straightforward task. However, if you're trying to swap two items of an associative array, this can be little bit more hands-on. So, in this short post, I'll show you how you can use macros in Laravel to keep your code looking clean and reusable.
By the end of the post, you should have a brief idea on how to create a macro that you can use to change the order of your like in this example:
1$assocArray = [ 2 'item_one' => ['name' => 'One'], 3 'item_two' => ['name' => 'Two'], 4 'item_three' => ['name' => 'Three'], 5 'item_four' => ['name' => 'Four'], 6]; 7 8$newArray = Arr::swap($array, 'item_one', 'item_three'); 9 10/*11 * $newArray is now:12 * [13 * 'item_three' => ['name' => 'Three'],14 * 'item_two' => ['name' => 'Two'],15 * 'item_one' => ['name' => 'One'],16 * 'item_four' => ['name' => 'Four'],17 * ]18 */
What Are Macros?
In Laravel, macros are methods that can be added to classes at runtime. They can be a pretty cool way of extending the functionality of a class that you might not have full access to and might not want to inherit from. Not all classes are "macroable", but if you want a full list of the Laravel classes that you can add macros to, check out this article written by Caleb Porzio.
Where Do I Define The Macro?
Whenever we create a new macro, we'll need to let Laravel new that we're providing a new macro; and we can do this inside a service provider. In theory, we can add this code to the AppServiceProvider
but I like to try and keep the providers split out; otherwise, that file starts to get full pretty early on in your project. But this is just my personal opinion though, so feel free to use the AppServiceProvider
if that helps you.
So, if you want to add the macro to a separate provider, let's start by creating a new MacroServiceProvider
using the following command:
1php artisan make:provider MacroServiceProvider
We'll then need to remember to register this service provider inside the app/config.php
like below:
1return [2 3 'providers' => [4 // ...5 \App\Providers\MacroServiceProvider::class,6 // ...7 ],8 9]
Now that we've created the new service provider, let's create the macro. This is the macro that we're going to be adding:
1Arr::macro('swap', function (array $array, $keyOne, $keyTwo): array { 2 if (! Arr::isAssoc($array)) { 3 $itemOneTmp = $array[$keyOne]; 4 5 $array[$keyOne] = $array[$keyTwo]; 6 $array[$keyTwo] = $itemOneTmp; 7 8 return $array; 9 }10 11 $updatedArray = [];12 foreach ($array as $key => $value) {13 if ($key === $keyOne) {14 $updatedArray[$keyTwo] = $array[$keyTwo];15 } elseif ($key === $keyTwo) {16 $updatedArray[$keyOne] = $array[$keyOne];17 } else {18 $updatedArray[$key] = $value;19 }20 }21 22 return $updatedArray;23});
So, let's add this macro to the service provider so that we can access it:
1namespace App\Providers; 2 3use Illuminate\Support\Arr; 4use Illuminate\Support\ServiceProvider; 5 6class MacroServiceProvider extends ServiceProvider 7{ 8 /** 9 * Bootstrap services.10 *11 * @return void12 */13 public function boot(): void14 {15 Arr::macro('swap', function (array $array, $keyOne, $keyTwo): array {16 if (! Arr::isAssoc($array)) {17 $itemOneTmp = $array[$keyOne];18 19 $array[$keyOne] = $array[$keyTwo];20 $array[$keyTwo] = $itemOneTmp;21 22 return $array;23 }24 25 $updatedArray = [];26 foreach ($array as $key => $value) {27 if ($key === $keyOne) {28 $updatedArray[$keyTwo] = $array[$keyTwo];29 } elseif ($key === $keyTwo) {30 $updatedArray[$keyOne] = $array[$keyOne];31 } else {32 $updatedArray[$key] = $value;33 }34 }35 36 return $updatedArray;37 });38 }39}
Now that we've defined the macro inside the service provider, we can swap items in arrays using the Arr::swap()
method. Here are some examples below of how we would be able to use this method:
1$array = [ 2 ['name' => 'One'], 3 ['name' => 'Two'], 4 ['name' => 'Three'], 5 ['name' => 'Four'], 6]; 7 8$newArray = Arr::swap($array, 0, 2); 9 10/*11 * $newArray is now:12 * [13 * ['name' => 'Three'],14 * ['name' => 'Two'],15 * ['name' => 'One'],16 * ['name' => 'Four'],17 * ]18 */
1$assocArray = [ 2 'item_one' => ['name' => 'One'], 3 'item_two' => ['name' => 'Two'], 4 'item_three' => ['name' => 'Three'], 5 'item_four' => ['name' => 'Four'], 6]; 7 8$newArray = Arr::swap($array, 'item_one', 'item_three'); 9 10/*11 * $newArray is now:12 * [13 * 'item_three' => ['name' => 'Three'],14 * 'item_two' => ['name' => 'Two'],15 * 'item_one' => ['name' => 'One'],16 * 'item_four' => ['name' => 'Four'],17 * ]18 */
Hopefully, this short post will have given you a very brief overview of how to quickly create a macro that we can use swap two items in a PHP array. And a pretty nice benefit is that we can reuse that macro method across our system and keep our code looking readable and Laravel-y.
I'd love to hear any feedback in the comments if this helped you or not! 🚀