2

Good morning, I'm just shook about it but, php has more than 10 ways to sort an array but I can't find one to sort by desired key dynamically.

I cannot set something like some uksorts because it will be filled dynamically. I'm using smarty on the front (which does not have array sort functions) and I'm trying to make a callable static to resort and print sorted arrays on one specific point.

I've applied some logic on it and I think it would be something like this.

Smarty:

  {assign var='key' value='category_id'}
  {assign var='direction' value='normal'}
  {assign var='sortedItem' value=''}
    {foreach $object.prop item="item"}
        {sortedItem = Class::arraySortBy($item, $key, $direction)}
        <a href="{$item['link']}">
            {$item['name']}
        </a>
    {foreach}

PHP:

public static function arraySortBy($elemGroup, $sortBy, $direction) {
    if(is_object($elemGroup)){
        $elemGroup =  (array) $elemGroup;
    }
    if ($direction == 'normal') {
        // here is where i want to sort the elemGroup array by the key i want, as the key is product_id and i want to sort by category_id
    } else if ($direction == 'reverse'){
        // here the same but in reverse order
    } else {
       error_log('Direction not properly set.');
    }

    return $elemGroup;
}

the fact is that i want to re-order the objects bu category_id, and second by product_id IE:

itemA{product_id=1, category_id=1}
itemB{product_id=2, category_id=2}
itemC{product_id=3, category_id=1}
itemE{product_id=4, category_id=1}
itemD{product_id=5, category_id=2} 

Result:

itemA
itemB
itemC
itemE
itemD

expected result

itemA
itemC
itemE
itemB
itemD

Is there a way to make this with PHP sorting functions or it has to be custom?

Thanks

treyBake
  • 6,096
  • 5
  • 22
  • 47

2 Answers2

1

Why can't you use uasort?

function custom_array_sort($arr, $sorts)
{
    // Either pass an array of sorts, or every argument after the first one.
    $sorts = is_array($sorts) ? $sorts : array_slice(func_get_args(), 1);

    uasort($arr, function ($a, $b) use (&$arr, $sorts) {
        for ($i = 0; $i < count($sorts); $i++) {
            if ($a[$sorts[$i]] == $b[$sorts[$i]]) {
                if (isset($sorts[$i + 1])) {
                    $arr = custom_array_sort($arr, array_slice($sorts, 1));
                } else {
                    return 0;
                }
            } else {
                return $a[$sorts[$i]] - $b[$sorts[$i]];
            }
        }
    });

    return $arr;
}

Live demo

This works by first comparing the category_id fields.
If these are the same then we compare the product_id. The subtraction is used so that the smaller of the product_ids is sorted before the bigger one.

If the category_ids are not the same then we do the same operation on the category_ids as we did above for product_id.


To implement this into your view, follow this documentation

$smarty->register_function('custom_array_sort', 'custom_array_sort_wrapper');

function custom_array_sort_wrapper($params, &$smarty)
{
    if (empty($params['arr'])) {
        $arr = [];
    } else {
        $arr = $params['arr'];
    }

    if (empty($params['sorts'])) {
        $sorts = [];
    } else {
        $sorts = $params['sorts'];
    }

    return custom_array_sort($arr, $sorts);
}

This can then be used in your views in the following way:

{custom_array_sort arr=$object sorts=['category_id', 'product_id']}

The advantage of this new implementation is that you can specify as many columns to sort as you like.
It also means that you can specify different columns to sort for different arrays.

If you want to sort by more columns then just add another column name to the $sorts array.

JustCarty
  • 3,261
  • 3
  • 26
  • 46
  • This will make me create a new soert function each time i want to sort by a different key. I know and tried different php doc array sort functions, i'm looking for the existence of something more useful. I think i'll have to make a lib for it anyway but it could be fine if there's something built-in that gives more than a simple "sort by the first key or DIY" i saw on php doc... – Joel Bonet Rodríguez Feb 28 '19 at 15:48
  • @JoelBonetRodríguez I don't understand your request then... If you want custom sorts, then I can modify the function accordingly so that you can change what columns are sorted... Your question doesn't really make it clear that you might want to sort by different columns at different times. – JustCarty Feb 28 '19 at 16:22
  • @JoelBonetRodríguez I have updated my code, please check to see if that better suits your application. – JustCarty Feb 28 '19 at 17:05
-1

You can you try this function.

function array_sort($array, $on, $order=SORT_ASC){

    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
                break;
            case SORT_DESC:
                arsort($sortable_array);
                break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

Example:

Array Value:-

$item_array = array (
    'itemA' => array('product_id'=>1, 'category_id'=>1), 
    'itemB' => array('product_id'=>2, 'category_id'=>2),
    'itemC' => array('product_id'=>3, 'category_id'=>1),
    'itemD' => array('product_id'=>4, 'category_id'=>1),
    'itemE' => array('product_id'=>5, 'category_id'=>2)
); 

Use function:-

$itme_list = array_sort($item_array, 'category_id', SORT_ASC);
print_r($itme_list);

Output:

Array
(
    [itemA] => Array
        (
            [product_id] => 1
            [category_id] => 1
        )

    [itemC] => Array
        (
            [product_id] => 3
            [category_id] => 1
        )

    [itemD] => Array
        (
            [product_id] => 4
            [category_id] => 1
        )

    [itemB] => Array
        (
            [product_id] => 2
            [category_id] => 2
        )

    [itemE] => Array
        (
            [product_id] => 5
            [category_id] => 2
        )

)

Note: Reference link :- Sort PHP multi-dimensional array based on key?

How to sort multidimensional array by multiply keys?

Praveen Kumar
  • 779
  • 1
  • 8
  • 29
  • a code-only and link-only answers aren't answers IMO. A good answer should explain the problem and solution so OP and future visitors can learn – treyBake Feb 28 '19 at 11:55
  • @treyBake: Thank you for your suggestion. I will take care of this – Praveen Kumar Feb 28 '19 at 12:00
  • This is just what i don't want. i mean if there's a built-in function on PHP to reach this without getting in doing custom comparisons as it's something pretty easy to implement, but tedious when you've to repeat it by different needings loads of times. – Joel Bonet Rodríguez Feb 28 '19 at 12:57