Fetching categories and subcategories from database
In no particular order:

Your id_parent field is nullable, and you use this fact to flag the category as having no parent.  This forces you to treat the field differently id_parent is NULL verse id_parent = ....  If you used a magic number, such as 0 to represent no parent, you could treat top level and child categories similarly.

You use a prepared statement, but create the SQL dynamically with "... where id_parent = {$array[$i][0]}".  This is poor design.  Use prepared statements with bound parameters to prevent SQL injection &amp; gain efficiency.

When you query your table, you retrieve all columns of data, but you are only using the name column and the 0th column.  Use "select id, name from..." to just retrieve the data you are going to use.  Not only do you gain efficiency, you document the code with the fields you will be using, and gain resilience against table structure changes that change the column indices.

The name column and the 0th column??  Be consistent; don't mix names and column numbers.

You are querying your SQL table multiple times, once for each possible category parent.  With n categories, you query the table n+1 times!  With such a small table, it would be better to query the table once, store the data in in-memory arrays, and then print the data from the in-memory arrays.

Why return 1;?  Nothing is returned when the function exits normally.  You could just return;.  Or better, reverse the test, put the print loop in the then clause, and don’t have any embedded returns!

Your SQL table should list id as primary key and possibly id_parent as foreign key references cat(id).



Sample code:

Building up the category ($cat) array with a single SQL query:

$stmt = $pdo-&gt;prepare("select id, name, id_parent from cat");
$stmt-&gt;execute()
$result = $stmt-&gt;fetchAll();

$root_id = NULL;
$cat = [$root_id =&gt; [ 'name' =&gt; '', 'children' =&gt; []]];

# Create $cat[id] entries for each row in table, with empty children list
foreach($result as $row) {
    $cat[$row['id']] = [ 'name' =&gt; $row['name'], 'children' =&gt; [] ];
}

# Add each item to its parent's children list
foreach($result as $row) {
    $cat[$row['id_parent']]['children'][] = $row['id'];
}


Displaying the categories from in-memory array:

function showCat($cat, $id) {
    echo $cat[$id]['name'];
    $children = $cat[$id]['children'];
    if ($children) {
        echo "&lt;ul&gt;";
        foreach($children as $child_id) {
            echo "&lt;li&gt;";
            showCat($cat, $child_id);
            echo "&lt;/li&gt;";
        }
        echo "&lt;/ul&gt;";
    }
}

showCat($cat, $root_id);