Laravel 多 where 并搜索


$size= (int)$request->size;
$page= (int)$request->page;
if(empty($page)) $page =1;
if(empty($size)) $size =10;
$ofsset = $size * ($page -1);
// var_dump($name);
$threatlistmodel = new ThreatList();

$total = $threatlistmodel->where(function($query) use ($data){
    $data['name'] && $query->where("name","like","%".$data['name']."%");
    isset($data['level']) && $query->where("level",$data['level']);
    isset($data['is_tb']) && $query->where("is_tb",$data['is_tb']);
    $data['end_at'] && $query->where("find_at","<=",$data['end_at'].' 23:59:59');
    $data['start_at'] && $query->where("find_at","=>",$data['start_at'].' 00:00:01');
    $query->where("is_state",1);
})->count();
//var_dump($total);
$list = $threatlistmodel->where(function($query) use ($data){
    $data['name'] && $query->where("name","like","%".$data['name']."%");
    isset($data['level']) && $query->where("level",$data['level']);
    isset($data['is_tb']) && $query->where("is_tb",$data['is_tb']);
    $data['end_at'] && $query->where("find_at","<=",$data['end_at'].' 23:59:59');
    $data['start_at'] && $query->where("find_at",">=",$data['start_at'].' 00:00:01');
    $query->where("is_state",1);
})->orderBy("id","desc")->offset($ofsset)->limit($size)->get()->each(function($item){
    $con_info = json_decode(unserialize($item->count_con),true);
    $item['ip_count'] = $con_info["total"];
    unset($item->count_con);

});
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
Vckin
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 29
public static function searchCon(array $validated)
{
    return function ($query) use ($validated) {
        extract($validated);

        // 关键字搜索
        if (filled($keyword)) {
            $query->where('name', 'like', '%' . $keyword . '%');
        }

        // 状态筛选
        if (filled($status)) {
            $query->where('status', $status);
        }

        if (filled($type)) {
            $query->where('type', $type);
        }

        if (filled($pid)) {
            $query->where('pid', $pid);
        }
    };
}

抛砖引玉啦

    public function scopePage($query, $page = 1, $pageSize = 10)
    {
        return \Request::input('excel') == self::TO_EXCEL ? $query : $query->offset(($page - 1) * $pageSize)->limit($pageSize);
    }

分页的优化

public static function list(array $validated)
{
    $where = self::searchCon($validated);

    $data['list'] = self::where($where)
        ->with('labelNext')
        ->orderBy('order', 'desc')
        ->page($validated['page'], $validated['page_size'])
        ->get();

    $data['count'] = self::where($where)->count();

    return $data;
}
5年前 评论
sunny123456 3年前
PhoenixIcy (作者) 3年前
sunny123456 3年前
PhoenixIcy (作者) 3年前
sunny123456 3年前
PhoenixIcy (作者) 3年前

看到这串代码 我的强迫症一下就出来了 取值要用arrget或者dataget 不然有可能报未找到的下标 闭包的变量我会命名类名 数字之间的计算我会尽量用bc函数 并不是为了计算金钱 调用where 我会调用Model:query() 不然ide会报模型找不到where这样的方法 这该死的强迫症

5年前 评论
游离不2

可以了解一下when方法,会优雅很多。

5年前 评论
Vckin

@deeka 谢谢您的意见,但是有些使用场景不一样!

5年前 评论
laisxn
if(empty($page)) $page =1;
if(empty($size)) $size =10;

个人实在不建议这样简写,还有 英文逗号后面留个空格,连接符 . 前后空格,一些php编码规则看一下, 整个代码都看的舒服一些

5年前 评论
游离不2

@Vckin 不客气。不过从你上面的代码看when完全可以接管

5年前 评论

就你贴出来的代码来说 when 完全能满足你的需求,让代码更简洁美观易读

5年前 评论

看到这串代码 我的强迫症一下就出来了 取值要用arrget或者dataget 不然有可能报未找到的下标 闭包的变量我会命名类名 数字之间的计算我会尽量用bc函数 并不是为了计算金钱 调用where 我会调用Model:query() 不然ide会报模型找不到where这样的方法 这该死的强迫症

5年前 评论
Vckin

@罪人 @helone 受教受教 我在好好研究一下!

5年前 评论
北冥
$size= (int)$request->input("size","1");

再说参数好像不必是 int 吧

5年前 评论
yourself

这样去写,等到以后需要增加或者删减业务的时候不觉得麻烦么?为什么不在一个地方统一处理然后根据参数控制呢?
如果有10种情况,那岂不是要写10遍?有一天业务改了要改10遍

5年前 评论

emmmmm
你这么写 你们老大不抽你么 代码可读性和维护性太差了啊 写个闭包 list count 的条件只写一次就行了

我宁愿 用if 判断 你这种 让别人过来怎么维护你的代码。

5年前 评论
public static function searchCon(array $validated)
{
    return function ($query) use ($validated) {
        extract($validated);

        // 关键字搜索
        if (filled($keyword)) {
            $query->where('name', 'like', '%' . $keyword . '%');
        }

        // 状态筛选
        if (filled($status)) {
            $query->where('status', $status);
        }

        if (filled($type)) {
            $query->where('type', $type);
        }

        if (filled($pid)) {
            $query->where('pid', $pid);
        }
    };
}

抛砖引玉啦

    public function scopePage($query, $page = 1, $pageSize = 10)
    {
        return \Request::input('excel') == self::TO_EXCEL ? $query : $query->offset(($page - 1) * $pageSize)->limit($pageSize);
    }

分页的优化

public static function list(array $validated)
{
    $where = self::searchCon($validated);

    $data['list'] = self::where($where)
        ->with('labelNext')
        ->orderBy('order', 'desc')
        ->page($validated['page'], $validated['page_size'])
        ->get();

    $data['count'] = self::where($where)->count();

    return $data;
}
5年前 评论
sunny123456 3年前
PhoenixIcy (作者) 3年前
sunny123456 3年前
PhoenixIcy (作者) 3年前
sunny123456 3年前
PhoenixIcy (作者) 3年前
hezhizheng

@PhoenixIcy 优雅 :+1:

5年前 评论

@PhoenixIcy extract($validated);学习了

5年前 评论
Mumujin

$request->page ?? 1

5年前 评论

@PhoenixIcy ,之前看了篇文章说是不要用%.xxx%以%或者_开头进行模糊查询会导致索引失效,我之前也是%.xxx.%,后来改成xxx.%,但是我也没怎么仔细去研究,说错了不要打我。

5年前 评论

@Mr_White_DT 可根据业务需求改变 我的业务需求没想到什么好方法 可以不 %xxx%

5年前 评论

@Mr_White_DT %xxx% 不走索引 %dadada 也不走索引

这样的代码看着很累 如果能保证前后的字段一致可以自己写一个扩展实现.

<?php

namespace App\Libraries\SearchBuilder;

class SearchBuilder
{
    protected $config;

    protected $builder;

    public function __construct($builder, $config)
    {
        $this->builder = $builder;
        $this->config = $config;
    }

    public function resolveSearchColumns($columns, $request)
    {
        if (empty($request)) {
            return $this->builder;
        }

        $cloumns = $this->parseSearchColumns($columns, $request);

        if (is_array($cloumns) && ! empty($cloumns)) {
            foreach ($cloumns as $column => $value) {
                $this->addQueries($column, $value);
            }
        }

        return $this->builder;
    }

    protected function addQueries($column, $value)
    {
        $boolean = array_get($this->config, 'boolean', 'and');

        if (is_array($value)) {
            return $this->addArrayQuery($column, $value, $boolean);
        }
        if (in_array(preg_replace('/(:\w+)/', '', $column), array_get($this->config, 'like_columns', []))) {
            return $this->addLikeQuery($column, $value, $boolean);
        }

        if (str_contains($column, ':')) {
            $column = explode(':', $column);
            list($column, $operator) = $column;

            return $this->builder->where($column, $operator, $value, $boolean);
        } else {
            return $this->builder->where($column, '=', $value, $boolean);
        }
    }

    protected function addArrayQuery($column, $value, $boolean)
    {
        $column = explode(':', $column);

        if (count($column) !== 2) $column[1] = 'in';

        list($column, $mean) = $column;
        $method = 'where' . ucfirst($mean);

        $this->builder->{$method}($column, $value, $boolean);
    }

    protected function addLikeQuery($column, $value, $boolean)
    {
        $column = explode(':', $column);
        if (count($column) !== 2)
            $column[1] = 'right';

        list($column, $like) = $column;

        switch ($like) {
            case 'right':
                $value = "$value%";
                break;
            case 'left':
                $value = "%$value";
                break;
            case 'full':
                $value = "%$value%";
                break;
            default:
                break;
        }

        return $this->builder->where($column, 'like', $value, $boolean);
    }

    protected function parseSearchColumns($columns, $request)
    {
        if (is_callable($columns))
            return $columns($request);

        $searches = [];
        foreach ($columns as $column) {
            $key = preg_replace('/\:[\s\S*]+/', '', $column);
            if (str_contains($key, '.')) {
                $key =  end(explode('.', $key));
            }
            if (array_key_exists($key, $request)) {
                $searches[$column] = array_get($request, $key);
            }
        }

        return $searches;
    }
}

$config = [
 'like_columns' => [
        //
   ],
   'boolean' => 'and'
]
QueryBuilder::macro('searchBuilder', function ($columns, array $request = []) use ($config) {
    $searchBuilder = new SearchBuilder($this, $config);

    return $searchBuilder->resolveSearchColumns($columns, $request);
});

$builder = Post::searchBuilder(['author_id:between'], ['author_id' => [1, 2]]);
$this->assertEquals($builder->toSql(), 'select * from "posts" where "author_id" between ? and ?');
5年前 评论

@DamonTo 我可能离这一步还有差距 :joy:

5年前 评论

挺好的 节约键盘if按键的寿命

1年前 评论

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