0
votes

I have a list of Product objects, defined like so:

class Product{

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

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

}

Each Product object has a category and subcategory object as part of the definition, these are defined as so:

ProductCategory:

class ProductCategory{
    public $name;
    public $id;

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

ProductSubCategory:

class ProductSubCategory{
    public $name;
    public $id;

    public function __construct($subCategoryName, $subCategoryId){
        $this->name = $subCategoryName;
        $this->id = $subCategoryId;
    }
}

For example, the parent category Non-Medicated has the following subcategories (parent category, subcategory):

Non Medicated, Glass
Non Medicated, Accesories
Non Medicated, Lip Balm
Non Medicated, Lotion
Non Medicated, Distillate
Non Medicated, Cartridges
Non Medicated, Tincture
Non Medicated, Capsules

I am trying to return an array of objects that is the main category as well as the distinct subcategories for each main category by iterating through the products, so that I can ultimately get a display like this:

  • Non-Medicated
    • Glass
    • Accessories
    • Lip Balm
    • Lotion
    • Distillate
    • Cartridges
    • Tincture
    • Capsules

What I've done so far:

So far I can get the categories by doing this:

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

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

Where $allProducts is an array of Product objects, as defined above.

So I have this array:

Array ( [0] => ProductCategory Object ( [name] => Non Medicated [id] => 6 ) [1] => ProductCategory Object ( [name] => Infused Edible [id] => 4 ) [2] => ProductCategory Object ( [name] => Concentrate [id] => 2 ) [3] => ProductCategory Object ( [name] => Cartridges / Pens [id] => 3 ) [4] => ProductCategory Object ( [name] => Flower [id] => 1 ) )

What I am trying to do is get something here $categories[0][0] is the main category and then $categories[0][1] is subcategory 1, $categories[0][2] is subcategory 2, etc.

I am also open to approaching it another way - that's just the easiest I could think of off the top of my head. Any advice on how to better structure this would be appreciated as well. I have heard of Collections before, but I've never used them, and I'm not sure if they would be applicable here.

3
somehow I am feeling the application of groupBy. But unable to understand your question.Rahul
Hmm - I will look into array grouping.Soulfire

3 Answers

1
votes

Reading your question looks more ProductSubCategory belongs to ProductCategory object instead Product object.

Basically, I believe you can better design it by Product having a ProductCategory object and a ProductCategory having an array of ProductSubCategory. So, when you get the Product object, you have access to it ProductCategory and all ProductSubCategory objects.

So, you can iterate your objects like this:

foreach($allProducts as $product) {
    $category = $product->getCategory(); // Get your object category
    $subCategories = $category->getSubCategories(); // Get your sub categories from CategoryObject
    echo "Category: " . $category;
    foreach($subCategories as $subCategory) {
        echo "Sub category: " . $subCategory;
    }
}

You can get the result you were expecting in your question above.

0
votes

You may do it in one loop:

$allCategories = [];
foreach($allProducts as $product){
    if(!isset($allCategories[$product->category)) // add the category
        $allCategories[$product->category] = [];   
    if(!isset($allCategories[$product->category][$product->subcategory])) // add the subcategory to top-level category
        $allCategories[$product->category][] = $product->subcategory;
}
0
votes

I am assuming there is a function to get all sub categories for a given category

$categories  = array();
$allProducts = $this->get_all_products();
foreach ( $allProducts as $key => $item ) {
    $categories[$key][] = $item->category;
    foreach ($this->get_all_subcategories($item->category) as $subCat) { //assuming there is a get_all_subcategories function available, it could be an array with category as the key and subcategories as the value
        $categories[$key][] = $subCat;
    }
}

print_r( $categories );

Modification

$categories  = array();
$allProducts = $this->get_all_products();
foreach ( $allProducts as $key => $item ) {
    $categories[$key][0] = $item->category;
    if (!in_array($item->subcategory, $categories[$key]))
        $categories[$key][] = $item->subcategory;
}

print_r( $categories );