Php Laravel:树过滤器子递归

Php Laravel:树过滤器子递归,php,laravel,eloquent,Php,Laravel,Eloquent,我似乎无法对以树模型格式定义的所有子级应用筛选,而这些子级使用了渴望加载机制 以下是我的模型定义(非常有用): 现在我想根据“criteria对象”过滤掉递归 public function getMachines(SectionCriteria $sectionCriteria = NULL) { /** * @var $builder Builder|Section */ $builder = Section::with([ 'childr

我似乎无法对以树模型格式定义的所有子级应用筛选,而这些子级使用了渴望加载机制

以下是我的模型定义(非常有用):

现在我想根据“criteria对象”过滤掉递归

public function getMachines(SectionCriteria $sectionCriteria = NULL)
{
    /**
     * @var $builder Builder|Section
     */
    $builder = Section::with([
        'children' => function ($query) use ($sectionCriteria) {
            if ($sectionCriteria) {
                foreach ($sectionCriteria->getFilterFlags() as $flagName => $flagValue) {
                    if ($flagValue) {
                        $query->whereFlag($flagName);  //Custom implementation
                    } else {
                        $query->whereNotFlag($flagName); //Custom implementation
                    }
                }
            }
        }
    ]);
此操作适用于树的第一级

我的问题是:是否有方法将对象传递给
children()
关系,以便我可以应用递归过滤器(适用于所有级别)

比如说:

注意:这是不可能的,因为只有回调被接受为参数

public function children($parameters)
{
    return $this->hasMany(
        self::class,
        'IdParent',
        'Id'
    )->with('children'=>$parameters);
}
我不想使用的(关于坚实的原则):

  • 创建一个包含条件的静态类变量
  • 任何类型的全局变量

  • 我还尝试检索递归的子对象(并应用过滤器),但最终得到了更多的查询,因此preety很好地优化了这些查询

    我使用了技巧#1(生成一个静态类变量),虽然我不太喜欢它,但它很有效

    型号

    /**
     * @var null|SectionCriteria
     */
    public static $childrenFilter = NULL;  //This can be whatever you need since it's static
    
    
    /**
     * @return HasMany
     */
    public function children()
    {
        return $this->hasMany(
            self::class,
            'IdParent',
            'Id'
        )->with(['children'=>self::searchChild()]);
    }
    
    /**
     * @return \Closure
     */
    public function searchChild()
    {
        return function ($builder) {
            if (Section::$childrenFilter) {
               foreach ($sectionCriteria->getFilterFlags() as $flagName => $flagValue) {
                    if ($flagValue) {
                        $query->whereFlag($flagName);  //Custom implementation
                    } else {
                        $query->whereNotFlag($flagName); //Custom implementation
                    }
                }
            }
        };
    }
    
    /**
     * @param SectionCriteria $criteria
     */
    public static function setChildSearch(SectionCriteria $criteria)
    {
        Section::$childrenFilter = $criteria;
    }
    
    /**
     * Remove the search criteria filter
     */
    public static function clearChildSearch()
    {
        Section::$childrenFilter = NULL;
    }
    
    存储库(实际使用)

    再一次…不是普里蒂,但它完成了任务

    New:另一种方法(将对此进行测试)是扩展
    Builder

    /**
     * @var null|SectionCriteria
     */
    public static $childrenFilter = NULL;  //This can be whatever you need since it's static
    
    
    /**
     * @return HasMany
     */
    public function children()
    {
        return $this->hasMany(
            self::class,
            'IdParent',
            'Id'
        )->with(['children'=>self::searchChild()]);
    }
    
    /**
     * @return \Closure
     */
    public function searchChild()
    {
        return function ($builder) {
            if (Section::$childrenFilter) {
               foreach ($sectionCriteria->getFilterFlags() as $flagName => $flagValue) {
                    if ($flagValue) {
                        $query->whereFlag($flagName);  //Custom implementation
                    } else {
                        $query->whereNotFlag($flagName); //Custom implementation
                    }
                }
            }
        };
    }
    
    /**
     * @param SectionCriteria $criteria
     */
    public static function setChildSearch(SectionCriteria $criteria)
    {
        Section::$childrenFilter = $criteria;
    }
    
    /**
     * Remove the search criteria filter
     */
    public static function clearChildSearch()
    {
        Section::$childrenFilter = NULL;
    }
    
    /**
     * @param SectionCriteria|NULL $sectionCriteria
     * @return Section[]|Collection
     */
    public function getMachines(SectionCriteria $sectionCriteria = NULL)
    {
        /**
         * @var $builder Builder|Section
         */
        $builder = Section::with(['children']); //Here I do not need the root elements to be filtered, If needed then use: Section::with(['children'=>Section::searchChild()])
        Section::setChildSearch($sectionCriteria);
        $builder->orderBy('Name');
        $results = $builder->get();
        Section::clearChildSearch();
        return $results;
    }