对父级和子级进行排序,最多2个级别

时间:2018-04-07 16:44:04

标签: php arrays sorting multidimensional-array

我有一个相当独特的问题,我现在已经拔牙了。

我基本上要做的是编写一个可以将bbPress论坛转换为我自己的Laravel论坛的导入器。导入用户工作正常,下一步是类别。由于以下原因,这是一个大问题:

bbPress可以有无限的子论坛,我自己的论坛只能有2个级别,这意味着每个类别可以有一个子类别。子类别不能再有子类别。有一个标签系统取代了具有子类别子类别的需要。例如:

Support
   Product line --> Available Tags: Product 1, Product 2..

我已经从bbPress导出文件中创建了一个数组,并添加了我需要的所有数据。重要的是要记住bbPress导入可以有无限的子类别,我的例子没有太多,在其他情况下可能会有所不同。无论如何,代码需要能够处理。对我来说很明显会有一些递归使用,不幸的是我无法弄清楚它应该在哪里以及它应该如何。我目前的例子如下:

array:14 [
  0 => array:5 [
    "exists" => true
    "post_id" => "2983"
    "parent_id" => 3058
    "data" => array:4 [
      "name" => "Product Downloader"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 11
  ]
  1 => array:5 [
    "exists" => true
    "post_id" => "2985"
    "parent_id" => 2983
    "data" => array:4 [
      "name" => "Plugins"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 3
  ]
  2 => array:5 [
    "exists" => true
    "post_id" => "2987"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 1"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 4
  ]
  3 => array:5 [
    "exists" => true
    "post_id" => "3058"
    "parent_id" => 0
    "data" => array:4 [
      "name" => "Support"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 1
  ]
  4 => array:5 [
    "exists" => true
    "post_id" => "3065"
    "parent_id" => 3058
    "data" => array:4 [
      "name" => "Protection Services"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 12
  ]
  5 => array:5 [
    "exists" => true
    "post_id" => "3279"
    "parent_id" => 3058
    "data" => array:4 [
      "name" => "Tutorials & How-Tos"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 13
  ]
  6 => array:5 [
    "exists" => true
    "post_id" => "3471"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 2"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 5
  ]
  7 => array:5 [
    "exists" => true
    "post_id" => "3472"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 3"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 6
  ]
  8 => array:5 [
    "exists" => true
    "post_id" => "3475"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 4"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 7
  ]
  9 => array:5 [
    "exists" => true
    "post_id" => "3476"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 5"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 8
  ]
  10 => array:5 [
    "exists" => true
    "post_id" => "3979"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 6"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 9
  ]
  11 => array:5 [
    "exists" => true
    "post_id" => "4683"
    "parent_id" => 3058
    "data" => array:4 [
      "name" => "Protection Services Advanced"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 14
  ]
  12 => array:5 [
    "exists" => true
    "post_id" => "6618"
    "parent_id" => 2985
    "data" => array:4 [
      "name" => "Module 7"
      "description" => ""
      "icon" => ""
      "locked" => 0
    ]
    "id" => 10
  ]
]

对于此问题,唯一相关的键是post_idparent_idparent_id引用post_id,忽略id字段。应该发生的事情如下:

该脚本会创建所有没有父ID的类别,这意味着父ID等于0.这是一个简单的部分。之后,它需要使用parent_id执行逻辑。它需要检查应导入的类别是否具有parent_id。如果是,则需要检查该父级是否有另一个父级。

如上所述,应该只有2个级别,所有其他级别应该用标记替换,这些级别将被分配给已创建的最低父级。

记住post_id并不总是低于parent_id,这很重要。可以先创建子项,然后创建父项,然后编辑子项并设置父项。在这种情况下,订单会搞砸,这意味着usort()不会得到很多帮助,至少从我的尝试来看。代码真的需要"解决"来自身份的父母。

上面的例子应该是这样的:

Support
   Product Downloader --> Tags: Plugins, Module 1 - Module 7
   Protection Services
   Protection Services Advanced
   Tutorials & How-Tos

您只需在类别和标签创建中添加占位符/虚拟代码,例如

$newCategory = create_category($name, $parent_id)

$newTag = create_tag($name, $category_id);

这两个调用都将返回已创建的类别/标记的主键。

问题在于如何正确地对数据进行排序和解析。我没有为问题添加代码,因为目前没有代码可以提供任何帮助,我有几次尝试,但没有一个按预期完成,他们都无法正确解决父母并决定是否有需要是标签而不是创建另一个类别。示例数组的json代码如下:

[{"exists":true,"post_id":"2983","parent_id":3058,"data":{"name":"Product Downloader","description":"","icon":"","locked":0},"id":6},{"exists":false,"post_id":"2985","parent_id":2983,"data":{"name":"Plugins","description":"","icon":"","locked":0},"id":8},{"exists":false,"post_id":"2987","parent_id":2985,"data":{"name":"Module 1","description":"","icon":"","locked":0},"id":9},{"exists":true,"post_id":"3058","parent_id":0,"data":{"name":"Support","description":"","icon":"","locked":0},"id":3},{"exists":true,"post_id":"3065","parent_id":3058,"data":{"name":"Protection Services","description":"","icon":"","locked":0},"id":4},{"exists":false,"post_id":"3279","parent_id":3058,"data":{"name":"Tutorials & How-Tos","description":"","icon":"","locked":0},"id":10},{"exists":false,"post_id":"3471","parent_id":2985,"data":{"name":"Module 2","description":"","icon":"","locked":0},"id":11},{"exists":false,"post_id":"3472","parent_id":2985,"data":{"name":"Module 3","description":"","icon":"","locked":0},"id":12},{"exists":false,"post_id":"3475","parent_id":2985,"data":{"name":"Module 4","description":"","icon":"","locked":0},"id":13},{"exists":false,"post_id":"3476","parent_id":2985,"data":{"name":"Module 5","description":"","icon":"","locked":0},"id":14},{"exists":false,"post_id":"3979","parent_id":2985,"data":{"name":"Module 6","description":"","icon":"","locked":0},"id":15},{"exists":true,"post_id":"4683","parent_id":3058,"data":{"name":"Protection Services Advanced","description":"","icon":"","locked":0},"id":5},{"exists":false,"post_id":"6618","parent_id":2985,"data":{"name":"Module 7","description":"","icon":"","locked":0},"id":16},{"exists":false,"post_id":"6618","parent_id":2985,"data":{"name":"Module 7","description":"","icon":"","locked":0},"id":16}]

#Edit:我们也可以让输入数组的键代表post_id,如果有任何帮助,那将导致以下json数据:

{"2983":{"exists":true,"post_id":"2983","parent_id":3058,"data":{"name":"Product Downloader","description":"","icon":"","locked":0},"id":6},"2985":{"exists":true,"post_id":"2985","parent_id":2983,"data":{"name":"Plugins","description":"","icon":"","locked":0},"id":8},"2987":{"exists":true,"post_id":"2987","parent_id":2985,"data":{"name":"Module 1","description":"","icon":"","locked":0},"id":9},"3058":{"exists":true,"post_id":"3058","parent_id":0,"data":{"name":"Support","description":"","icon":"","locked":0},"id":3},"3065":{"exists":true,"post_id":"3065","parent_id":3058,"data":{"name":"Protection Services","description":"","icon":"","locked":0},"id":4},"3279":{"exists":true,"post_id":"3279","parent_id":3058,"data":{"name":"Tutorials & How-Tos","description":"","icon":"","locked":0},"id":10},"3471":{"exists":true,"post_id":"3471","parent_id":2985,"data":{"name":"Module 2","description":"","icon":"","locked":0},"id":11},"3472":{"exists":true,"post_id":"3472","parent_id":2985,"data":{"name":"Module 3","description":"","icon":"","locked":0},"id":12},"3475":{"exists":true,"post_id":"3475","parent_id":2985,"data":{"name":"Module 4","description":"","icon":"","locked":0},"id":13},"3476":{"exists":true,"post_id":"3476","parent_id":2985,"data":{"name":"Module 5","description":"","icon":"","locked":0},"id":14},"3979":{"exists":true,"post_id":"3979","parent_id":2985,"data":{"name":"Module 6","description":"","icon":"","locked":0},"id":15},"4683":{"exists":true,"post_id":"4683","parent_id":3058,"data":{"name":"Protection Services Advanced","description":"","icon":"","locked":0},"id":5},"6618":{"exists":true,"post_id":"6618","parent_id":2985,"data":{"name":"Module 7","description":"","icon":"","locked":0},"id":16}}

编辑2:当前代码:

            $categoriesMapped = [];
            $posts = $categoriesToBeProcessed;
            // find all the categories
            foreach ($posts as $post) {
                if (!$post['parent_id']) {
                    $categoryCreate = $this->category->create($post['data']);
                    $categories[] = $categoryCreate;
                    $categoriesMapped[$categoryCreate->id] = $post['post_id'];
                }
            }

            // now find all the sub-categories and tags
            foreach ($categories as $category) {
                foreach ($posts as $post) {
                    if ($post['parent_id'] == $categoriesMapped[$category->id]) {
                        $data = $post['data'];
                        $data['parent_id'] = $category->id;
                        $thisSubcategory = $this->category->create($data);
                        $thisSubcategory->tags = $this->find_tags($categoriesMapped, $post['post_id'], $posts);
                        $category->subcategories[] = $thisSubcategory;
                    }
                }
            }

编辑3:最新代码:

private function find_tags($categoriesMapped, $id, $posts) {
    $tags = array();
    foreach ($posts as $post) {
        if ($post['parent_id'] == $categoriesMapped[$id]) {
            $tag = $this->tag->create($post['data']);
            $tags[] = $tag;
            $tag->category()->associate($id);
            // any subcategories below this?
            // TODO: How to fix this?
            $tags = array_merge($tags, $this->find_tags($categoriesMapped, $post['post_id'], $posts));
        }
    }
    return array_unique($tags, SORT_REGULAR);
}

我的主要功能中的代码:

 $categoriesMapped = [];
            $posts = $categoriesToBeProcessed;
            // find all the categories
            foreach ($posts as $post) {
                if (!$post['parent_id']) {
                    $categoryCreate = $this->category->create($post['data']);
                    $categories[] = $categoryCreate;
                    $categoriesMapped[$categoryCreate->id] = $post['post_id'];
                }
            }

            // now find all the sub-categories
            foreach ($categories as $category) {
                foreach ($posts as $post) {
                    if ($post['parent_id'] == $categoriesMapped[$category->id]) {
                        $data = $post['data'];
                        $data['parent_id'] = $category->id;
                        $thisSubcategory = $this->category->create($data);
                        $category->subcategories[] = $thisSubcategory;
                        $categoriesMapped[$thisSubcategory->id] = $post['post_id'];
                    }

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我认为以此为模型的代码应该做你想要的:

$posts = json_decode('[{"exists":true,"post_id":"2983","parent_id":3058,"data":{"name":"Product Downloader","description":"","icon":"","locked":0},"id":6},{"exists":false,"post_id":"2985","parent_id":2983,"data":{"name":"Plugins","description":"","icon":"","locked":0},"id":8},{"exists":false,"post_id":"2987","parent_id":2985,"data":{"name":"Module 1","description":"","icon":"","locked":0},"id":9},{"exists":true,"post_id":"3058","parent_id":0,"data":{"name":"Support","description":"","icon":"","locked":0},"id":3},{"exists":true,"post_id":"3065","parent_id":3058,"data":{"name":"Protection Services","description":"","icon":"","locked":0},"id":4},{"exists":false,"post_id":"3279","parent_id":3058,"data":{"name":"Tutorials & How-Tos","description":"","icon":"","locked":0},"id":10},{"exists":false,"post_id":"3471","parent_id":2985,"data":{"name":"Module 2","description":"","icon":"","locked":0},"id":11},{"exists":false,"post_id":"3472","parent_id":2985,"data":{"name":"Module 3","description":"","icon":"","locked":0},"id":12},{"exists":false,"post_id":"3475","parent_id":2985,"data":{"name":"Module 4","description":"","icon":"","locked":0},"id":13},{"exists":false,"post_id":"3476","parent_id":2985,"data":{"name":"Module 5","description":"","icon":"","locked":0},"id":14},{"exists":false,"post_id":"3979","parent_id":2985,"data":{"name":"Module 6","description":"","icon":"","locked":0},"id":15},{"exists":true,"post_id":"4683","parent_id":3058,"data":{"name":"Protection Services Advanced","description":"","icon":"","locked":0},"id":5},{"exists":false,"post_id":"6618","parent_id":2985,"data":{"name":"Module 7","description":"","icon":"","locked":0},"id":16},{"exists":false,"post_id":"6618","parent_id":2985,"data":{"name":"Module 7","description":"","icon":"","locked":0},"id":16}]');

$categories = array();

class Category {
    public $name;
    public $id;
    public $subcategories;

    public function __construct($post) {
        $this->name = $post->data->name;
        $this->id = $post->post_id;
        $this->subcategories = array();
    }
}

class Subcategory {
    public $name;
    public $id;
    public $tags;

    public function __construct($post) {
        $this->name = $post->data->name;
        $this->id = $post->post_id;
        $this->tags = array();
    }
}

class Tag {
    public $name;
    public $id;

    public function __construct($post) {
        $this->name = $post->data->name;
        $this->id = $post->post_id;
    }
}

function find_tags($id, $posts) {
    $tags = array();
    foreach ($posts as $post) {
        if ($post->parent_id == $id) {
            $tags[] = new Tag($post);
            // any subcategories below this?
            $tags = array_merge($tags, find_tags($post->post_id, $posts));
        }
    }
    return array_unique($tags, SORT_REGULAR);  
}

// find all the categories
foreach ($posts as $post) {
    if (!$post->parent_id) {
        $categories[] = new Category($post);
    }
}

// now find all the sub-categories and tags
foreach ($categories as $category) {
    foreach ($posts as $post) {
        if ($post->parent_id == $category->id) {
            $thisSubcategory = new Subcategory($post);
            $thisSubcategory->tags = find_tags($post->post_id, $posts);
            $category->subcategories[] = $thisSubcategory;
        }
    }
}

print_r($categories);

如果您需要在创建任何标记之前创建所有子类别,则可以将最后一个循环(前面是//现在找到所有子类别和标记)更改为这两个。这个效率相当低,这就是为什么我首先不用这种方式写它。

// now find all the sub-categories
foreach ($categories as $category) {
    foreach ($posts as $post) {
        if ($post->parent_id == $category->id) {
            $category->subcategories[] = new Subcategory($post);
        }
    }
}

// now find all the sub-categories and tags
foreach ($categories as $category) {
    foreach ($category->subcategories as $subcategory) {
        $subcategory->tags = find_tags($subcategory->id, $posts);
    }
}