Generally speaking, I think that you are thinking about associative (not "associated") arrays in the wrong manner. Normally, one does not use associative arrays when array element ordering needs to be guaranteed. This is what numerically-indexed arrays are for. It should be a big red flag to you that PHP has no built-in functions to deal with ordering of associative arrays like it does for numerically-indexed arrays.
Now, if you need to have key-value combinations like you present here and be able to render them in a given order, perhaps for when they are being iterated for output (which is really the only use case I can think of for why you would want to do this), you might consider one of two options.
First, you could create a numerically-indexed array which references the key value array, and use this for iteration.
For example:
$keyValueArray = ['foo1' => 'bar', 'foo2' => 'buzz', 'foo3' => 'bazz'];
$keyOrder = ['foo1', 'foo2', 'foo3'];
Now, if you want to change the "order" of your key-value pairs, you simply do it in the $keyOrder
array. And then iterate out like this:
foreach($keyOrder as $key) {
echo $keyValueArray[$key];
}
Alternately, you might find it more intuitive to build an array of objects (or array of associative arrays).
$yourArray = [
(object) ['foo1' => 'bar'],
(object) ['foo2' => 'buzz'],
(object) ['foo3' => 'bazz']
];
function placeObjectBeforeByKey(array $arr, string $key, string $before)
{
$keyIdx = null;
$beforeIdx = null;
foreach($arr as $idx => $obj) {
if(isset($obj[$key])) {
$keyIdx = $idx;
}
if(isset($obj[$before])) {
$beforeIdx = $idx;
}
if(!is_null($keyIdx) && !is_null($beforeIdx)) {
break;
}
}
if(is_null($keyIdx) || is_null($beforeIdx)) {
// bad input, perhaps throw exception or log error and return $arr unaltered
}
if($keyIdx === $beforeIdx) {
// same object had matching keys for both $key and $before
// perhaps throw exception or just return $arr unaltered
return $arr;
}
$keySlice = array_splice($arr, $keyIdx, 1);
if($keyIdx < $beforeIdx) $beforeIdx--;
array_splice($arr, $beforeIdx, 0, $keySlice);
}
Note that either of these approaches, in essence, do the same as what you do in your function, when you are using array_keys()
to build a new array from scratch. The main difference from your approach and the alternatives I propose is that you are being more transparent to other areas of code around how ordering of these underlying key-value pairs is achieved. To me, if I were a developer picking up your code base, and I saw that you were simply using an associative array, I would not expect this to imply any ordering, whereas if you gave me an array of objects/arrays or an array which describes ordering of an associative array, it would be very clear to me that there is intended ordering to these pairs.