zoukankan      html  css  js  c++  java
  • laravel query builder/ Eloquent builder 添加自定义方法

    上次干这事已经是一年前了,之前的做法特别的繁琐、冗余,具体就是创建一个自定义 Builder 类,继承自 QueryBuilder,然后覆盖 Connection 里面获取 Builder 的方法,返回自定义的 Builder,还有其他一系列很长的步骤。

    下面是之前的做法:

    (算了,还是不说了,太蠢),总之,多看看源码有好处

    就说最优雅的解决方法吧:

    laravel 中提供了 Macroable 的 trait,之前一直没有想过可以用上这个东西。

    最近才想到可以这么做,源码看这里:https://github.com/laravel/framework/blob/5.6/src/Illuminate/Support/Traits/Macroable.php

    目前用的是 5.1 版本,应该 5.1 版本以后的都有这个特性。

    当然,你也可以在 Model 基类里面添加自定义方法,但是这样添加的方法 DB 类是用不了的。

    但是使用 macro 定义到 Builder 的方法可以同时在 DB 类和 Eloquent Model 中使用(具体不赘述,自己看源码,就是利用 __call、__callStatic 这些魔术方法)。

    使用方法:调用 Macroable 的 macro 方法,绑定一个自定义方法到 Builder 类中,如:

    IlluminateDatabaseQueryBuilderBuilder::macro('active', function () {
        return $this->where('status', 1);
    });
    

      

    调用方法是(使用 DB 类):

    DB::table(xxx)->active()->get();
    

      

    或者(使用 Eloquent Model):

    AppModelUser::active()->first();
    

      

    至于我们应该把上面那几行放哪里?

    个人觉得一个比较好的地方是 Providers 中,在 app/Providers 下面新建一个 Provider,把 macro 调用放到 Provider 的 register 方法中。如:

    <?php
    
    namespace AppProviders;
    
    use IlluminateDatabaseQueryBuilder;
    use IlluminateSupportServiceProvider;
    
    /** @mixin IlluminateDatabaseEloquentBuilder */
    class DatabaseServiceProvider extends ServiceProvider
    {
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            Builder::macro('active', function () {
                return $this->where('status', 1);
            });
        }
    }
    

      

    当然,加了 Providers 之后还要在 config/app.php 中配置这个 Provider。

    就这样。

    还有个问题是,这样添加的方法 ide 无法识别,我们这时候就可以使用 @method 了,如:

    @method $this active()

    可以使用命令把这些 @method 写入到 Builder 头部(我看 laravel-ide-helper 这么干我才这么干的):

    <?php
    
    namespace AppConsoleUtils;
    
    use AppConsoleCommandsBaseCommand;
    
    /** @see IlluminateDatabaseQueryBuilder */
    class Ide extends BaseCommand
    {
        public $signature = 'ide';
    
        public $description = '生成 PHP doc到 Query Builder';
    
        public function handle()
        {
            $file = base_path() . '/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php';
            if (!is_file($file)) {
                $this->info("文件不存在({$file}), 先 composer install");
                return;
            }
    
            $content = file_get_contents($file);
            $pos = strpos($content, 'class Builder');
            list($before, $after) = $this->splitFileByPos($content, $pos);
            $before = $this->removeOldDoc($before);
            $new_file_content = $before . $this->docProvider() . $after;
    
            $f = fopen($file, 'w+');
            fwrite($f, $new_file_content);
            fclose($f);
        }
    
        // 移除旧的 php doc
        private function removeOldDoc($before)
        {
            if (preg_match('/(/*.*?*/)/ism', $before, $match)) {
                $before = preg_replace('/(/*.*?*/)/ism', '', $before);
            }
    
            return $before;
        }
    
        // 生成新的 php doc
        private function docProvider()
        {
            return <<<DOC
    /**
     * @method $this like($field, $keyword = '')
     * @method $this recent()
     * @method $this active()
     * @method $this notDeleted()
     */
    
    DOC;
        }
    
        // 通过一个点把文件分割成两部分
        private function splitFileByPos($content_string, $pos)
        {
            $before = substr($content_string, 0, $pos);
            $after = substr($content_string, $pos);
    
            return [$before, $after];
        }
    }
    

      

    这样的好处是,也没什么好处,就是你 push 上去的时候,一般 vendor 都 ignore 了,在其他电脑 clone 下来,就没有那些 @method 了,也就不会有语法提示了。

    手速惊人的还是忽略吧。

      

  • 相关阅读:
    rqnoj71 拔河比赛
    NOI2002 洛谷 P1196 银河英雄传说
    sdibt 1244 烦人的幻灯片
    POJ 1273 Drainage Ditches -dinic
    NOIP2005提高组 过河
    OpenJudge 7627 鸡蛋的硬度
    Openjudge 8782 乘积最大
    OpenJudge 7624 山区建小学
    UVa 1328 Period
    UVa 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/eleven24/p/8870854.html
Copyright © 2011-2022 走看看