Soulfire
Soulfire

Reputation: 4296

How do I get common subcategories from a category/subcategory array in PHP?

I have an array like so:

Array
(
    [0] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Glass
                    [id] => 409
                )

        )

    [1] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Accesories
                    [id] => 46
                )

        )

    [2] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Lip Balm
                    [id] => 17576
                )

        )

    [3] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Lotion
                    [id] => 17577
                )

        )

    [4] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Distillate
                    [id] => 17578
                )

        )

    [5] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Cartridges
                    [id] => 17579
                )

        )

    [6] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Tincture
                    [id] => 17644
                )

        )

    [7] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Capsules
                    [id] => 17645
                )

        )

    [8] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Gummies
                    [id] => 26
                )

        )

    [9] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Chocolate Bars
                    [id] => 25
                )

        )

    [10] => ProductCategory Object
        (
            [name] => Concentrate
            [id] => 2
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Live Resin
                    [id] => 15
                )

        )

    [11] => ProductCategory Object
        (
            [name] => Cartridges / Pens
            [id] => 3
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Solventless
                    [id] => 18051
                )

        )

    [12] => ProductCategory Object
        (
            [name] => Concentrate
            [id] => 2
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Distillate
                    [id] => 18005
                )

        )

    [13] => ProductCategory Object
        (
            [name] => Concentrate
            [id] => 2
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Sauce
                    [id] => 18767
                )

        )

    [14] => ProductCategory Object
        (
            [name] => Cartridges / Pens
            [id] => 3
            [subcategory] => ProductSubcategory Object
                (
                    [name] => BHO
                    [id] => 10
                )

        )

    [15] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Baked Goods
                    [id] => 23
                )

        )

    [16] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Tincture
                    [id] => 29
                )

        )

    [17] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Vaporizers
                    [id] => 42
                )

        )

    [18] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Cooking Oil
                    [id] => 18864
                )

        )

    [19] => ProductCategory Object
        (
            [name] => Concentrate
            [id] => 2
            [subcategory] => ProductSubcategory Object
                (
                    [name] => RSO
                    [id] => 18865
                )

        )

    [20] => ProductCategory Object
        (
            [name] => Concentrate
            [id] => 2
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Sugar (Each)
                    [id] => 18876
                )

        )

    [21] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Shirts
                    [id] => 44
                )

        )

    [22] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Sweets
                    [id] => 27
                )

        )

    [23] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => CBD Bath Bomb
                    [id] => 19461
                )

        )

    [24] => ProductCategory Object
        (
            [name] => Non Medicated
            [id] => 6
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Edibles
                    [id] => 17580
                )

        )

    [25] => ProductCategory Object
        (
            [name] => Infused Edible
            [id] => 4
            [subcategory] => ProductSubcategory Object
                (
                    [name] => Capsules/Pills
                    [id] => 22
                )

        )

)

The ProductCategory object is defined like so:

class ProductCategory{
    public $name;
    public $id;
    public $subcategory;

    public function __construct($categoryName, $categoryId, $subcategory){
        $this->name = $categoryName;
        $this->id = $categoryId;
        $this->subcategory = $subcategory;
    }
}

The ProductSubcategory is defined like so:

class ProductSubcategory{

    public $name;
    public $id;

    public function __construct($subcategoryName, $subcategoryId){
        $this->name = $subcategoryName;
        $this->id = $subcategoryId;

    }

I am trying to get all of the subcategories that belong to the same category. For example, at position 0 and 1 of the array above, both the Glass and Accessories subcategories belong to the Non Medicated category.

Ultimately I am trying to get a display like this (I don't want to display the category and subcategory numbers but I will need them for later use):

This final output will be radio buttons that user can click - if they click a parent category, products will be filtered by that parent category. If they click a subcategory, products will be filtered by that parent category as well as the subcategory.

The only thing I've tried is I got a distinct list of the parent categories from the array, and attempted to loop through them, then for each parent category loop through the above array and check if the category matches the parent category, and then append the subcategory object.

For some reason, I can't get it to work. I don't know if I just need to abandon using the objects themselves and return an array of names and ids or what. Any guidance would be appreciated.

This is related to a question I asked yesterday, in which someone helped me redesign the ProductCategory object. I'm much closer than I was yesterday, but still not there.

Edit

Here is how the categories and subcategories are being grouped:

public function get_categories_from_all_products() {

    $categories  = array();
    $allProducts = $this->get_all_products();

    foreach ( $allProducts as $item ) {
        if ( ! in_array( $item->category, $categories ) ) {
            array_push( $categories, $item->category );
        }
    }

    return $categories;
}

get_all_products returns an array of Product objects that are defined like this:

class Product{

    public $description;
    public $pricing;
    public $name;
    public $imageUrl;
    public $id;
    public $category;

    public function __construct($id, $description, $pricing, $name, $imageUrl, ProductCategory $category){
        $this->description = $description;
        $this->pricing = $pricing;
        $this->name = $name;
        $this->imageUrl = $imageUrl;
        $this->id = $id;
        $this->category = $category;
    }

}

Example product declaration (here $item is from an array of products returned by an API call):

$p = new Product(
    $item['id'],
    $item['description'] ? $item['description'] : 'No product description.',
    $price,
    $item["name"],
    array_key_exists('primary_image_urls', $item) ? $item['primary_image_urls'] : 'img/no_image_available.png',
    new ProductCategory( $item['category_name'], $item['category_id'], new ProductSubcategory( $item['subcategory_name'], $item['subcategory_id']) )
);

Final Edit:

A slight adjustment to the accepted answer is working:

foreach($categories as $category){

    $cat = $category->name;
    $id = $category->id;
    $toRet[$id][$cat][] = $category->subcategory;


 }

return $toRet;

Testing the display (note: I added logic so that if a parent category only has one subcategory it will just display the parent category):

$categories = $MJPlugin->get_categories_from_all_products(); //Populates array from above

echo '<ul>';


foreach( $categories as $categoryId => $category ) {

    $cat = key( $categories[$categoryId] );

    echo '<li>' . $cat . '</li>';

    echo '<ul>';

    foreach( $categories[$categoryId] as $subcategories ) {

        if( count( $subcategories ) > 1 ) {
            foreach( $subcategories as $subcategory ) {

                echo '<li>' . $subcategory->name . '</li>';
            }
        }
    }

    echo '</ul>';

}

echo '<ul>';

Upvotes: 0

Views: 124

Answers (3)

Wolfetto
Wolfetto

Reputation: 1130

I create a fake objects ($categories) as you have.

Hope this can help:

<?php

 $categories = array();

 $obj0 = new stdClass;
 $obj0->id = 123;
 $obj0->name = "Non Medicated";
 $obja = new stdClass;
 $obja->name = "Glass";
 $obja->id = 409;
 $obj0->subcategory =$obja;
 $categories[0] = $obj0;

 $obj1 = new stdClass;
 $obj1->id = 124;
 $obj1->name = "Non Medicated";
 $obj1a = new stdClass;
 $obj1a->name = "Capsules";
 $obj1a->id = 410;
 $obj1->subcategory =$obj1a;
 $categories[1] = $obj1;

 $obj2 = new stdClass;
 $obj2->id = 125;
 $obj2->name = "Non Medicated";
 $obj2a = new stdClass;
 $obj2a->name = "Capsules";
 $obj2a->id = 411;
 $obj2->subcategory =$obj2a;
 $categories[2] = $obj2;

 $toRet =array();

 foreach($categories as $category){
    $cat = $category->name;
    $toRet[$cat][] = $category->subcategory;
 }

 var_dump($toRet);

This is the output of var_dump function:

array(1) { ["Non Medicated"]=> array(3) { [0]=> object(stdClass)#2 (2) { ["name"]=> string(5) "Glass" ["id"]=> int(409) } [1]=> object(stdClass)#4 (2) { ["name"]=> string(8) "Capsules" ["id"]=> int(410) } [2]=> object(stdClass)#6 (2) { ["name"]=> string(8) "Capsules" ["id"]=> int(411) } } }

Upvotes: 0

Rahul
Rahul

Reputation: 18557

Below code may help you will raw array(you can do it by toArray()),

$parentCategories = [6, 4, 3, 2];
$result           = [];
foreach ($parentCategories as $key => $pv) {
    foreach ($childCategories as $cv) {
        if ($pv == $cv['id']) {
            if (empty($result[$cv['id']]['name'])) {
                $result[$cv['id']]['data']['id'] = $pv;
                $result[$cv['id']]['data']['name']       = $cv['name'];
            }
            $result[$cv['id']]['children'][] = $cv['subcategory'];
        }
    }
}

Demo

Output:-

                      (
                            [name] => Cartridges
                            [id] => 17579
                        )

                    [6] => Array
                        (
                            [name] => Tincture
                            [id] => 17644
                        )

                    [7] => Array
                        (
                            [name] => Capsules
                            [id] => 17645
                        )

                    [8] => Array
                        (
                            [name] => Vaporizers
                            [id] => 42
                        )

                    [9] => Array
                        (
                            [name] => Shirts
                            [id] => 44
                        )

                    [10] => Array
                        (
                            [name] => CBD Bath Bomb
                            [id] => 19461
                        )

                    [11] => Array
                        (
                            [name] => Edibles
                            [id] => 17580
                        )

                )

        )

    [4] => Array
        (
            [data] => Array
                (
                    [id] => 4
                    [name] => Infused Edible
                )

            [children] => Array
                (
                    [0] => Array
                        (
                            [name] => Gummies
                            [id] => 26
                        )

                    [1] => Array
                        (
                            [name] => Chocolate Bars
                            [id] => 25
                        )

                    [2] => Array
                        (
                            [name] => Baked Goods
                            [id] => 23
                        )

                    [3] => Array
                        (
                            [name] => Tincture
                            [id] => 29
                        )

                    [4] => Array
                        (
                            [name] => Cooking Oil
                            [id] => 18864
                        )

                    [5] => Array
                        (
                            [name] => Sweets
                            [id] => 27
                        )

                    [6] => Array
                        (
                            [name] => Capsules/Pills
                            [id] => 22
                        )

                )

        )

    [3] => Array
        (
            [data] => Array
                (
                    [id] => 3
                    [name] => Cartridges / Pens
                )

            [children] => Array
                (
                    [0] => Array
                        (
                            [name] => Solventless
                            [id] => 18051
                        )

                    [1] => Array
                        (
                            [name] => BHO
                            [id] => 10
                        )

                )

        )

    [2] => Array
        (
            [data] => Array
                (
                    [id] => 2
                    [name] => Concentrate
                )

            [children] => Array
                (
                    [0] => Array
                        (
                            [name] => Live Resin
                            [id] => 15
                        )

                    [1] => Array
                        (
                            [name] => Distillate
                            [id] => 18005
                        )

                    [2] => Array
                        (
                            [name] => Sauce
                            [id] => 18767
                        )

                    [3] => Array
                        (
                            [name] => RSO
                            [id] => 18865
                        )

                    [4] => Array
                        (
                            [name] => Sugar (Each)
                            [id] => 18876
                        )

                )

        )

)

I am logically getting the output from script,

foreach ($result as $key => $value) {
    echo "<ul>";
    echo "<li>" . $value['data']['name'] . '(' . 'id=' . $value['data']['id'] . ')';
    echo "<ul>";
    foreach ($value['children'] as $k => $value1) {
        echo "<li>";
        if ($k == 0) {
            echo $value1['name'] . "(" . 'categoryid = ' . $value['data']['id'] . ', subcategoryid = ' . $value1['id'] . ")";
        } else {
            echo $value1['name'];
        }
        echo "</li>";
    }
    echo "</ul></li></ul>";
}

Output as

<ul>
  <li>Non Medicated(id=6)
    <ul>
      <li>Glass(categoryid = 6, subcategoryid = 409)</li>
      <li>Accesories</li>
      <li>Lip Balm</li>
      <li>Lotion</li>
      <li>Distillate</li>
      <li>Cartridges</li>
      <li>Tincture</li>
      <li>Capsules</li>
      <li>Vaporizers</li>
      <li>Shirts</li>
      <li>CBD Bath Bomb</li>
      <li>Edibles</li>
    </ul>
  </li>
</ul>
<ul>
  <li>Infused Edible(id=4)
    <ul>
      <li>Gummies(categoryid = 4, subcategoryid = 26)</li>
      <li>Chocolate Bars</li>
      <li>Baked Goods</li>
      <li>Tincture</li>
      <li>Cooking Oil</li>
      <li>Sweets</li>
      <li>Capsules/Pills</li>
    </ul>
  </li>
</ul>
<ul>
  <li>Cartridges / Pens(id=3)
    <ul>
      <li>Solventless(categoryid = 3, subcategoryid = 18051)</li>
      <li>BHO</li>
    </ul>
  </li>
</ul>
<ul>
  <li>Concentrate(id=2)
    <ul>
      <li>Live Resin(categoryid = 2, subcategoryid = 15)</li>
      <li>Distillate</li>
      <li>Sauce</li>
      <li>RSO</li>
      <li>Sugar (Each)</li>
    </ul>
  </li>
</ul>

Upvotes: 1

Omer Farooq
Omer Farooq

Reputation: 4064

Not sure if i understand what you want, but If you just need to show categories and subcategories, you can do something like this?

foreach($categories as $key => $category){

    echo $category->name;
    echo $category->id;

    foreach($category->subcategory as $key2 => $subCategory){

        echo $subCategory->name;
        echo $subCategory->id;
        echo $category->id;
    }
}                

Upvotes: 0

Related Questions