在 Laravel 中创建过滤器

第 1 步 --- 安装和设置 Laravel AuthProject

第 2 步 --- 创建模型和关系

  • Products 产品
  • Product Category 产品分类
  • Product Type 产品类型
  • Images 图像

Product Model - 产品型号 -

php 复制代码
use App\Traits\UuidSet;  
use Illuminate\Database\Eloquent\Factories\HasFactory;  
use App\Http\Filter\QueryFilter;  
use Illuminate\Database\Eloquent\Builder;  
  
class Products extends Model  
{  
use UuidSet, HasFactory;  
protected $guarded = ['id' , 'created_at' , 'updated_at'];  
protected $fillable = [  
'status' ,  
'uuid_key',  
'type_id',  
'category_id',  
'title',  
'code' ,  
'description'  
];  
}  
//IT WILL BE RESPONSABLE TO QUERY THOSE FILTERS  
public function scopeFilter(Builder $builder, QueryFilter $filters) {  
return $filters->apply($builder);  
}  
  
// CATEGORY BELONGS TO PRODUCT  
public function Category(){  
return $this->belongsTo(ProductCategory::class , 'category_id');  
}  
  
// TYPE BELONGS TO PRODUCTS  
public function Type(){  
return $this->belongsTo(ProductType::class , 'type_id');  
}  
  
// A PRODUCT HAS IMAGES  
public function Images(){  
return $this->hasMany(ProductImages::class , 'propuct_id');  
}  
}

Product Category Model - 产品分类 型号 -

php 复制代码
use App\Traits\UuidSet;  
use Illuminate\Database\Eloquent\Factories\HasFactory;  
  
class ProductCategory extends Model  
{  
use UuidSet, HasFactory;  
  
  
protected $guarded = ['id' , 'created_at' , 'updated_at'];  
protected $fillable = [  
'title'  
];  
  
// RELATION SHIP  
public function props()  
{  
return $this->hasMany(Product::class , 'bath_id' );  
}  
}

Product Type Model - 产品类型 型号 -

php 复制代码
use App\Traits\UuidSet;  
use Illuminate\Database\Eloquent\Factories\HasFactory;  
  
class ProductType extends Model  
{  
use UuidSet, HasFactory;  
  
  
protected $guarded = ['id' , 'created_at' , 'updated_at'];  
protected $fillable = [  
'title'  
];  
  
// RELATION SHIP  
public function props()  
{  
return $this->hasMany(Product::class , 'bath_id' );  
}  
}

Image Model - 图像模型 -

php 复制代码
use App\Traits\UuidSet;  
use Illuminate\Database\Eloquent\Factories\HasFactory;  
  
class ProductImages extends Model  
{  
use UuidSet, HasFactory;  
  
  
protected $guarded = ['id' , 'created_at' , 'updated_at'];  
protected $fillable = [  
'uuid_key',  
'gallery_id',  
'image' ,  
'title' ,  
];  
  
public function Props() {  
return $this->belongsTo(Product::class ,'product_id' );  
}  
}

Create the Status Enum 创建 Status 枚举

php 复制代码
<?php  
  
namespace App\Classes\Enums\Property;  
  
use App\Traits\EnumToArray;  
  
enum PropStatusEnum:string  
{  
use EnumToArray;  
case ACTIVE = 'active';  
case INACTIVE = 'inactive';  
}

Step 3--- Create Filters 第 3 步 --- 创建过滤器

php 复制代码
class ProductFilter extends QueryFilter  
{  
// WHERE HAS THE CATEGORY ID  
public function category($id) {  
return $this->builder->where('category_id', $id);  
}  
// WHERE HAS THE TYPE ID  
public function type($id) {  
return $this->builder->where('type_id', $id);  
}  
// WHERE TITLE IS LIKE ( THE NAME OF THE PRODUCT)  
public function title($name)  
{  
$this->query->where('name', 'like', $name.'%');  
}  
  
// SEARCH THE PRODUCT CREATED AT BEFORE THE DATE  
public function beforeDate($date) {  
return $this->builder->whereDate('created_at' , '<' , $date );  
}  
  
// SEARCH THE PRODUCT CREATED AT AFTER THE DATE  
public function afterDate($date) {  
return $this->builder->whereDate('created_at' , '>' , $date );  
}  
  
// search the status enum  
public function status($value) {  
return $this->builder->where('status', $value);  
}  
  
// WHERE HAS MORE THAN IMAGES COUNTING, FOR EXAMPLE WE WANT TO GET PRODUCTS THAT HAS MORE THAN 3 IMAGES  
public function imageCount($imageNumber) {  
return $this->builder->withCount('Images')->having('images_count', '>', $imageNumber);  
}  
// WHERE HAS IMAGES ID  
public function images($id) {  
return $this->builder->WhereHas('Images' , function($query) use ($id) {  
return $query->where('id' , $id );  
});  
}

在这里,我们创建了一个可以在所有这些过滤器中使用的类。

php 复制代码
use Illuminate\Database\Eloquent\Builder;  
use Illuminate\Http\Request;  
  
class QueryFilter  
{  
  
protected $builder;  
protected $request;  
  
public function __construct(Request $request)  
{  
$this->request = $request;  
}  
  
protected function filter($arr) {  
foreach($arr as $key => $value) {  
if (method_exists($this, $key)) {  
$this->$key($value);  
}  
}  
  
return $this->builder;  
}  
  
public function apply(Builder $builder) {  
$this->builder = $builder;  
  
foreach($this->request->all() as $key => $value) {  
if (method_exists($this, $key)) {  
$this->$key($value);  
}  
}  
  
return $builder;  
}  
}

第 4 步 --- 创建资源

产品资源

php 复制代码
<?php  
  
namespace App\Http\Resources;  
  
use Illuminate\Http\Request;  
use Illuminate\Http\Resources\Json\JsonResource;  
  
class ProductResource extends JsonResource  
{  
/**  
* Transform the resource into an array.  
*  
* @return array<string, mixed>  
*/  
public function toArray(Request $request): array  
{  
  
return [  
'id' => $this->uuid_key,  
'status' => $this->status,  
'type' => new ProductTypeResource($this->whenLoaded('Type')),  
'category' => new ProductCategoryResource($this->whenLoaded('Category')),  
'images' => new ProductImageResource($this->whenLoaded('Images')),  
'title'=> $this->title,  
'code'=> $this->code,  
'description' $this->description  
];  
}  
}

产品分类资源 -

php 复制代码
<?php  
  
namespace App\Http\Resources;  
  
use Illuminate\Http\Request;  
use Illuminate\Http\Resources\Json\JsonResource;  
  
class ProductCategoryResource extends JsonResource  
{  
/**  
* Transform the resource into an array.  
*  
* @return array<string, mixed>  
*/  
public function toArray(Request $request): array  
{  
  
return [  
'id' => $this->uuid_key,  
'title'=> $this->title  
];  
}  
}

产品类型 资源 ---

php 复制代码
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ProductTypeResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {

         return [
             'id' => $this->uuid_key,
             'title'=> $this->title
            ];
     }
}

产品图片资源 -

php 复制代码
<?php  
  
namespace App\Http\Resources;  
  
use Illuminate\Http\Request;  
use Illuminate\Http\Resources\Json\JsonResource;  
  
class ProductImageResource extends JsonResource  
{  
/**  
* Transform the resource into an array.  
*  
* @return array<string, mixed>  
*/  
public function toArray(Request $request): array  
{  
  
return [  
'id' => $this->uuid_key,  
'title'=> $this->title,  
'image' => $this->image  
];  
}  
}

现在我们也可以为 Product Pagination 创建一个资源 -

php 复制代码
<?php  
  
namespace App\Http\Resources;  
  
use Illuminate\Http\Request;  
use Illuminate\Http\Resources\Json\JsonResource;  
  
class ProductPaginateResource extends JsonResource  
{  
/**  
* Transform the resource into an array.  
*  
* @return array<string, mixed>  
*/  
public function toArray(Request $request): array  
{  
return [  
"data" => ProductResource::collection($this->items()),  
'pagination' => [  
'total' => $this->total(),  
'per_page' => $this->perPage(),  
'current_page' => $this->currentPage(),  
'last_page' => $this->lastPage(),  
'from' => $this->firstItem(),  
'to' => $this->lastItem()  
]  
];  
}  
}

第 5 步 --- 创建过滤器

现在我们已经设置了这些过滤器。

它能够在 Product Controller 中创建方法

php 复制代码
use App\Traits\ApiResponse;  
class ProductController extends Controller  
{  
use ApiResponse;  
  
public function index(ProductFilter $filter,Request $request )  
{  
$props = Product::filter($filter)->with('Category', 'Type', 'Images')->paginate(40 ['*'], 'page', $request['page']);  
return $this->successResponse(new ProductPaginateResource($props));  
}  
}

Api Resonse Trait

php 复制代码
trait ApiResponse  
{  
public function successResponse($data = null, $code = Response::HTTP_OK)  
{  
return response()->json($data, $code);  
}  
}

Route::get('/products', [ProductController::class, 'index']);

第 6 步 --- 将 Include 添加到这些过滤器

我们可以创建在请求中包含这些模型的可能性 .以允许用户使用 includes or not 进行搜索。 在 QueryFilter 类中,我们可以进行更改并添加 include 方法-

php 复制代码
use Illuminate\Database\Eloquent\Builder;  
use Illuminate\Http\Request;  
  
class QueryFilter  
{  
  
protected $builder;  
protected $request;  
  
public function __construct(Request $request)  
{  
$this->request = $request;  
}  
  
protected function filter($arr) {  
foreach($arr as $key => $value) {  
if (method_exists($this, $key)) {  
$this->$key($value);  
}  
}  
  
return $this->builder;  
}  
// NOW ARE APPLING THE POSSIBILITY TO SEARCH AND BRING THE INCLUDE THAT WE WANT  
public function include($value) {  
// WE WILL MAKE THE REQUEST WITH THE INCLUDE SEPARATED BY COMA  
$sortAttributes = explode(',', $value);  
$list = collect([]);  
foreach($sortAttributes as $sortAttribute) {  
// IF DOES HAVE THE RELATION  
if (in_array($sortAttribute, $this->includeOption['relations'])) {  
// ADD THE INCLUDE  
$list->push($sortAttribute);  
}  
}  
$this->builder->with($list->all());  
}  
  
public function apply(Builder $builder) {  
$this->builder = $builder;  
  
foreach($this->request->all() as $key => $value) {  
if (method_exists($this, $key)) {  
$this->$key($value);  
}  
}  
  
return $builder;  
}  
}

现在在控制器上,我们可以删除搜索选项 --- 'Category', 'Type', 'Images' ( ->with('Category', 'Type', 'Images' ) ) 。

php 复制代码
use App\Traits\ApiResponse;  
class ProductController extends Controller  
{  
use ApiResponse;  
  
public function index(ProductFilter $filter,Request $request )  
{  
$props = Product::filter($filter)->paginate(40 ['*'], 'page', $request['page']);  
return $this->successResponse(new ProductPaginateResource($props));  
}  
}

现在我们可以搜索 -

{{APP_URL}}/api/products?category=1&type=1&imageCount=2&title=Dell Inspiron&include=Category,Type,Images

{{APP_URL}}/api/products?category=1&type=1&imageCount=2&title=Dell Inspiron&include=类别,类型,图像

相关推荐
他日若遂凌云志1 小时前
深入剖析 Fantasy 框架的消息设计与序列化机制:协同架构下的高效转换与场景适配
后端
快手技术2 小时前
快手Klear-Reasoner登顶8B模型榜首,GPPO算法双效强化稳定性与探索能力!
后端
二闹2 小时前
三个注解,到底该用哪一个?别再傻傻分不清了!
后端
用户49055816081252 小时前
当控制面更新一条 ACL 规则时,如何更新给数据面
后端
林太白2 小时前
Nuxt.js搭建一个官网如何简单
前端·javascript·后端
码事漫谈2 小时前
VS Code 终端完全指南
后端
该用户已不存在3 小时前
OpenJDK、Temurin、GraalVM...到底该装哪个?
java·后端
怀刃3 小时前
内存监控对应解决方案
后端
码事漫谈3 小时前
VS Code Copilot 内联聊天与提示词技巧指南
后端
Moonbit3 小时前
MoonBit Perals Vol.06: MoonBit 与 LLVM 共舞 (上):编译前端实现
后端·算法·编程语言