l5-repository 怎么拼接搜索条件

原因

最近项目引入了 l5-repository 这个组件,然后发现当列表有搜索条件的时候,写的很别扭。因为这个组件支持的搜索格式很奇怪:

'http://prettus.local/users?search=John%20Doe'

这样:

'http://prettus.local/users?search=John&searchFields=name:like'

还有这样:

'http://prettus.local/users?search=age:17;email:john@gmail.com&searchJoin=and'

我沉默了一下,那我写个组装搜索条件的方法去兼容它?
我的感觉还是很奇怪。
又去看了它的 criteria 类,需要建一个这样的类,把搜索条件写进去,然后调用方法应用这个搜索类。
那只有一个搜索条件的情况下,建一个搜索类也不是很划算。
而这个 repository 组件没有 where 方法,自己拼接搜索条件也不行。

用后感

不知道是我的使用方法不正确,总是觉得这个组件很鸡肋,因为 ORM 方法用不了了,而 repository 也没有这些功能。结果导致控制器里有些地方是用 ORM,有些地方用 repository。
补充:用 scopeQuery 方法可以实现,这种写法看着还是难受的

$repository->scopeQuery(function ($query) use ($request) {
    if ($keyword = $request->get('keyword')) {
        $query = $query->where('keyword', $keyword);
    }
    return $query;
});

提问

有没有更好的解决方法?
可以不用建 criteria,不用管它的搜索格式。

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

这个我也很烦,我选择 https://github.com/Tucker-Eric/EloquentFil... 这个库来一起配合使用。
写一个这样的criteria


<?php

namespace App\Criteria;

use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;

/**
 * Class FilterCriteria
 * @package namespace App\Criteria;
 */
class FilterCriteria implements CriteriaInterface
{
    protected $map;

    /**
     * IsCommonCriteria constructor.
     * @param             $map
     */
    public function __construct($map)
    {
        $this->map = $map;
    }

    /**
     * Apply criteria in query repository
     *
     * @param                     $model
     * @param RepositoryInterface $repository
     *
     * @return mixed
     */
    public function apply($model, RepositoryInterface $repository)
    {
        return $model->filter($this->map);
    }
}

然后repository里面写一个filter方法

/**
     * 自动设置过滤
     * @param array $map
     * @return $this
     */
    public function filter(array $map)
    {
        $this->popCriteria(FilterCriteria::class);

        return $this->pushCriteria(new FilterCriteria($map));
    }

写好ModelFilter的条件,要做查询就可以这样用了,例如查询性别是女的会员:


    public function __construct(MemberRepository $repo)
    {
        $this->repo = $repo;
    }
    public function index(Request $request)
    {
        $this->repo->filter(['sex' => 'female'])->get();
    }
5年前 评论
讨论数量: 7
张无忌

建议自己封装,用别人写好的增加学习成本也不利于自己的进步

5年前 评论

@张无忌 自己封装可以,但就是觉得很奇怪,有没有用过的朋友说一下你们是怎么用的?

5年前 评论
张无忌

@xvotan 这个没用过,我一般都是参考别人的思路然后自己写一套适合自己项目用的

5年前 评论
幽弥狂

看过别人的代码 基本上都是自己封装 I5这个好像很重

5年前 评论
xvotan (楼主) 5年前
sanders

没有用于生产环境过,但我的感觉是选用这个仓库包,用 criteria 就是很必要的。

5年前 评论
sanders (作者) 5年前
xvotan (楼主) 5年前
朕略显ぼうっと萌

这个我是用模型里面的作用域来做的,不知道可不可以

<?php
namespace App\Models;

use Illuminate\Database\Query\Builder;

class Mould extends Model{

    ...

    /**
     * @auth: kingofzihua
     * @param Builder $query
     * @param $name
     * @return mixed
     */
    public function scopeQueryLikeName($query, $name)
    {
        return $query->where('name', 'like', "%{$name}%");
    }

    /**
     * @auth: kingofzihua
     * @param Builder $query
     * @param $name
     * @return mixed
     */
    public function scopeSearchName($query, $name)
    {
        return $name ? $query->queryLikeName($name) : $query;
    }
}

使用的时候像下面这样:

Mould::searchName(request('keyword'))->get();
5年前 评论

这个我也很烦,我选择 https://github.com/Tucker-Eric/EloquentFil... 这个库来一起配合使用。
写一个这样的criteria


<?php

namespace App\Criteria;

use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;

/**
 * Class FilterCriteria
 * @package namespace App\Criteria;
 */
class FilterCriteria implements CriteriaInterface
{
    protected $map;

    /**
     * IsCommonCriteria constructor.
     * @param             $map
     */
    public function __construct($map)
    {
        $this->map = $map;
    }

    /**
     * Apply criteria in query repository
     *
     * @param                     $model
     * @param RepositoryInterface $repository
     *
     * @return mixed
     */
    public function apply($model, RepositoryInterface $repository)
    {
        return $model->filter($this->map);
    }
}

然后repository里面写一个filter方法

/**
     * 自动设置过滤
     * @param array $map
     * @return $this
     */
    public function filter(array $map)
    {
        $this->popCriteria(FilterCriteria::class);

        return $this->pushCriteria(new FilterCriteria($map));
    }

写好ModelFilter的条件,要做查询就可以这样用了,例如查询性别是女的会员:


    public function __construct(MemberRepository $repo)
    {
        $this->repo = $repo;
    }
    public function index(Request $request)
    {
        $this->repo->filter(['sex' => 'female'])->get();
    }
5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!