-1

I have created a function that returns an array of data for the descendants of a chosen Parent.

First it checks for Children of the Parent whose UUID we have fed to it, it then checks for further Children of those Children and so on down the family tree, eventually returning an array of all users in the chosen Parents lineage.

    Example of my DB Table
    **id, name, uuid, parent**
    1, John, 0001, none
    2, Steve, 0002, 0001
    3, Mark, 0003, 0001
    4, Kevin, 0004, 0002
    5, Adam, 0005, 0003

    function checkForChildren($uuid, $conn){
        global $familyArray;
    
        $sql = "SELECT id, uuid, name FROM people WHERE parent = '".$uuid."'";
        $result = mysqli_query($conn, $sql);
        
        /*-- Data has been found --*/
        if (mysqli_num_rows($result) > 0){
            foreach ($result as $row){
                $familyArray[]= 
                [
                    'id' => $row['id'],
                    'uuid' => $row['uuid'],
                    'name' => $row['name']
                ];                
                checkForChildren($row['uuid'],$conn);
            }
        }
        return $familyArray;
    }

The code works fine with $familyArray as a global variable, but I have come to understand that using global variables isn't good practice.

Without $familyArray being global, the function no longer returns the full family lineage, only the direct descendants of the parent $uuid we are originally feeding into the function.

Does anybody have any idea of ways to make this work without the array being global?

Thanks in advance.

1 Answer 1

1

You could return array result from the recursive call and array merge them at the parent level call.

<?php

function checkForChildren($uuid, $conn){
    $familyArray = [];

    $sql = "SELECT id, uuid, name FROM people WHERE parent = '".$uuid."'";
    $result = mysqli_query($conn, $sql);

    foreach ($result as $row){
        $familyArray[] = [
            'id' => $row['id'],
            'uuid' => $row['uuid'],
            'name' => $row['name']
        ];                
        $familyArray = array_merge($familyArray,checkForChildren($row['uuid'],$conn));
    }

    return $familyArray;
}

Update:

I would suggest you to have a look at the with recursive cte queries to avoid roundtrips via DB query calls to DB server.

4
  • 1
    Thank you! I've spent the last 8 hours or so tinkering with solutions. This has worked perfectly. Very much appreciate the help. I noticed you removed the check to see if there were 1 or more rows of data returned, is this because "foreach ($result as $row)" wouldn't fire from NULL? Thank you again! You've just added a small strand of fibre that will one day become a string in this bow I'm trying to carve lol. :thumbsup: Commented Dec 1, 2021 at 5:25
  • @LearningLanguages No problem. We all have been there spending hours trying to figure out the issue and it's solution. Just don't give up. Yes, I removed the if condition check assuming foreach would handle the empty array result of $result as well. You could just var_dump($result) to check what is being returned each time. You can restore back the if condition if it's causing an issue with empty rows returned from MySQL.
    – nice_dev
    Commented Dec 1, 2021 at 5:31
  • 1
    Thanks for the explantion =) It should be fine without the if condition, as I'm using the array length as the total number of descendants, so I can add an "if 0" check on the actual profile page that shows the family tree. Thank you again! Now my project uses no global variables at all =) Commented Dec 1, 2021 at 5:37
  • @LearningLanguages Good to hear that. If the $uuid is coming from frontend, you will need to use prepared statements for security. Global variables are mostly bad but sometimes useful, for example, a single global $app instance for the entire application. Even wordpress gives us a $wpdb global DB variable to work with. But yes, in your context, avoiding them is a good approach.
    – nice_dev
    Commented Dec 1, 2021 at 5:45

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.