Красноречивое рекурсивное отношение - PullRequest
1 голос
/ 08 января 2020

У меня проблема с тем, что я пытаюсь получить всех потомков объекта и сохранить только тех, у кого есть указанное свойство c.

У меня есть следующие отношения:

    public function getChildren()
    {
        return $this->hasMany(self::class, 'parent_id', 'id');
    }

    public function allChildren()
    {
        return $this->getChildren()->with('allChildren');
    }

И я получаю массив этого типа, например:

$array = [
           0 => ['name' => 'aaa', 'type' => 0, 'parent' => null, 'children' => [
                 1 => ['name' => 'bbb', 'type' => 1, 'parent' => null, 'children' => []], 
                 2 => ['name' => 'ccc', 'type' => 0, 'parent' => null, 'children' => [
                       3 => ['name' => 'ddd', 'type' => 1, 'parent' => 2, 'children' => []]
                        ]]
                    ]],
           4 => ['name' => 'eee', 'type' => 0, 'parent' => null, 'children' => []]
];

В этом примере я хотел бы удалить все объекты, которые имеют type 1, и получить чистый массив без них.

Я не очень понимаю, почему можно получить все потомки объекта, но не в состоянии пройти условия.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 09 января 2020

Решение только для коллекции будет выглядеть примерно так (поместите пользовательский макрос в поставщика услуг вашего приложения):

Collection::macro('whereDeep', function ($column, $operator, $value, $nested) {
    return $this->where($column, $operator, $value)->map(function ($x) use ($column, $operator, $value, $nested) {
        return $x->put($nested, $x->get($nested)->whereDeep($column, $operator, $value, $nested));
    });
});

Затем при необходимости вызовите:

$yourArray->whereDeep('type', '!=', 1, 'children');

Вкл. В вашем примере макрос работает так:

  1. Отфильтруйте все элементы, где: type != 1
    (внешний массив будет не тронут, поскольку оба элемента имеют type => 0)
  2. Для каждого элемента текущего массива:
    • Извлеките свойство children и примените ту же фильтрацию к этому подмассиву, начиная с первого пункта этой инструкции.
    • Замените свойство children на новое дочернее свойство только что отфильтровано.

В любом случае, вы должны попытаться глубоко понять, почему фильтрация отношений не работает. Это решение будет более эффективным, если его оптимизировать правильно.

0 голосов
/ 14 января 2020

Я нашел отличное решение, когда нет необходимости во всей этой рекурсии или любом из этих вызовов отношений, поэтому я делюсь им:

Использование: "gazsp / baum"


// get your object with roots method

$contents = Content::roots()->get();

// and simply run through the object and get whatever you need 
// thanks to getDescendantsAndSelf method

$myArray = [];

foreach($contents as $content) {
 $myArray[] = $content->getDescendantsAndSelf()->where('type', '!=', 1)->toHierarchy();
}

return $myArray;

Это работает для меня так же, как и другой метод выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...