简体   繁体   中英

Get full path of nested parents

I have a model called Source which contains a parent_id column. Each source can have a parent_id , and the hierarchy is infinite. If a Source has no parent_id , then it is a root.

Now, I currently have the following methods in my model:

public function parent()
{
    return $this->hasOne('App\Source', 'id', 'parent_id');
}

public function children()
{
    return $this->hasMany('App\Source', 'parent_id')->orderBy('name');
}

I have no problem obtaining a nice list of the children eg:

$parents = Source::with('children')->whereNull('parent_id')->orderBy('name')->get();
$traverse = function ($parents, $prefix = '') use (&$traverse) {
    foreach ($parents as $parent) {
        echo '<option value="'.$parent->id.'">'.$prefix.$parent->name.'</option>';
        $traverse($parent->children, $prefix.'- ');
    }
};
$traverse($parents);

My problem is that I want to get a full string of the model name along with its parents names.

So say I had the following sources:

Parent 1
- Child 1
- - Subchild 1
- - Subchild 2
- Child 2

I'm trying to create a function that will give me Parent 1 - Child 1 - Subchild 1 when called on Subchild 1

Here is what I've tried, which only seems to give me the top level parent name:

public static function treeName(Source $source, &$tree)
{
    if ($source->parent) {
        $tree[] = self::treeName($source->parent, $tree);
    }
    else {
        $tree[] = $source->name;
    }
}

$source = Source::where('name', 'Subchild 1')->first();
$tree = [];
Source::treeName($source, $tree);
Log::info($tree);

This gives me:

[2018-04-25 23:02:25] laravel.INFO: array (
  0 => 'Parent 1',
  1 => NULL,
  2 => NULL,
)

I can simply implode the array by - but the array isn't giving me what I want. How can I get this to work?

Here is what I want:

array (
      0 => 'Parent 1',
      1 => 'Child 1',
      2 => 'Subchild 1',
    )

This should get you the desired result in an array:

function toArray($child) {
    $tree = [];

    while($child) {
        // Prepand the name to the front of the array
        array_unshift($tree, $child->name);
        // Overwrites `$child` with it's parent, for next iteration
        // If the parent doesn't exist, $child will be null
        // which will also end the `while` loop
        $child = $child->parent;
    }
    return $tree;
}

Pass it the child's object and it'll return the array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM