wpcmf: wpcmf cms ,内容管理系统,类似 wordpress 系统

在显示到视图时,我们经常需要过滤 eloquent 模型。如果我们有少量过滤器,这可能很好,但如果您需要添加多个过滤器,则控制器可能会变得混乱且难以阅读。

在处理可以结合使用的多个可选过滤器时尤其如此。

但是,有一些方法可以创建这些过滤器,甚至可以使它们可重复使用。在本文结束时,您将能够更好地处理项目中的复杂过滤选项。

定义问题
比方说,我有一个控制器方法,它返回我们商店中的所有产品,这可以用于 API,将其传递给刀片模板,或者无论如何,控制器可能看起来像这样:

<?phpnamespace App\Http\Controllers;use App\Models\Product;
use Illuminate\Http\Request;class ProductsController extends Controller
{public function index(){return Product::all();}
}

然而,这根本不现实。通常情况下,我们需要添加一些过滤,例如,假设我们只想获取给定类别中的产品,我们可以通过在查询字符串中发送类别 slug 然后使用 slug 进行过滤来做到这一点。所以我们的新控制器看起来像这样:

class ProductsController extends Controller
{public function index(){if ($request->filled('category')) {$categorySlug = $request->category;return Product::whereHas('category', function ($query) use ($categorySlug) {$query->where('slug', $categorySlug);});}return Product::all();}
}

如果我们只需要一个过滤器,这很好。但是,看看如果我们只引入另外两个过滤选项会发生什么:

class ProductsController extends Controller
{public function index(Request $request){$query = Product::query();if ($request->filled('price')) {list($min, $max) = explode(",", $request->price);$query->where('price', '>=', $min)->where('price', '<=', $max);}if ($request->filled('category')) {$categorySlug = $request->category;$query->whereHas('category', function ($query) use ($categorySlug) {$query->where('slug', $categorySlug);});}if ($request->filled('brand')) {$brandSlug = $request->brand;$query->whereHas('brand', function ($query) use ($brandSlug) {$query->where('slug', $brandSlug);});}return $query->get();}
}

我们又推出了两种过滤器,一种用于品牌 slug,一种用于价格范围。在我看来,这太忙了,很难跟踪这里发生的事情,如果我们需要添加更多过滤选项,情况会很快变得更糟。

例如,当您在 eBay 上搜索产品时,您通常会获得十多个可选过滤器。我们需要寻找另一种方法来做到这一点。

想像
如果不是在我们的控制器中包含所有这些过滤器,我们可以做这样的事情怎么办:

class ProductsController extends Controller
{public function index(ProductFilters $filters){return Product::filter($filters)->get();}
}

在这里,我们收到一个ProductFilters可能包含所有过滤器的类,然后我们可以将它们应用于名为 的查询范围filter。这使得我们的控制器非常纤薄,很容易猜到它发生了什么。我们正在筛选产品,如果我们需要了解更多细节,我们可以查看ProductFilters类。

实施新方法
首先,让我们将作用域添加到我们的模型中:

class Product extends Model
{use HasFactory;public function category() {return $this->belongsTo(Category::class);}public function brand() {return $this->belongsTo(Brand::class);}// This is the scope we addedpublic function scopeFilter($query, $filters){return $filters->apply($query);}
}

在这个范围内,我们接收一个QueryBuilder实例和ProductFilters我们从控制器传递下来的实例。apply然后我们在这个$filter实例上调用方法。

到目前为止,我们知道这个ProductFilters类看起来像这样:

namespace App\Filters;class ProductFilters
{public function apply($query){if (request()->filled('price')) {list($min, $max) = explode(",", $request->price);$query->where('price', '>=', $min)->where('price', '<=', $max);}if (request()->filled('category')) {$categorySlug = $request->category;$query->whereHas('category', function ($query) use ($categorySlug) {$query->where('slug', $categorySlug);});}if (request()->filled('brand')) {$brandSlug = $request->brand;$query->whereHas('brand', function ($query) use ($brandSlug) {$query->where('slug', $brandSlug);});}return $query->get();}
}

这段代码可以工作,但并不比控制器中的过滤器好多少。而不是这样做,我想有单独的过滤器类,只包含它们的过滤逻辑。

让我们为类别过滤器执行此操作:

namespace App\Filters;class CategoryFilter
{function __invoke($query, $categorySlug){return $query->whereHas('category', function ($query) use ($categorySlug) {$query->where('slug', $categorySlug);});}
}

这里我们有一个自包含的类,我们甚至可以在其他模型中使用,假设我们有一个附加到商店的博客,我们可以对博客文章使用相同的过滤器。

顺便说一句,如果您不熟悉__invoke魔术方法,可以在这里找到更多信息:https ://www.php.net/manual/en/language.oop5.magic.php#object.invoke 。简而言之,它只是让我们像调用函数一样调用类的实例。

在为过滤器创建类之后,我们需要找到一种从ProductFilters类中调用它们的方法。有很多方法可以做到这一点,对于本文,我将采用以下方法:


namespace App\Filters;class ProductFilters
{protected $filters = ['price' => PriceFilter::class,'category' => CategoryFilter::class,'brand' => BrandFilter::class,];public function apply($query){foreach ($this->receivedFilters() as $name => $value) {$filterInstance = new $this->filters[$name];$query = $filterInstance($query, $value);}return $query;}public function receivedFilters(){return request()->only(array_keys($this->filters));}
}

这是完成的课程,让我分解并解释每个部分。

这是如何运作的?
首先,让我们从$filters属性开始

   protected $filters = ['category' => CategoryFilter::class,'price' => PriceFilter::class,'brand' => BrandFilter::class,];

在这里,我为产品定义了每个可选过滤器,数组的键是用于检查过滤器是否在请求中的键,数组的值是定义过滤器行为的类。这使我们可以轻松添加更多过滤器,当我们需要添加新过滤器时,我们只需创建新过滤器类并将该类添加到此数组中。

第二部分是这个方法:

    public function receivedFilters(){return request()->only(array_keys($this->filters));}

此方法用于查找请求中正在使用哪些过滤器,因此我们仅应用所需的过滤器。我们还调用该only方法并将$filters数组的键传递给它,以防止我们尝试调用不存在的过滤器类。假设有人发送过滤器“大小”,但我们目前不支持它,这将使请求密钥被忽略。

现在来说说这个类的肉,apply方法:

    public function apply($query){foreach ($this->receivedFilters() as $name => $value) {$filterInstance = new $this->filters[$name];$query = $filterInstance($query, $value);}return $query;}

这个方法只是一个 for each 循环通过接收到的过滤器创建一个过滤器类,然后使用$query请求中接收到的值和值调用过滤器。

例如,假设我们收到一个如下所示的请求:

['category' => 'mobile-phones', 'price' => '100,150']

此类将首先创建一个实例,CategoryFilter然后将$query和“手机”传递给它。本质上,它会这样做:

$filterInstance = new CategoryFilter();
$query = $filterInstance($query, 'mobile-phones');

下一个同样的事情PhoneFilter:

$filterInstance = new PhoneFilter();
$query = $filterInstance($query, '100,150');

然后在应用所有查询之后,它将返回$query带有每个请求过滤器的对象。这就是我们在控制器中应用范围时收到的内容:

class ProductsController extends Controller
{public function index(ProductFilters $filters){return Product::filter($filters)->get();}
}

结论
我们创建了一种可扩展的方式来为我们的产品制作多个过滤器,并且这里有一些我们可以改进的地方,例如为过滤器值添加验证或创建一个基类,ProductFilters以便我们可以将相同类型的过滤器添加到其他模型中。

使用多个可选过滤器过滤 Eloquent 模型相关推荐

  1. 过滤器过滤特定的url_如何从过滤器中排除URL

    过滤器过滤特定的url 默认情况下,过滤器不支持排除特定的URL模式,每当您为过滤器定义URL模式时,任何与该模式匹配的请求都将由过滤器无例外处理. 从过滤器中排除URL的最简单方法是将过滤器映射到非 ...

  2. php 查看 实例 的方法,php – 从Laravel 5.1中的通用数据库查询中获取Eloquent模型的实例...

    我有不同关系的模型.假设我的Entry模型属于供应商,所以通常我的模型文件中有一个supplier()方法. 到目前为止一切都那么好,当我有一些像Entry :: find(1) – >供应商这 ...

  3. php注册 绑定的容器,php – 将Eloquent模型绑定到服务容器

    有没有人使用IoC容器绑定到Eloquent模型? 例如,我有一个我的帐户和类别雄辩模型的存储库. Account模型与Categories具有hasMany关系.类别存储库将Account存储库注入 ...

  4. PHP利用分组查询groupby,Laravel 实现Eloquent模型分组查询并返回每个分组的数量 groupBy...

    Laravel 5.5 Linux mint 18 PHPStorm 最近刚玩Laravel,手册源码还没来得及看完就跃跃欲试做了个小项目,其中有个需求是分组查询数据库中的一个字段并返回每个分组中的数 ...

  5. 袋式过滤器 - - 过滤与分离的基本原理,结构和布局的控制袋式过滤器

    袋式过滤器 - - 过滤与分离的基本原理,结构和布局的控制袋式过滤器 一,引言在现代社会中,几乎每个家庭都离不开"袋式过滤器."例如,大家熟悉的家用清洁剂,汽车和电脑微清洗车.在冶 ...

  6. Java添加过滤器过滤xss入侵

    Filter过滤器过滤XSS攻击 一.springmvc框架 1.添加自定义过滤器文件XssFilter.java和XssHttpServletRequestWrapper.java XssFilte ...

  7. Laravel 5.1 文档攻略 —— Eloquent:模型关系

    简介 其实大家都知道,数据表之间都是可以关联的,前面讲过了,Eloquent ORM是数据模型操作代替表操作,那么表的关联查询,在Eloquent这里也就是模型间的关联查询,这就是本章的主要内容: E ...

  8. Spring Boot使用过滤器过滤非法URL

    一.场景 使用Spring Boot框架,通过过滤器过滤不存在的URL,将这些非法URL转发或重定向到自定义错误页面. 二.实现 API: WebApplicationContext:用于获取全局信息 ...

  9. STM32F103的CAN通讯接收过滤器过滤分析

    前言 STM32 的标识符过滤是一个比较复杂的东东,它的存在减少了 CPU 处理 CAN 通信的开销.STM32 的过滤器组最多有 28 个(互联型),但是 STM32F103ZET6 只有 14 个 ...

  10. java过滤器过滤Emoji 表情

    1.web.xml添加过滤器 <filter><filter-name>EmojiFilter</filter-name><filter-class>c ...

最新文章

  1. mysql插入数据die_吴裕雄 10-MySQL插入数据
  2. 任务管理器taskmgr查看几核
  3. 【前端】你打console.log要花几秒?
  4. 零基础学Python-爬虫-4、下载网络图片
  5. 文献记录(part20)--Discriminative metric learning for multi-view graph partitioning
  6. python 网站发送验证码_Python爬虫模拟登录带验证码网站
  7. java jvm内存地址_JVM--Java内存区域
  8. Contoso 大学 - 3 - 排序、过滤及分页
  9. Confluence 6 教程:在 Confluence 中导航
  10. FISCO BCOS Solidity 智能合约 返回数组
  11. sop流程图模板_SOP模板-标准操作流程编写程序
  12. 基于51单片机的秒表设计
  13. 席慕容《写给幸福》读记
  14. 提取文件名+复制+改名+批量创建文件程序(Excel VBA版)
  15. 上海青浦区大众驾校(科目二·自动挡)真实考场操作全程
  16. 哈希表(HashMap)的学习与实现
  17. 阿里云备案流程和操作步骤详解(图文教程)
  18. CodeForces - 1255B Fridge Lockers 思维+建图)
  19. ROS中的TF坐标变换工具及实现、Rviz查看(十四)C++、python
  20. 微信小程序onTabItemTap和onShow的执行顺序

热门文章

  1. clang: error:clang frontend command failed due to signal
  2. 在外部JS中使用validity进行表单验证出现未定义问题
  3. 小程序与bmob后端云
  4. mmdetection源码笔记(一):train.py解读
  5. Diabetic Retinopathy Detection
  6. 数论概论 第三章 勾股数组与单位圆
  7. c#运用——简体字转繁体字
  8. 小白windows内网离线部署宝塔面板
  9. arcgis 触屏实现键盘模拟
  10. 先定一个能达到的小决心,比方读个一本书 ——《小决心》读后感 @阿狸不歌