OOP problem: Relationship between category, sub category and product

88 Views Asked by At

I am now using PHP, try to do a exercise myself for studying but encounter a problem currently.

My design is like: 1 Category will contains 0 to many Sub Category, and 1 Sub Category will contains 0 to many Product, Each Product in my case will only belongs to 1 SubCategory. In my view, they are composition relationship(please correct me if wrong), But after that I don't know how to write the code of this kind of relationship. In my view, it should be 3 classes (Category,SubCategory,Product) with their own attributes and method. But may be due to my mind is still stuck in my design page. I will create a page for adding a new Category and its SubCategory(of course it will also have another page for editing and updating). And create a page for adding a new Product.

If I write the code of Category and SubCatgory like that, how about the class Product? What I am stucking is, if I write the class Product like that, but I already put the attribute [product] in class SubCategory, isn't be a wrong logic? Can anyone tell me a proper logic for designing this relationship? I know for many seniors it may be a stupid question, but it really stucks me for a month without a proper solution.

Moreover, is that any advice or materials for teaching how to design a good class structure and relationship? I think this is really hard for me.

Thank you for viewing my question.

Class Category{
private $subCat;

public function createNewSubCat(){
$this->subCat[]=new SubCategory();
}
}

Class SubCategory{
private $product;
public function createNewProduct(){
$this->product[]=new Product();
}
}

Class Product{
private $cat;
private $subCat;

public function setCategory(Category $c){
$this->cat=$c;
}

public function setSubCat(SubCategory $subC){
$this->subCat=$subC;
}
}
1

There are 1 best solutions below

3
KIKO Software On

You could merge the Category and SubCatgory classes into one Category class. Like this:

class Category
{
    private $parentCategory = NULL;
    private $categoryLevel = 0;
    private $categories = [];
    private $products = [];

    public function __construct($parentCategory = NULL)
    {
        if ($parentCategory) {
            $this->parentCategory = $parentCategory;
            $this->categoryLevel = $parentCategory->getCategoryLevel() + 1;
        }
    }

    public function getCategoryLevel()
    {
        return $this->categoryLevel;
    }

    public function createNewCategory()
    {
        return $this->categories[] = new Category($this);
    }

    public function createNewProduct(){
        return $this->products[] = new Product($this);
    }
}

class Product
{
    private $parentCategory;

    public function __construct($parentCategory = NULL)
    {
        $this->parentCategory = $parentCategory;
    }
}

Note that I wrote this loosely typed for simplicity, but I added a "level" attribute to the category class, so you can check how deep in the tree a specific category is.

As you can see there's no reason to have a "SubCategory" class. This simplifies your code, especially when you want to render the categories.

Note how I connect sub-categories and products using the constructor.

You could put in a restriction: When a category class has child category it cannot have a product, and when it has a product it cannot have a child category. Alternatively, you could allow this.

Finally, one thing you need to unlearn as quickly as possible: Abbreviating things that should not be abbreviated. A "category" is a "category", it's not a "cat", which is an animal, nor is it "c", whatever that means. Use meaningful names that reflect the content of a variable. Shorter names are not always better names, especially if they are ambiguous, nor do longer names slow down the execution of your code.