Eloquent sync() belongsToMany with pivot and nested children

Eloquent sync() belongsToMany with pivot and nested children

我想解决这个问题。我有一个 json 这样的:

[
  {
    "id": 2,
    "title": "One",
    "parent": {},
    "children": [
      {
        "id": 3,
        "title": "One One",
        "parent": {
          "id": 2,
          "title": "One"
        },
        "children": [],
        "value": 1
      },
      {
        "id": 4,
        "title": "One Two",
        "parent": {
          "id": 2,
          "title": "One"
        },
        "children": [],
        "value": 2
      }
    ],
    "value": 3
  },
  {
    "id": 5,
    "title": "Three",
    "value": 3
  }
]

如你所见,每个项目可以有一个child,也可以有一个child,也可以有一个child等等。它是嵌套的。

现在我想将这些 items 和每个 child 保存在与主元的 belongsToMany 关系中(在本例中:value)。如果我想使用 sync(),我必须在我的控制器中准备好我的所有项目:

 <?php

/*Save $items*/
$items
    = collect($request->input('data.items'))->mapWithKeys(function (
    $item
) {

    if (array_key_exists('value', $item)) {
        $value = $item['value'];
    } else {
        $value = null;
    }

    return [
        $item['id'] => compact('value'),
    ];
});

$user->items()->sync($items);

但这并不会递归遍历所有 children。我想到了类似的事情:

/*Save items*/
$items
    = collect($request->input('data.items'))->mapWithKeys(function (
    $item
) {
    $traverse = function ($item) use (&$traverse) {
        if (array_key_exists('value', $item)) {
            $value = $item['value'];
        } else {
            $value = null;
        }

        foreach ($item['children'] as $child) {
            $child = $traverse($child);
        }

        $children = ($item['children']);

        return [
            $item['id'] => compact('value', 'children'),
        ];
    };

    $item = $traverse($item);

但这行不通。

我想要的结果:

首先我想说的是你的数据其实是JSON,不是数组。所以在这里我写了一些代码,你可以看到我解码并从中得到一个数组(从 loop() 函数开始)。

据我了解,您想将所有项目值收集到 1 个数组中,该数组将用于保存 1 个用户的所有关系。因此,您可以使用该输出数组(请参阅 loop() 函数的底部)。

protected $result = [];

protected function deepDiveIntoNextLevel(array $array) {
    foreach ($array as $item) {
        $this->result[] = $item['value'];
        if(!empty($item['children'])) {
            $this->deepDiveIntoNextLevel($item['children']);
        }
    }
}

public function loop()
{
    $json_array = '[
      {
        "id": 2,
        "title": "One",
        "parent": {},
        "children": [
          {
            "id": 3,
            "title": "One One",
            "parent": {
              "id": 2,
              "title": "One"
            },
            "children": [],
            "value": 1
          },
          {
            "id": 4,
            "title": "One Two",
            "parent": {
              "id": 2,
              "title": "One"
            },
            "children": [],
            "value": 2
          }
        ],
        "value": 3
      },
      {
        "id": 5,
        "title": "Three",
        "value": 3
      }
    ]';
    $initial_array = json_decode($json_array, true);

    $this->deepDiveIntoNextLevel($initial_array);
    $result = $this->result;
    // As output you may get an array, where you can have duplicates
    sort($result);
    // Or it can be not ordered
    $relations_ids_odered = array_unique($result);
}