V
V
vasisualii2016-05-24 18:43:42
PHP
vasisualii, 2016-05-24 18:43:42

Bug when copying a tree?

There is a certain tree structure of folders. Everything is stored in psql. You need to copy this structure so that the folders have new id's, but parent-child relationships remain between all new folders. Because since foreign keys are used in the database, it is necessary to create folders recursively, from root to child, so that all the necessary links are created in the database.
We get all the current folders and call the recursive function:

$groups = Group::query()->execute();
$newGroupId = $this->deployChildGroups($groups, 0,  []);

The recursive function itself
/**
     * @param $platformId
     * @param $parentId
     * @param $sourceGroups Device\Group[]
     * @param $resultsId
     */
    public function deployChildGroups($sourceGroups, $parentId, $resultsId)
    {
        // Если исходные папки находятся в корневой директории, то и новые создаем там же
        if ($parentId == 0) {
            $newParentId = 0;
        } else {
            if (! isset($resultsId[$parentId])) {
                return false;
            }
            $newParentId = $resultsId[$parentId];
        }

        foreach ($sourceGroups as $sourceGroup) {
            if ($sourceGroup->getParentId() == $parentId) {
                $group = new Group();
                $group->setName($sourceGroup->getName());
                $group->setParentId($newParentId);
                $group->save();

                $resultsId[$sourceGroup->getId()] = $group->getId();
                $resultsId = $this->deployChildGroups($sourceGroups, $sourceGroup->getId(), $resultsId);
            }
        }

        return $resultsId;
    }

The result, to be honest, is not very good. Only the first folders on each level are copied. These are:
2cc26380790a4d69ba1c71f9618a0837.png
Result:
{"210":"296","273":"297","274":"298"}
What's with the recursion parsley? Why is it not going through all the folders in a loop?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Niomin, 2016-05-24
@Niomin

Haven't looked at the bypass order?

if (! isset($resultsId[$parentId])) {
    return false;
}

At this location, it can skip a decent number of subfolders (including all).
Even sorted Groups do not guarantee that it will be possible to copy the entire tree, because if the parent appeared after the child, it will start from the child.
That is, the proposed algorithm, in principle, will not cope well with this task. It is necessary either to store in the form of a tree (that is, in memory), or to store a flag that this element has already passed (with incremental IDs, you can use the id value as a crutch-flag, more or less than the old maximum).
Other adequate solutions do not come to mind :)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question