资讯专栏INFORMATION COLUMN

使用 Laravel 的服务容器来优化读写数据库中的 options

qingshanli1988 / 1987人阅读

摘要:但是这样的弊端就是每一次的操作都要去查询数据库,这对于性能还是有挺大影响的,尤其是在一次响应中要使用很多的情况下。没错,我们正是要把放到的服务容器里去。

原文地址:https://prinzeugen.net/optimi...

这篇文章应该算是心得体会一类的吧,因为并没有什么卵用(笑

就像前两篇文章说的一样,在我把项目框架改为 Laravel 后,自然要最大限度地利用 Laravel 的特性来提升我们应用的性能(虽然使用 Laravel 本身就是在降低性能了),并且让我们的代码看起来更优雅 装逼

其中我们可以最方便地利用的一个特性就是 Laravel 的服务容器了。在这里我不多赘述 Service Container 是个啥,想了解的可以自行搜索。不想了解的就只要大致知道它是个可以 绑定/取出 实例的东西就好了(当然服务容器可不止这么点功能)。

相信很多 Web 应用都会在数据库建立一个 options 表来储存一些用户的配置信息,而为了方便,我们通常会封装一个 Option 类来方便地进行数据的 getset 操作。而通常的做法是把这些操作做成类内静态方法来调用。

但是这样的弊端就是每一次的操作都要去查询数据库,这对于性能还是有挺大影响的,尤其是在一次响应中要使用很多 options 的情况下。

那么在 Laravel 下我们可以怎么优化呢?

蛤?你说 Eloquent?你 TM 长点脑子啊 用了 ORM 那 tm 还叫优化?你们呀,不要听的风是得雨,看到 Laravel 就想到 Eloquent!

好吧好吧,再强行 +1s 是要出事的,我们回到正题。没错,我们正是要把 options 放到 Laravel 的服务容器里去。

这样的话我们只需要在应用启动的时候实例化一个 OptionRepository 类,在构造函数里读入所有的 options 并放到类内属性上,get 方法直接从该属性里取值,而调用 set 操作的时候则对该属性进行修改,同时 push 修改过的 key 到一个 $items_modified 数组里去,在对象析构的时候再真正执行数据库操作,写入所有修改过的 options

下面我们来定义 OptionRepository 类:

get();

        foreach ($options as $option) {
            $this->items[$option->option_name] = $option->option_value;
        }

    }

    /**
     * Determine if the given option value exists.
     *
     * @param  string  $key
     * @return bool
     */
    public function has($key)
    {
        return Arr::has($this->items, $key);
    }

    /**
     * Get the specified option value.
     *
     * @param  string  $key
     * @param  mixed   $default
     * @return mixed
     */
    public function get($key, $default = null)
    {
        return Arr::get($this->items, $key, $default);
    }

    /**
     * Set a given option value.
     *
     * @param  array|string  $key
     * @param  mixed   $value
     * @return void
     */
    public function set($key, $value = null)
    {
        if (is_array($key)) {
            foreach ($key as $innerKey => $innerValue) {
                Arr::set($this->items, $innerKey, $innerValue);
                $this->items_modified[] = $innerKey;
            }
        } else {
            Arr::set($this->items, $key, $value);
            $this->items_modified[] = $key;
        }
    }

    protected function save()
    {
        $this->items_modified = array_unique($this->items_modified);

        foreach ($this->items_modified as $key) {
            if (!DB::table("options")->where("option_name", $key)->first()) {
                DB::table("options")
                    ->insert(["option_name" => $key, "option_value" => $this[$key]]);
            } else {
                DB::table("options")
                        ->where("option_name", $key)
                        ->update(["option_value" => $this[$key]]);
            }
        }
    }

    /**
     * Prepend a value onto an array option value.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function prepend($key, $value)
    {
        $array = $this->get($key);

        array_unshift($array, $value);

        $this->set($key, $array);
    }

    /**
     * Push a value onto an array option value.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function push($key, $value)
    {
        $array = $this->get($key);

        $array[] = $value;

        $this->set($key, $array);
    }

    /**
     * Get all of the option items for the application.
     *
     * @return array
     */
    public function all()
    {
        return $this->items;
    }

    /**
     * Determine if the given option option exists.
     *
     * @param  string  $key
     * @return bool
     */
    public function offsetExists($key)
    {
        return $this->has($key);
    }

    /**
     * Get a option option.
     *
     * @param  string  $key
     * @return mixed
     */
    public function offsetGet($key)
    {
        return $this->get($key);
    }

    /**
     * Set a option option.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function offsetSet($key, $value)
    {
        $this->set($key, $value);
    }

    /**
     * Unset a option option.
     *
     * @param  string  $key
     * @return void
     */
    public function offsetUnset($key)
    {
        $this->set($key, null);
    }

    /**
     * Save all modified options into database
     */
    public function __destruct()
    {
        $this->save();
    }

}

可以看到我们顺便实现了 ArrayAccess 接口,所以我们在拿到 OptionRepository 的实例后就可以使用类似于 $option["fuck"] 的形式来获取数据了(其实我后来一次也没用到)。

不过光是实现了一个 Repository 还是不够的,我们还需要把它绑定到服务容器里,同时注册个 Facade 给它,让我们能够更优雅地调用仓库类的相关方法:

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // 绑定单例到服务容器上
        $this->app->singleton("option", AppServicesOptionRepository::class);
    }
}

新建一个 Option 类并集成 Laravel 的 Facade 基类:


然后我们在 config/app.php 中加入我们 Facade 的别名:

 [
        "Option"    => AppServicesFacadesOption::class
    ],

];

大功告成!我们现在又可以像以前那样方便地使用类似于 Option::get("shit") 的方法获取数据,而且又大幅减少了数据库操作,是不是很棒呢~ (=゚ω゚)=

好吧其实本文也没讲啥有用的东西,不过希望对从其他框架迁移到 Laravel 的开发者们有所启示~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30444.html

相关文章

  • PHP日常开发小结

    摘要:参考一些博主的经验和自己的开发经验进行总结持续更新。优先使用和集合来操作和处理数据。 参考一些博主的经验和自己的开发经验进行总结-持续更新ing。 功能设计 功能尽量模块化; 类的设计尽量单一,函数功能单一; 需要uml图(类图、时序图、组件图)、文档沉淀; 编写风格 遵循PSR-1 基础编码规范https://laravel-china.org 遵循PSR-2 编码风格规范h...

    xfee 评论0 收藏0
  • Laravel核心解读--Database(一)基础介绍

    摘要:第三步注册工厂启动数据库服务数据库服务的启动主要设置的连接分析器,让能够用服务连接数据库。 在我们学习和使用一个开发框架时,无论使用什么框架,如何连接数据库、对数据库进行增删改查都是学习的重点,在Laravel中我们可以通过两种方式与数据库进行交互: DB, DB是与PHP底层的PDO直接进行交互的,通过查询构建器提供了一个方便的接口来创建及运行数据库查询语句。 Eloquent...

    reclay 评论0 收藏0
  • PHPer面试指南-Laravel

    摘要:简述的生命周期采用了单一入口模式,应用的所有请求入口都是文件。分发请求一旦应用完成引导和所有服务提供者都注册完成,将会移交给路由进行分发。此外,由于对动态方法的独特用法,也使测试起来非常容易。 本书的 GitHub 地址:https://github.com/todayqq/PH... Laravel 作为现在最流行的 PHP 框架,其中的知识较多,所以单独拿出来写一篇。 简述 La...

    alaege 评论0 收藏0
  • php实现依赖注入(DI)和控制反转(IOC)

    摘要:工厂模式,依赖转移当然,实现控制反转的方法有几种。其实我们稍微改造一下这个类,你就明白,工厂类的真正意义和价值了。虽然如此,工厂模式依旧十分优秀,并且适用于绝大多数情况。 此篇文章转载自laravel-china,chongyi的文章https://laravel-china.org/top...原文地址: http://www.insp.top/learn-lar... ,转载务必保...

    tomato 评论0 收藏0
  • 深入理解控制反转(IoC)和依赖注入(DI)

    摘要:本文一大半内容都是通过举例来让读者去理解什么是控制反转和依赖注入,通过理解这些概念,来更加深入。这种由外部负责其依赖需求的行为,我们可以称其为控制反转。工厂模式,依赖转移当然,实现控制反转的方法有几种。 容器,字面上理解就是装东西的东西。常见的变量、对象属性等都可以算是容器。一个容器能够装什么,全部取决于你对该容器的定义。当然,有这样一种容器,它存放的不是文本、数值,而是对象、对象的描...

    HollisChuang 评论0 收藏0

发表评论

0条评论

qingshanli1988

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<