php - Sort an associative/multidimensional array based on a sub-object array value

one text

Solution:

According to your logic, we need to sort the array by badge condition and within the campaign badge group we need to sort by a product name. Please take a look at the following snippet.

<?php

declare(strict_types=1);

$campaignBadge                  = new \stdClass();
$campaignBadge->badge_id        = 3;
$campaignBadge->badge_name      = 'campaign';
$campaignBadge->badge_published = 1;
$campaignBadge->badge_access    = 'all';

$whateverBadge                  = new \stdClass();
$whateverBadge->badge_id        = 5;
$whateverBadge->badge_name      = 'whatever';
$whateverBadge->badge_published = 1;
$whateverBadge->badge_access    = 'all';

$product1               = new \stdClass();
$product1->product_id   = 195;
$product1->product_name = 'Product name 1';
$product1->badges       = [
    $campaignBadge,
];

$product2               = new \stdClass();
$product2->product_id   = 290;
$product2->product_name = 'Amazing product';
$product2->badges       = [
    $whateverBadge,
];

$product3               = new \stdClass();
$product3->product_id   = 102;
$product3->product_name = 'Some product';
$product3->badges       = [
    $whateverBadge,
];

$product4               = new \stdClass();
$product4->product_id   = 250;
$product4->product_name = 'Awesome product';
$product4->badges       = [
    $campaignBadge,
];

$products = [
    $product1,
    $product2,
    $product3,
    $product4,
];

usort($products, static function ($a, $b) {
    $aHasCampaignBadge = false;
    foreach ($a->badges as $badge) {
        if ('campaign' === $badge->badge_name) {
            $aHasCampaignBadge = true;
            break;
        }
    }

    $bHasCampaignBadge = false;
    foreach ($b->badges as $badge) {
        if ('campaign' === $badge->badge_name) {
            $bHasCampaignBadge = true;
            break;
        }
    }

    if (!$aHasCampaignBadge && !$bHasCampaignBadge) {
        return 0;
    }

    if ($aHasCampaignBadge && $bHasCampaignBadge) {
        return strcmp($a->product_name, $b->product_name);
    }

    return $aHasCampaignBadge < $bHasCampaignBadge;
});

var_dump($products);

Source