如何编码递归函数以获取子类别ID(优化且不优化)Laravel
#编程 #php #laravel #codequality

今天,我将向您展示如何获得父级类别的所有子类别ID既优化又不优化。

的性能与优化是我一直以来一直以查询优化的方式或代码重构为目标的。

今天,我们将查看有关如何在处理递归功能或获取子类别ID列表时如何减少查询的查询优化。

我知道很难理解递归功能,而且更难创建一个功能。
因此,我将尝试清楚地解释一下。

需要:有关递归工作原理的知识,强大的OOP概念,Laravel,PHP,强大的DB设计和RDBMS知识。

ex: - 基本类别树结构看起来像

Image description

现在让我们看一下类别结构的外观,我们正在存储父级ID,它指的是主要类别ID。

Image description

我希望您知道这种结构的工作原理,如果没有几篇文章和视频解释了类别和子类别的数据库结构。

与产品类别DB设计。

Image description

现在,您可能已经在许多网站上看到了,您越远,您可以单击子类别,结果变得更短且独特。

这意味着,如果您选择了父类别,它将向您显示所有依赖该类别的产品,并且随着您的深入研究,它将向您显示更多与该类别相关的产品。

eg; - 如果您选择电子类别,它将向您显示所有电子子类别的产品,例如游戏,笔记本电脑,PC等。

那么我们该怎么做?我们将如何获取这些子类别的产品?

好吧,如果您了解类别的DB Strucutre的模式,您可以看到该设计不是基于循环的,而是基于嵌套的嵌套,因此在嵌套的关系或设计中,我们使用递归方法。

现在您可能已经听到了这个术语,但是您可能不知道在现实生活中如何使用它。

当您具有嵌套设计模式或结构时,递归功能主要使用。

一些示例:

第一个示例:一个文件夹可以具有许多文件夹,每个文件夹都可以具有更多文件夹

第二个示例:评论可以有很多答复,每个答复都可以有自己的答复

第三示例:类别可以具有许多子类别,每个子类别都可以具有多个子类别

我现在为您提供了一些现实世界情景的示例,我们将研究如何编码递归功能以获取子类别的产品。

imp:要获得此工作或为了完成这项工作,我们必须在数组中获得主要类别的所有子类别ID之后,我们可以将该数组放入这样的产品查询中:

Product::orWhereIn('id',$subCategoryIds)->get();

将获取数组中给出的所有类别的产品。

让我们仔细研究它的工作方式!


首先,我们将创建一个称为getubCategoryIds的递归函数,
我们将添加1个称为$ categoryId的参数(主要类别ID)

我们将创建一个名为“儿童”功能的数组,我们将存储父级的所有子类别ID,在第二步中,我们将存储参数ID,每次函数都会将其不同被称为,因此我们将在函数的每次运行中附加该类别ID

public function getSubcategoryids($categoryId)
{
  $children = [];

  $children[] = $categoryId

}

然后,我们将进行查询以通过其父id

查找子类别

看起来像这样:

$parentCategories = Category::where('parent_id', $categoryId)
                ->latest()
                ->select('id')
                ->get()

此查询将获取具有主要类别的parent_id的所有子类别。

public function getSubcategoryids($categoryId)
{
  $children = [];

  $children[] = $categoryId
  $parentCategories = Category::where('parent_id', $categoryId)
                ->latest()
                ->select('id')
                ->get()

    foreach ($parentCategories as $category)
    {
        $children[] = getSubcategoryids($category->id,$children);
    }             
   return Arr::flatten($children);         
}

之后,我们将为每个父类别运行循环,我们将在循环内再次运行该函数,并将传递类别ID参数,该函数是子类别ID,并将将函数值存储在孩子阵列中并返回。 /p>

由于结果将嵌套,我们必须将数组弄平,因此我们使用arr ::在此处弄平。

public function getSubcategoryids($categoryId)
{
  $children = [];

  $children[] = $categoryId
  $parentCategories = Category::where('parent_id', $categoryId)
                ->latest()
                ->select('id')
                ->get()

    foreach ($parentCategories as $category)
    {
        $children[] = $this->getSubcategoryids($category->id,$children);
    }             
   return Arr::flatten($children);         
}


public function index()
{

 $category = Category::where('parent_id',4)->first();
 $subcategoryIds = $this->getSubcategoryids($category->id)

 dd($subcategoryIds);

 //results: 4,5,8,12,3,7,8

}

现在我们再次调用该函数,并将传递我们想要的子类别的类别ID的参数。

我们将存储递归函数结果在变量
中 如果您dd()结果您可以看到所有子类别ID。

但是现在问题是,如果您在函数的每个呼叫中​​看到调试栏,则查询正在运行的函数,如果您有多个类别,则可能导致性能问题。

Image description

取而代之的是,我们有一个优化的解决方案,而不是在函数的每个调用上运行查询,我们可以过滤掉具有主要类别的父ID的类别吗?让我们更深入!


我们可以创建一个函数,其中我们将传递3个参数

**第一参数:**它将具有所有类别列表

第二个参数:儿童数组您将存储所有子类别ID

第三参数:父级ID,它将帮助您找到。

的子类别。

第一步:
我们将取出类别列表,我们将检查类别列表父级ID是否等于我们要找到的子类别的给定父级,如果是的话,我们将过滤出这些类别并将其存储到一个称为的变量中子类别。

第二步:
我们将循环浏览每个子类别,我们将附加孩子数组中的这些子类别ID。

第三步:
我们将再次调用该函数,并将子类别ID添加到参数中,以便我们也可以找到其子类别,并且ID将作为下一个函数调用中的父ID,并且此过程将继续重复直到父级ID不等于给定的父ID。

public function getSubcategoryids($categories, &$children, $parent_id = null)
{
   //filter out the categories who have subcategories by using its parent id
   //return those categories if the category parent id 
   //matches our parent id of the parameter    

  $subcategories = $categories->filter(function ($item) use ($parent_id) 
      return $item->parent_id == $parent_id; 

    });


    //loop through each subcategories
    foreach ($subcategories as $subcategory)
    {
        $children[] = $subcategory->id; //append each subcategory in the array
       //call the function again and send the subcategory id as a parameter
       //to check if it has subcategories or not 
        $this->getSubcategoryids($categories, $children, $cat->id);
    }
}


public function index()
{
  //your category list where the you will filter the subcategory 
  // by its parent id in the function
  $categories = DB::table('categories')->select('id', 'parent_id', 'name')->get();

  $subCategoryIds = []; //the array where we will store all the subcategory 

  //we call the function to store the results in the array 

  //and passing the category id to find the subcategories
  getSubcategoryids($categories, $subCategoryIds,$categoryId);

}

现在您只能看到单个查询是ran ran ran,如果您有多个类别

,这真的很好

Image description

您可以将这些子类别ID添加到产品查询中:


Product::orWhereIn('id',$subCategoryIds)->get();

您将看到它已经获取了类别和子类别的所有产品。

所以,我希望您喜欢这篇文章,如果您对代码重构感兴趣,代码和查询优化不忘记关注我
因为您将收到与此有关的很多文章。

下一篇文章:将其他逻辑转移到特征上。