Search Filters Controller Documentation
File: /controllers/searchFiltersController.php
Purpose: Manages hierarchical search filters/categories for product organization and filtering
Last Updated: December 20, 2024
Total Functions: 12 main functions + 4 utility functions
Lines of Code: ~460
---
๐ Overview
The Search Filters Controller is a comprehensive category management system that provides hierarchical product filtering and organization capabilities. This controller handles:
- โข Hierarchical category/filter structures with parent-child relationships
- โข Multi-language support (Arabic/English category names)
- โข Color-coded category identification
- โข AJAX endpoints for dynamic category selection
- โข Bulk operations (delete, restore)
- โข Recursive category tree management
- โข Integration with product management system
Primary Functions
- โ Create and manage hierarchical categories/filters
- โ Multi-language category names (Arabic/English)
- โ Parent-child category relationships
- โ Color coding for visual category identification
- โ AJAX search and autocomplete functionality
- โ Bulk category operations
- โ Soft delete with restore functionality
- โ Recursive category tree operations
- โ Category path generation and display
Related Controllers
- โข productController.php - Product management
- โข productCatController.php - Product categories
- โข onlineCatController.php - Online store categories
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|---|---|---|
| **searchfilters** | Hierarchical search filters/categories | id, name, name_en, parentid, conditions, color_code, user_id, created_at, updated_at |
| Table Name | Purpose | Key Columns |
|---|---|---|
| **product** | Products linked to filters | productId, searchfiltersid |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **youtubelink** | Tutorial video links | youtubelinkid, title, url | |
| **programsettings** | System configuration | programsettingsid, settingkey, settingvalue |
-- Hierarchical structure
searchfilters.parentid -> searchfilters.id (self-referencing)
-- Product integration
product.searchfiltersid -> searchfilters.id
-- User tracking
searchfilters.user_id -> user.userid
---
๐ Key Functions
1. Default Action (empty $do) - Add Form Display
Location: Lines 95-99
Purpose: Display form for creating new search filters/categories
Process Flow:
1. Load parent categories via getSearchFiltersParents()
2. Assign categories to template
3. Display add form
Template Variables:
- โข
$categories- Available parent categories for selection
---
2. add ($do == "add") - Create Search Filter
Location: Lines 100-108 (function at 264-288)
Purpose: Create new search filter/category with hierarchical support
Function Signature:
function add()
Form Fields:
- โข
name- Arabic category name (required) - โข
name_en- English category name - โข
parent- Parent category ID (-1 for root level) - โข
color_code- Color code for visual identification (default: #000000)
Process Flow:
1. Extract form data from POST
2. Validate parent ID (-1 becomes 0 for root)
3. Create new searchfilters record using RedBeanPHP
4. Set metadata (timestamps, user, color)
5. Return inserted ID
Database Operation:
$searchFilters = R::dispense('searchfilters');
$searchFilters->conditions = 0; // Active
$searchFilters->created_at = date("Y-m-d H:i:s");
$searchFilters->updated_at = date("Y-m-d H:i:s");
$searchFilters->name = $name;
$searchFilters->name_en = $name_en;
$searchFilters->parentid = $parent;
$searchFilters->user_id = $_SESSION['userid'];
$searchFilters->color_code = isset($_POST['color_code']) ? $_POST['color_code'] : '#000000';
$id = R::store($searchFilters);
---
3. show ($do == "show") - Display Categories List
Location: Lines 109-125 (function at 290-300)
Purpose: Display all search filters with hierarchical information
Parameters:
- โข
catId- Optional category ID to filter by
Process Flow:
1. Load YouTube tutorial links
2. Check if specific category ID provided
3. Call appropriate display function (showByCatId() or show())
4. Enable custom validation and checks
Template Variables:
- โข
$allData- All category data - โข
$youtubes- Tutorial video links - โข
$searchFiltersData- Formatted category data with parent names
---
4. executeOperation ($do == "executeOperation") - Bulk Operations
Location: Lines 125-135 (function at 313-354)
Purpose: Handle bulk operations on multiple categories
Parameters:
- โข
operation- Operation type (1 = temp delete, 2 = restore) - โข
choosedItem[]- Array of category IDs to operate on
Process Flow:
1. Get operation type from POST
2. Iterate through selected category IDs
3. For each category:
- Load category name for feedback
- Execute operation (delete/restore)
- Collect success/error messages
4. Display operation results
Operation Types:
if ($operationType == '1') { // Temp delete
$note = tempdelete($id);
} elseif ($operationType == "2") { // Restore
returndelete($id);
}
---
5. tempdelete ($do == "tempdelete") - Soft Delete
Location: Lines 142-157 (function at 356-381)
Purpose: Mark category as deleted with dependency checking
Parameters:
- โข
id- Category ID to delete
Function Signature:
function tempdelete($id)
Process Flow:
1. Check for dependent products (commented out in current code)
2. Check for child categories
3. If dependencies exist, return error message
4. If safe to delete, mark as deleted (conditions = 1)
5. Return success/error status
Dependency Checking:
// Check for child categories
$childCategories = R::getAll('SELECT * FROM searchfilters WHERE parentid = ' . $id);
if (count($childCategories) > 0) {
$note = "ูุง ูู
ูู ุญุฐู ูุฐุง ุงูุชุตููู ูุงุฑุชุจุงุทู ุจุจูุงูุงุช ุฃุฎุฑู";
} else {
// Safe to delete
R::exec('UPDATE searchfilters SET sysdate = "' . date("Y-m-d") . '", user_id = ' . $_SESSION['userid'] . ', conditions = 1 where id = ' . $id);
$note = "success";
}
---
6. returndelete ($do == "returndelete") - Restore Deleted Category
Location: Lines 135-142 (function at 383-391)
Purpose: Restore soft-deleted category
Parameters:
- โข
id- Category ID to restore
Function Signature:
function returndelete($id)
Process Flow:
1. Update conditions field to 0 (active)
2. Category becomes visible again in listings
---
7. edit ($do == "edit") - Edit Form Display
Location: Lines 167-182 (function at 393-398)
Purpose: Display edit form for existing category
Parameters:
- โข
id- Category ID to edit - โข
parentid- Optional parent category ID
Process Flow:
1. Load all parent categories (excluding current category)
2. Load current category data
3. If parent ID provided, load parent data for context
4. Display edit form with pre-filled data
---
8. update ($do == "update") - Update Category
Location: Lines 183-193 (function at 400-424)
Purpose: Update existing search filter/category
Function Signature:
function update()
Form Fields:
- โข
id- Category ID to update - โข
conditions- Category status - โข
name- Arabic category name - โข
name_en- English category name - โข
parent- Parent category ID - โข
color_code- Color code
Process Flow:
1. Extract form data including category ID
2. Validate parent ID
3. Load existing category record
4. Update all fields with new values
5. Save updated record
---
9. getallsearchfilters ($do == "getallsearchfilters") - AJAX Category Search
Location: Lines 200-219
Purpose: AJAX endpoint for category autocomplete/search
Parameters:
- โข
term- Search term - โข
page_limit- Results limit - โข
withoutId- Category ID to exclude from results
Process Flow:
1. Query categories matching search term
2. For each result, generate category path
3. Format as JSON array for autocomplete
4. Return JSON response
Response Format:
$row_array = array();
$row_array['id'] = $parentId;
$row_array['text'] = $pathArr; // Full category path
array_push($return_arr, $row_array);
echo json_encode($return_arr);
---
10. getallSubFilters ($do == "getallSubFilters") - AJAX Subcategory Search
Location: Lines 220-242
Purpose: AJAX endpoint for leaf category search (categories without children)
Parameters:
- โข
term- Search term - โข
page_limit- Results limit - โข
withoutId- Category ID to exclude
Process Flow:
1. Query categories that are not parents (leaf nodes)
2. Include parent name in results
3. Generate category paths
4. Return JSON formatted results
SQL Query:
SELECT child.*, parent.name as parentName
FROM searchfilters child
LEFT JOIN searchfilters parent ON child.parentid = parent.id
WHERE child.conditions = 0
AND child.id NOT IN (SELECT DISTINCT(parentid) FROM searchfilters)
AND child.name LIKE "%{$term}%"
LIMIT {$limit}
---
๐ Workflows
Workflow 1: Hierarchical Category Creation
---
Workflow 2: Category Management and Operations
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=` (empty) | Default action | Display category creation form | |
| `do=add` | `add()` | Create new search filter category | |
| `do=show` | `show()` / `showByCatId()` | Display categories list | |
| `do=executeOperation` | `executeOperation()` | Handle bulk operations | |
| `do=tempdelete` | `tempdelete()` | Soft delete category | |
| `do=returndelete` | `returndelete()` | Restore deleted category | |
| `do=edit` | `edit()` | Display edit form | |
| `do=update` | `update()` | Update category | |
| `do=deleteFinaly` | `deleteFinaly()` | Permanently delete category | |
| `do=getallsearchfilters` | AJAX endpoint | Category autocomplete search | |
| `do=getallSubFilters` | AJAX endpoint | Subcategory search |
Category Creation (do=add):
- โข
name- Arabic category name (required) - โข
name_en- English category name (optional) - โข
parent- Parent category ID (optional, -1 for root) - โข
color_code- Color code (optional, defaults to #000000)
Category Display (do=show):
- โข
catId- Optional category ID to filter by
Bulk Operations (do=executeOperation):
- โข
operation- Operation type (1=delete, 2=restore) - โข
choosedItem[]- Array of category IDs
Edit Category (do=edit):
- โข
id- Category ID to edit - โข
parentid- Optional parent category context
Update Category (do=update):
- โข
id- Category ID - โข
name- Arabic name - โข
name_en- English name - โข
parent- Parent category ID - โข
conditions- Category status - โข
color_code- Color code
AJAX Endpoints:
- โข
term- Search term - โข
page_limit- Results limit - โข
withoutId- Category ID to exclude
---
๐งฎ Calculation Methods
Hierarchical Path Generation
function fetch_recursive($parentid, $categories) {
if ($parentid) {
$catData = R::getRow('SELECT child.*, parent.name as parentName
FROM searchfilters as child
LEFT JOIN searchfilters as parent ON child.parentid = parent.id
WHERE child.id = ' . $parentid);
if (count($catData) > 0) {
$categories .= $catData['name'] . '/';
$newParentId = $catData['parentid'];
return fetch_recursive($newParentId, $categories);
}
}
$categories = substr($categories, 0, strlen($categories) - 1); // Remove trailing slash
return $categories;
}
Parent ID Validation
// Convert -1 (no parent) to 0 (root level)
if (empty($parent) || $parent == -1) {
$parent = 0;
}
Status Management
// Active category
$searchFilters->conditions = 0;
// Deleted category (soft delete)
UPDATE searchfilters SET conditions = 1 WHERE id = ?
// Restore category
UPDATE searchfilters SET conditions = 0 WHERE id = ?
---
๐ Security & Permissions
Session Management
// Handle CURL requests with session initiation
if (isset($_POST['curlpost']) && $_POST['curlpost'] == 1) {
array_push($ajaxDoArr, $do);
}
// Conditional header/footer for AJAX requests
if (!in_array($do, $ajaxDoArr)) {
include("../public/impOpreation.php");
$smarty->display("header.html");
}
User Tracking
// Track user who creates/modifies categories
$searchFilters->user_id = $_SESSION['userid'];
// Audit trail for deletions
UPDATE searchfilters SET user_id = {user_id}, sysdate = "{date}" WHERE id = ?
Input Validation
- โข Search term sanitization: LIKE queries properly escaped
- โข Parent ID validation: Converted to integer, -1 handled as special case
- โข Color code validation: Default value provided if missing
- โข AJAX response validation: JSON encoding for safe data transmission
---
๐ Performance Considerations
Database Optimization
1. Indexes Recommended:
CREATE INDEX idx_searchfilters_parent ON searchfilters(parentid);
CREATE INDEX idx_searchfilters_conditions ON searchfilters(conditions);
CREATE INDEX idx_searchfilters_name ON searchfilters(name);
CREATE INDEX idx_searchfilters_user ON searchfilters(user_id);
```
2. **Query Performance**:
- Recursive category path generation may be slow for deep hierarchies
- Consider materialized path or closure table for better performance
- AJAX endpoints use LIMIT to control result size
- JOIN queries for parent-child relationships
3. **Memory Considerations**:
- Category hierarchy depth should be monitored
- AJAX responses limited by page_limit parameter
- Bulk operations process arrays in memory
### Potential Performance Issues
php
// N+1 Problem in recursive path generation
// Current: Multiple queries for each level
// Better: Single query with Common Table Expression (CTE)
// Improved approach:
WITH RECURSIVE category_path AS (
SELECT id, name, parentid, CAST(name AS VARCHAR(1000)) as path
FROM searchfilters WHERE parentid = 0
UNION ALL
SELECT s.id, s.name, s.parentid,
CONCAT(cp.path, '/', s.name) as path
FROM searchfilters s
JOIN category_path cp ON s.parentid = cp.id
)
SELECT * FROM category_path WHERE id = ?;
---
## ๐ Common Issues & Troubleshooting
### 1. **Recursive Loop in Category Hierarchy**
**Issue**: Category assigned as its own parent or circular reference
**Cause**: No validation preventing circular references
**Prevention**:
php
function validateParentAssignment($categoryId, $newParentId) {
// Check if new parent is descendant of current category
$descendants = getDescendants($categoryId);
if (in_array($newParentId, $descendants)) {
throw new Exception("Cannot create circular reference");
}
}
### 2. **Orphaned Categories After Deletion**
**Issue**: Child categories become orphaned when parent deleted
**Cause**: Dependency checking not comprehensive
**Fix**:
php
function tempdelete($id) {
// Check for child categories
$childCategories = R::getAll('SELECT * FROM searchfilters WHERE parentid = ' . $id);
if (count($childCategories) > 0) {
return "Cannot delete category with child categories";
}
// Check for associated products
$products = R::getAll('SELECT * FROM product WHERE searchfiltersid = ' . $id);
if (count($products) > 0) {
return "Cannot delete category with associated products";
}
// Safe to delete
// ... deletion code
}
### 3. **AJAX Endpoints Not Working**
**Issue**: Category search/autocomplete fails
**Cause**: Session management issues or incorrect headers
**Debug**:
php
// Check if AJAX request properly handled
if (!in_array($do, $ajaxDoArr)) {
// This should NOT execute for AJAX requests
include("../public/impOpreation.php");
}
// Verify JSON response format
header('Content-Type: application/json');
echo json_encode($return_arr);
### 4. **Path Generation Fails**
**Issue**: Category paths show incomplete or incorrect information
**Cause**: Recursive function hits null or circular references
**Debug**:
sql
-- Check for circular references
WITH RECURSIVE category_check AS (
SELECT id, parentid, 1 as level
FROM searchfilters WHERE id = [CATEGORY_ID]
UNION ALL
SELECT s.id, s.parentid, cc.level + 1
FROM searchfilters s
JOIN category_check cc ON s.id = cc.parentid
WHERE cc.level < 10 -- Prevent infinite recursion
)
SELECT * FROM category_check;
---
## ๐งช Testing Scenarios
### Test Case 1: Hierarchical Category Creation
1. Create root level category (parent = -1)
2. Create child category under root
3. Create grandchild category
4. Verify hierarchy displays correctly
5. Test category path generation
6. Confirm parent-child relationships
### Test Case 2: Bulk Operations
1. Create multiple test categories
2. Select multiple categories for bulk delete
3. Verify dependency checking works
4. Execute bulk operation
5. Check operation feedback messages
6. Test bulk restore functionality
### Test Case 3: AJAX Functionality
1. Test category autocomplete search
2. Verify search results format
3. Test subcategory filtering
4. Check JSON response structure
5. Test search with special characters
6. Verify pagination with page_limit
### Test Case 4: Circular Reference Prevention
1. Create parent category A
2. Create child category B under A
3. Attempt to make A a child of B
4. Verify system prevents circular reference
5. Test with deeper hierarchies
6. Check error messaging
```
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข productController.md - Product management
- โข productCatController.md - Product categories
- โข Database Schema Documentation - Table relationships
- โข AJAX Implementation Guide - Frontend integration
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When category management requirements change