Hello. Leafing through foreach (products as product) I have on the page a lot of products like this:

  [2] => Array ( [product_id] => 295 [viewed] => Array ( [0] => Array ( [chat_id] => 74 [message_id] => 162 [status] => 0 ) [1] => Array ( [chat_id] => 74 [message_id] => 163 [status] => 1 ) ) ) 

In SQL, sorting is not possible.

How can I do a sorting, so that goods where there is [status] => 0 are at the top of the list?

In other words, if there is at least one unread message in the chat, pick it up at the top of the list.

    3 answers 3

     usort($products, function($a) { foreach ($a["viewed"] as $viewed) if (!$viewed["status"]) return 0; return 1; }); 

    Description, as requested:

    usort($products, function($a, $b) { ... }); allows you to sort an array using a user-defined function to which the first two indices of this array ( $a and $b ) are passed, the second of which is not required in this case. The returned values ​​of the user-defined function determine the order in which the element $a will be displayed.

    • where is $ b used? - ultimatum
    • @ultimatum, but in principle it is not needed in this case, I think so. slightly corrected. - check1st
    • The order of the output has not changed, there are no errors. do foreach (products as product) - ultimatum
    • @ultimatum, I understand correctly? if at least in one element of the views array the status is zero, then put the product at the top of the list? - check1st
    • Yes. that's right. (in other words, if there is at least one unread message in the chat, take it up to the top of the list) - ultimatum
     //Сортируем сообщения внутри "viewed" foreach($products as &$product){ usort($product['viewed'], function($a,$b){ if($a["status"] < $b['status']) return 1; if($a["message_id"]==$b["message_id"])return 0; //Если они не могут быть равными, то можно удалить эту строку return $a["message_id"]<$b["message_id"]; }); } //Сортируем $products по статусам вложенных сообщений. Внутри viewed мы уже отсортировали usort($products, function($a,$b){return $a["viewed"][0]<$b["viewed"][0];}) 
    • not quite, changes the sorting, not all NEW at the top. I leave the accepted answer, because He shorter and correctly fulfills. Senks. - ultimatum

    Crutch option, mb someone will come up with smarter, but still:

     $status_array = array(//Массив, в который мы будем записывать товары 0 => array(), 1 => array() ) foreach($products as $product){ $zero_status = false;//Если мы так и не найдем НОВЫЕ записи(статус==0) foreach($product[viewed] as $prod_detail){ $status = $prod_detail[status]; //получаем статус текущего товара(?) if($status == 0){ $status_array[0][] = $product; //записываем его в соответствующий массив $zero_status = true; break;//Искомое условие мы нашли, выходим } } if(!zero_status){ $status_array[1][] = $product; } } $status_array = array_merge($status_array[0],$status_array[1]); //получаем общий массив, где сначала идут записи со status = 0 
    • there may be a dozen or more of them within the same product - ultimatum
    • @ultimatum Fixed the answer - SLy_huh
    • there is progress in our business, the sorting works! but not correctly, displays only those products where there is NEW. And what about the rest?) - ultimatum
    • @ultimatum, yes, and really, I completely forgot. The answer is corrected, now all records should be added. - SLy_huh
    • not quite doing a bunch of duplicates + pulls 1 product from [0] - ultimatum