Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Optimizing PHP Recursive Tree Building with Native Array Functions

Tech May 16 1

When building hierarchical systems like permission trees or category menus, recursive algorithms are often the first choice. However, traditional recursion in PHP can become prohibitively slow when dealing with datasets exceeding 10,000 records and nesting beyond three levels.

A practical solution is to replace deep recursion with iterative filtering using native PHP array functions — specifically array_filter. This approach avoids the overhead of repeated function calls and drastically improves perofrmance.

Sample Table Structure

CREATE TABLE `admin_permission` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `parent_permission_id` int unsigned NOT NULL DEFAULT '0',
  `permission_name` varchar(50) NOT NULL,
  `permission_url` varchar(100) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `parent_permission_id` (`parent_permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Performance Comparison

With ~14,350 records:

  • Traditional Recursion: ~6 seconds per run
  • Native Array Filtering: ~1 second or less

Inefficient Recursive Approach

public static function buildTreeRecursive(array $items, int $parentId = 0, string $parentKey = 'parent_id'): array {
    $branch = [];
    foreach ($items as $item) {
        if ($item[$parentKey] == $parentId) {
            $children = self::buildTreeRecursive($items, $item['id'], $parentKey);
            if (!empty($children)) {
                $item['children'] = $children;
            }
            $branch[] = $item;
        }
    }
    return $branch;
}

Optimized Iterative Approach (3-Level Example)

$rootItems = array_filter($flatList, fn($item) => $item[$parentField] == 0);

foreach ($rootItems as &$level1) {
    $level1['children'] = array_filter($flatList, fn($item) => $item[$parentField] == $level1['id']);
    
    foreach ($level1['children'] as &$level2) {
        $level2['children'] = array_filter($flatList, fn($item) => $item[$parentField] == $level2['id']);
        
        // Optional: Add third level
        // foreach ($level2['children'] as &$level3) {
        //     $level3['children'] = array_filter($flatList, fn($item) => $item[$parentField] == $level3['id']);
        // }
    }
}

Complete Benchmarking Snippet

// Fetch flat list from DB
$permissions = AdminPermission::orderBy('id')->get(['id', 'parent_permission_id', 'permission_name'])->toArray();

echo "Total records: " . count($permissions) . "\n";

// Test recursive method
$start = microtime(true);
$treeRecursive = self::buildTreeRecursive($permissions, 0, 'parent_permission_id');
echo "Recursive: " . (microtime(true) - $start) . " seconds\n";

// Test filtered method
$start = microtime(true);
$treeFiltered = self::buildTreeFiltered($permissions, 'parent_permission_id');
echo "Filtered: " . (microtime(true) - $start) . " seconds\n";

Scalability Recommendations

  • For deeply nested structures, consider lazy loading — fetch children only when expanded.
  • Implement pagination or virtual scrolling for large sibling lists.
  • Avoid AI-generated "optimizations" that ignore real-world data access patterns.
  • Cache built trees when source data is relatively static.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.