【Laravel】存储仓Repository基础

laravel存储仓基础

本文基于 Laravel 9.* 版本,PHP 8.2 进行开发,所用扩展为 l5-repository

安装命令:
composer require prettus/l5-repository

创建存储仓

如果尚未创建过存储仓库的 Model,可以直接使用以下命令生成存储仓库文件:

php artisan make:repository Goods/Goods

此命令会自动生成 Model 及对应的存储仓库文件。

手动创建存储仓

创建接口

首先,创建一个存储仓库接口:

namespace App\Repositories\Goods\Interfaces;
use Prettus\Repository\Contracts\RepositoryInterface;

/**
 * Interface GoodsRepositoryRepository.
 *
 * @package namespace App\Repositories\Goods;
 */
interface GoodsRepository extends RepositoryInterface
{
    /**
     *
     * 获取商品列表信息
     *
     * @param $request
     * @return mixed
     */
    public function goodsPaginate($request);
}

创建接口实现

接下来,实现该接口:

namespace App\Repositories\Goods;

use App\Models\Goods;
use App\Repositories\Goods\Interfaces\GoodsRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use Prettus\Repository\Eloquent\BaseRepository;

/**
 * Class GoodsRepositoryRepositoryEloquent.
 *
 * @package namespace App\Repositories\Goods;
 */
class GoodsRepositoryEloquent extends BaseRepository implements GoodsRepository
{
    /**
     * Specify Model class name
     *
     * @return string
     */
    public function model()
    {
        return Goods::class;
    }

    protected $fieldSearchable = [
        'goods_name'=>'like',
        'goods_subname'=>'like',
        'goods_no'=>'like',
    ];

    /**
     * Boot up the repository, pushing criteria
     */
    public function boot()
    {
        $this->pushCriteria(app(RequestCriteria::class));
    }

    public function goodsPaginate($request)
    {
        // TODO: Implement goodsPaginate() method.
        $this->applyCriteria();
        $this->applyScope();
        $limit = (int)($data['page_size'] ?? 25);
        $limit = abs($limit) < 2000 ? abs($limit) : 2000;
        $page = abs((int)($data['page'] ?? 1));
        $results = $this->model->paginate($limit, ['*'], $pageName = 'page', $page);
        $this->resetModel();
        return $this->parserResult($results);
    }
}

在 config/app.php 中注册服务提供者

'providers' => [
	// .....
	App\Providers\RepositoryServiceProvider::class,
]

在 RepositoryServiceProvider 中绑定服务

 public function boot()
    {
        $this->app->bind(\App\Repositories\Goods\Interfaces\GoodsRepository::class, \App\Repositories\Goods\GoodsRepositoryEloquent::class);
    }

创建测试 Controller

namespace App\Http\Controllers\Learn;

use App\Http\Controllers\Controller;
use App\Repositories\Goods\Interfaces\GoodsRepository;
use Illuminate\Http\Request;

class GoodsController extends Controller
{

    /**
     * @var GoodsRepository
     */
    protected $repository;
    
    /**
     * GoodsController constructor.
     *
     * @param GoodsRepository $repository
     */
    public function __construct(GoodsRepository $repository)
    {
        $this->repository = $repository;
    }

    public function getList(Request $request)
    {
        return $this->repository->goodsPaginate($request);
    }
}

测试接口

访问接口:

http://xxx.test/api/Learn/goods/getList?search=goods_name:haha

返回的结果会是 goods_name 字段进行 like 模糊匹配,查询条件为 haha。

Criteria 封装查询逻辑的模式

Criteria 是一种用于封装查询逻辑的模式,可以将复杂的查询条件独立成类,从而提高代码的复用性、可读性和维护性。

作用
  • 动态过滤数据:通过 Criteria,你可以根据请求参数或业务需求动态地添加查询条件
  • 解耦查询逻辑:Criteria 将查询逻辑从仓库实现中分离出来,方便代码复用和测试
  • 链式调用:Criteria 可以组合使用,逐步添加查询条件
使用场景
  • 按条件过滤:例如,根据用户输入的关键词或筛选条件动态调整查询结果
  • 全局查询逻辑:比如,自动添加 where 条件过滤被软删除的数据
  • 复杂查询逻辑:将复杂查询封装到 Criteria 类中,保持代码简洁

使用示例

为了实现商品的灵活排序和状态筛选,我们通过以下两种 Criteria 对商品查询逻辑进行了封装:GoodsSortCriteria 用于处理排序逻辑,GoodsPublishedCriteria 用于状态筛选。下面是具体实现及业务调用的方式。

封装商品排序逻辑

GoodsSortCriteria 通过解析输入参数中的排序选项,动态生成排序规则,从而支持多种排序模式

namespace App\Criteria\Goods;

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

class GoodsSortCriteria implements CriteriaInterface
{
    public function __construct($filterData)
    {
        $this->request = $filterData;
    }

    const SORTBYCATEGORY = [
        'price-descending' => 'price_descending',
        'price-ascending' => 'price_ascending',
        'created-descending' => 'created_descending',
        'created-ascending' => 'created_ascending',
    ];

    public function apply($model, RepositoryInterface $repository)
    {
        $type = self::SORTBYCATEGORY[$this->request['sort']] ?? '';
        switch ($type) {
            case 'price_descending':
                $model = $model->orderByRaw('goods_price DESC');
                break;
            case 'price_ascending':
                $model = $model->orderByRaw('goods_price ASC');
                break;
            case 'created_ascending':
                $model = $model->orderByRaw('created_at ASC');
                break;
            case 'created_descending':
                $model = $model->orderByRaw('created_at DESC');
                break;
            default:
                $model = $model->orderByRaw('id DESC');
        }
        return $model;
    }
}

封装商品状态过滤逻辑

GoodsPublishedCriteria 用于筛选商品状态,返回已发布且审核通过的商品

namespace App\Criteria\Goods;

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

class GoodsPublishedCriteria implements CriteriaInterface
{
    public function apply($model, RepositoryInterface $repository)
    {
        return $model->where('goods_status', 1)->where('goods_verify', 1);
    }
}

业务逻辑封装

在业务层,通过 GoodsService 结合上述 Criteria 实现商品的排序与筛选功能

namespace App\Services\Study;

use App\Criteria\Goods\GoodsPublishedCriteria;
use App\Criteria\Goods\GoodsSortCriteria;
use App\Repositories\Goods\Interfaces\GoodsRepository;

class GoodsService
{
    public $goodsRepository;

    public function __construct(GoodsRepository $goodsRepository)
    {
        $this->goodsRepository = $goodsRepository;
    }


    public function goodsFilterAndSort($filterData)
    {
        $this->goodsRepository->pushCriteria(new GoodsSortCriteria($filterData));
        $this->goodsRepository->pushCriteria(new GoodsPublishedCriteria($filterData));
        return $this->goodsRepository;
    }


    public function goodsPaginator($filterData)
    {
        return $this->goodsFilterAndSort($filterData)->goodsPaginate($filterData);
    }
}

创建测试控制器

通过 GoodsController 调用 GoodsService,实现接口逻辑

namespace App\Http\Controllers\Learn;

use App\Http\Controllers\Controller;
use App\Repositories\Goods\Interfaces\GoodsRepository;
use App\Services\Study\GoodsService;
use Illuminate\Http\Request;

class GoodsController extends Controller
{
    public function getServerList(Request $request)
    {
        return app(GoodsService::class)->goodsPaginator($request);
    }
}

测试与结果

通过访问接口验证实现效果:

http://jwj.test/api/Learn/goods/getGoodsList?sort=price-descending

结果:

  • 按价格从高到低排序,返回符合条件的商品列表
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值