Skip to main content

Overview

The Ecom platform provides a flexible categorization system with hierarchical categories and brand management to organize products effectively. Categories support nested structures, multi-language translations, and visual assets.

Hierarchical Categories

Unlimited nested category levels with parent-child relationships

Multi-Language Support

Category names and descriptions in multiple languages

Brand Management

Organize products by brand with logo support

Visual Assets

Cover images, icons, and banners for categories

Category Model

The Category model provides a hierarchical structure for organizing products.

Category Relationships

Categories support unlimited nesting levels:
// Direct children
public function categories()
{
    return $this->hasMany(Category::class, 'parent_id');
}

// Recursive children (nested)
public function childrenCategories()
{
    return $this->hasMany(Category::class, 'parent_id')->with('categories');
}

// Parent category
public function parentCategory()
{
    return $this->belongsTo(Category::class, 'parent_id');
}
Location: ~/workspace/source/app/Models/Category.php:43-56This structure allows you to create deep category hierarchies like:
  • Electronics
    • Computers
      • Laptops
      • Desktops
    • Mobile Phones
      • Smartphones
      • Feature Phones
Categories have a many-to-many relationship with products:
public function products()
{
    return $this->belongsToMany(Product::class, 'product_categories');
}
Location: ~/workspace/source/app/Models/Category.php:30-33This allows products to belong to multiple categories simultaneously, enabling flexible product organization and cross-category listings.
Categories support multiple image types for different display contexts:
public function coverImage()
{
    return $this->belongsTo(Upload::class, 'cover_image');
}

public function catIcon()
{
    return $this->belongsTo(Upload::class, 'icon');
}

public function bannerImage()
{
    return $this->belongsTo(Upload::class, 'banner');
}
Location: ~/workspace/source/app/Models/Category.php:22-37Image Types:
  • Cover Image: Main category image for listings
  • Icon: Small icon for navigation and menus
  • Banner: Large banner for category landing pages
Categories can have associated attributes and size guides:
public function attributes()
{
    return $this->belongsToMany(Attribute::class);
}

public function sizeChart()
{
    return $this->belongsTo(SizeChart::class, 'id', 'category_id');
}
Location: ~/workspace/source/app/Models/Category.php:58-66Attributes define product characteristics (like color, size, material) that vary by category.

Category Translations

Categories support multi-language content through the CategoryTranslation model:
public function getTranslation($field = '', $lang = false)
{
    $lang = $lang == false ? App::getLocale() : $lang;
    $category_translation = $this->category_translations->where('lang', $lang)->first();
    return $category_translation != null ? $category_translation->$field : $this->$field;
}

public function category_translations()
{
    return $this->hasMany(CategoryTranslation::class);
}
Location: ~/workspace/source/app/Models/Category.php:12-20

Eager Loading

Category translations are automatically loaded to improve performance:
protected $with = ['category_translations'];
Location: ~/workspace/source/app/Models/Category.php:10

Usage Example

// Get category name in current locale
$categoryName = $category->getTranslation('name');

// Get category name in specific language
$categoryNameEs = $category->getTranslation('name', 'es');

Brand Model

The Brand model allows products to be organized by manufacturer or brand.

Brand Structure

class Brand extends Model
{
    protected $with = ['brand_translations'];

    public function getTranslation($field = '', $lang = false)
    {
        $lang = $lang == false ? App::getLocale() : $lang;
        $brand_translation = $this->brand_translations->where('lang', $lang)->first();
        return $brand_translation != null ? $brand_translation->$field : $this->$field;
    }

    public function brand_translations()
    {
        return $this->hasMany(BrandTranslation::class);
    }

    public function brandLogo()
    {
        return $this->belongsTo(Upload::class, 'logo');
    }
}
Location: ~/workspace/source/app/Models/Brand.php:8-29

Brand Features

Multi-Language Names

Brand names translated for different locales

Brand Logos

Upload and display brand logos

Product Association

Products linked to brands via relationship

Eager Loading

Translations automatically loaded for performance

Product-Category Association

In the ProductController, categories are managed during product creation and updates.

Category Selection During Creation

public function create()
{
    CoreComponentRepository::initializeCache();

    $categories = Category::where('parent_id', 0)
        ->where('digital', 0)
        ->with('childrenCategories')
        ->get();

    return view('backend.product.products.create_wizard', compact('categories'));
}
Location: ~/workspace/source/app/Http/Controllers/ProductController.php:176-186 This loads only parent categories (where parent_id = 0) along with their nested children for physical products (digital = 0).

Attaching Categories to Products

public function store(ProductRequest $request)
{
    $product = $this->productService->store($request->except([...]));
    
    // Product categories
    $product->categories()->attach($request->category_ids);
    
    // ... rest of the method
}
Location: ~/workspace/source/app/Http/Controllers/ProductController.php:215 The attach() method creates records in the product_categories pivot table, allowing a product to belong to multiple categories.

Updating Category Association

public function update(ProductRequest $request, Product $product)
{
    // ...
    
    // Product categories
    if ($request->has('category_ids')) {
        $product->categories()->sync($request->category_ids);
    }
    
    // ...
}
Location: ~/workspace/source/app/Http/Controllers/ProductController.php:324-326 The sync() method updates the category associations, removing old ones and adding new ones as specified.

Category Types

Physical vs Digital

Categories are separated by product type:
$categories = Category::where('digital', 0)->get(); // Physical products
$categories = Category::where('digital', 1)->get(); // Digital products
This ensures that digital products (like ebooks, software) have different category structures than physical products.

Classified Products

Categories can also be used for classified ads:
public function classified_products()
{
    return $this->hasMany(CustomerProduct::class);
}
Location: ~/workspace/source/app/Models/Category.php:39-41

Category Filtering in Products

The ProductController uses categories for filtering during product editing:
public function admin_product_edit(Request $request, $id)
{
    CoreComponentRepository::initializeCache();

    $product = Product::findOrFail($id);
    if ($product->digital == 1) {
        return redirect('admin/digitalproducts/' . $id . '/edit');
    }

    $lang = $request->lang;
    $tags = json_decode($product->tags);
    $categories = Category::where('parent_id', 0)
        ->where('digital', 0)
        ->with('childrenCategories')
        ->get();
    return view('backend.product.products.edit', compact('product', 'categories', 'tags', 'lang'));
}
Location: ~/workspace/source/app/Http/Controllers/ProductController.php:265-281

Brand-Product Filtering

Products can be retrieved by brand:
public function get_products_by_brand(Request $request)
{
    $products = Product::where('brand_id', $request->brand_id)->get();
    return view('partials.product_select', compact('products'));
}
Location: ~/workspace/source/app/Http/Controllers/ProductController.php:467-471

Implementation Examples

// Get all parent categories with their children
$parentCategories = Category::where('parent_id', 0)
    ->with('childrenCategories')
    ->get();

// Access nested structure
foreach ($parentCategories as $parent) {
    echo $parent->getTranslation('name');
    
    foreach ($parent->categories as $child) {
        echo "  - " . $child->getTranslation('name');
        
        // Access grandchildren
        foreach ($child->categories as $grandchild) {
            echo "    - " . $grandchild->getTranslation('name');
        }
    }
}
// Get categories with product counts
$categories = Category::withCount('products')->get();

foreach ($categories as $category) {
    echo $category->getTranslation('name') . ": " . $category->products_count . " products";
}

Database Structure

Category Fields

  • id - Primary key
  • parent_id - Reference to parent category
  • level - Category hierarchy level
  • name - Default name
  • slug - URL-friendly identifier
  • banner - Banner image ID
  • icon - Icon image ID
  • cover_image - Cover image ID
  • digital - Physical (0) or Digital (1) category
  • featured - Featured category flag
  • order - Display order

Brand Fields

  • id - Primary key
  • name - Default brand name
  • logo - Logo image ID
  • slug - URL-friendly identifier
  • meta_title - SEO meta title
  • meta_description - SEO meta description

Product Management

Learn how products use categories and brands

Multi-Language

Understand the translation system

Build docs developers (and LLMs) love