第 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=类别,类型,图像