head-img Force's Blog

CatchAdmin LLike、RLike 导致查询为空问题修复

PHP

在模型调整$searchable的subject_code => LLike 最终查询不到结果
55970705926F1753EAA645ECE10A11DA.png

在日志看到查询的sql把llike拼进值里面了
8FF0085256674713751790E50672D6AF.png

在官方群里面资讯了框架创作者们,但是迟迟没有回复,于是在/vendor/catchadmin/core/src/Support/Macros/Builder.phpquickSearch()方法发现了问题所在。
$this->where()时候$op作为第二参数不应该为 llike 和 rlike。
398FA1099B92BB75FF32FE5DEE60B03E.png

尝试临时调整quickSearch()代码,在llike 和 rlike拼接完%后,强制将$op='like',这应该是官方的bug
ED9FE1AF0E7046F1468FB53E2722E8C9.png


调整后发现再次搜索可以达到预期,为了不破快官方包代码。等待官方修复前先对quickSearch()进行劫持,在 app/Providers 目录下创建一个新的服务提供者,例如 CatchAdminMacroServiceProvider.php

php artisan make:provider CatchAdminMacroServiceProvider

在新创建的 Service Provider 中注册你的 Macro, 打开app/Providers/CatchAdminMacroServiceProvider.php 文件,并在 boot 方法中添加如下代码来覆盖或扩展 quickSearch 方法。

<?php

namespace App\Providers;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;

class CatchAdminMacroServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        Builder::macro('quickSearch', function (array $params = []) {

            $params = array_merge(request()->all(), $params);

            if (! property_exists($this->model, 'searchable')) {
                return $this;
            }

            // filter null & empty string
            $params = array_filter($params, function ($value) {
                return (is_string($value) && strlen($value)) || is_numeric($value);
            });

            $wheres = [];

            if (! empty($this->model->searchable)) {
                foreach ($this->model->searchable as $field => $op) {
                    // 临时变量
                    $_field = $field;
                    // contains alias
                    if (str_contains($field, '.')) {
                        [, $_field] = explode('.', $field);
                    }

                    if (isset($params[$_field]) && $searchValue = $params[$_field]) {
                        $operate = Str::of($op)->lower();
                        $value = $searchValue;
                        if ($operate->exactly('op')) {
                            $value = implode(',', $searchValue);
                        }

                        if ($operate->exactly('like')) {
                            $value = "%{$searchValue}%";
                        }

                        if ($operate->exactly('rlike')) {
                            $value = $searchValue. '%';
                            $op = 'like'; //bug修复点
                        }

                        if ($operate->exactly('llike')) {
                            $value = '%' .$searchValue;
                            $op = 'like'; //bug修复点
                        }

                        if (Str::of($_field)->endsWith('_at') || Str::of($_field)->endsWith('_time')) {
                            $value = is_string($searchValue) ? strtotime($searchValue) : $searchValue;
                        }

                        $wheres[] = [$field, strtolower($op), $value];
                    }
                }
            }

            // 组装 where 条件
            foreach ($wheres as $w) {
                [$field, $op, $value] = $w;
                if ($op == 'in') {
                    // in 操作的值必须是数组,所以 value 必须更改成 array
                    $this->whereIn($field, is_array($value) ? $value : explode(',', $value));
                } else {
                    $this->where($field, $op, $value);
                }
            }

            return $this;
        });
    }
}

注册 Service Provider:确保在 config/app.php 的 providers 数组中添加你的服务提供者

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

结束

点我评论
打赏本文
二维码


128

文章

14

标签

 访客统计  Update-******