在通过另一种方法返回的模型上使用雄辩的关系

时间:2017-09-27 11:41:30

标签: php laravel eloquent laravel-query-builder

我有Category模型,该模型通过名为belongsToMany的数据透视表与Product模型建立product_to_category关系 我可以使用$ category-> products()在Category中获取所有产品,然后对其应用过滤器范围,以使用Request中给出的参数过滤结果,如下所示:

当我发送此请求时:

http://site.dev/category/205?product&available&brand

我应用这样的参数:

Category::find($id)->products()->filter($request)

问题在于我希望获得某个类别及其子类中的所有产品。现有的products关系只为我提供了给定类别的产品。

我尝试修改products()模型中的Category方法,如下所示:

  public function products()
    {
        return DB::table('oc_product')
            ->join('oc_product_to_category', 'oc_product_to_category.category_id', '=', 'oc_product_to_category.category_id')
            ->join('oc_category_path', 'oc_category_path.category_id', '=', 'oc_category.category_id')
            ->whereIn('oc_product_to_category.category_id', $this->children(true));
    }

但是当我这个代码:

Category::find($id)->products()->filter($request)

我收到此异常错误:

(1/1) BadMethodCallException
Call to undefined method Illuminate\Database\Query\Builder::filter()

我知道过滤器范围是在Model类中定义的,但是如何将filter范围应用于由修改后的products方法返回的QueryBuilder?

以下是我的课程:

产品型号:

class Product extends Model {
    public function scopeFilter( $request, QueryFilter $filters ) {
        return $filters->apply( $request );
    }


    public function categories() {
        return $this->belongsToMany( Category::class, 'product_to_category', 'product_id', 'category_id' );
    }
}

类别模型:

class Category extends Model
{
    public function scopeFilter($query, QueryFilter $filters)
    {
        return $filters->apply($query);
    }

    public function children($id_only = false)
    {
        $ids = $this->hasMany(CategoryPath::class, 'path_id', 'category_id')
            ->join('category', 'category.category_id', '=', 'category_path.category_id')
            ->where('category.status', 1)
            ->pluck('category.category_id');

        if ($id_only)
            return $ids;

        return self::find($ids);
    }

    public function parent()
    {
        $parent = DB::Select("SELECT  cp.path_id AS category_id FROM category_path cp LEFT JOIN category_description cd1 
                        ON (cp.path_id = cd1.category_id AND cp.category_id != cp.path_id) 
                        WHERE cd1.language_id = '2' AND cp.category_id = " . $this->category_id);

        return $parent;
    }

    public function products()
    {
        return $this->belongsToMany(Product::class, 'product_to_category', 'category_id', 'product_id');
    }
}

QueryFilter类:

abstract class QueryFilter {

    protected $request;
    protected $builder;

    public function __construct( Request $request ) {

        $this->request = $request;
    }

    public function filters() {
        return $this->request->all();
    }

    public function apply( Builder $builder ) {
        $this->builder = $builder;

        foreach ( $this->filters() as $name => $value) {
            if (method_exists($this, $name)) {
                call_user_func_array([$this, $name], array_filter([$value]));
            }
        }

        return $this->builder;
    }
}

CategoryFilter类:

class CategoryFilters extends QueryFilter
{
    public function id($id)
    {
        return $this->builder->where('category_id', $id);
    }

    public function procons()
    {
        return $this->builder->with('pros', 'cons');
    }

    public function available()
    {
        return $this->builder->where('quantity', '>', 0);
    }

    public function optionValues()
    {
        return $this->builder->with('optionValues');
    }

    public function description()
    {
        return $this->builder->with('description');
    }

    public function images()
    {
        return $this->builder->with('images');
    }

    public function order($order)
    {
        $params = explode(',', $order);
        $order = isset($params[0]) ? $params[0] : null;
        $way = isset($params[1]) && strtolower($params[1]) == 'desc' ? $params[1] : 'asc';

        if ($order) {
            return $this->builder->orderBy($order, $way);
        }

        return $this->builder;
    }
}

0 个答案:

没有答案