Phalcon ORM查询结果集强制使用缓存的方法及注意事项

注册缓存服务

在\Phalcon\DI\FactoryDefault()中默认ORM的缓存使用modelsCache名进行注册,所有我们也使用同样的名字进行注册以覆盖默认的modelsCache。

    //Setup memcache service
    $di->set('modelsCache', function () use ($config) {
        $frontCache = new Phalcon\Cache\Frontend\Data([
            "lifetime" => 86400  //全局默认有效时间
        ]);
        $cache = new Phalcon\Cache\Backend\Memcache(
            $frontCache,
            [
                "host" => $config->memcache->host,
                "port" => $config->memcache->port
            ]);
        return $cache;
    });

Phalcon中的缓存分为前端和后端两部分,前端相当于数据接口,在数据存储或提取时进行数据的转义等加工,后端就是用于存储数据;程序只与前端进行通信,由前端负责与后端具体存储的进行通信来完成存储或者获取数据。这样的设计有利于在不修改程序业务逻辑的情况下更换所使用的后台缓存。
Phalcon支持APC、Xcache、Memcached、Redis等常用缓存设施,这里我们使用Memcached。

查访结果集使用缓存的方式

默认Phalcon的ORM是支持直接使用查询结果缓存的,如下所示:

<?php

// Get products without caching
$products = Products::find();

// Just cache the resultset. The cache will expire in 1 hour (3600 seconds)
$products = Products::find(
    [
        "cache" => [
            "key" => "my-cache",
        ],
    ]
);

// Cache the resultset for only for 5 minutes
$products = Products::find(
    [
        "cache" => [
            "key"      => "my-cache",
            "lifetime" => 300,
        ],
    ]
);

// Use the 'cache' service from the DI instead of 'modelsCache'
$products = Products::find(
    [
        "cache" => [
            "key"          => "my-cache",
            "cacheService" => "cache",
        ],
    ]
);

但通常不同的同学写的可能会不一样,尤其是涉及到key以及时间的一致性时,比较难以协调,所以比较合理的方式是在Model中直接设置一致的缓存策略,这样大家在写业务逻辑时不需要再关注缓存的设置和查询策略,可以集中在业务逻辑上。
同时,在Model中设置的缓存策略也不影响上述代码中所示的写法的有效性,如果在Controller中像上述代码写,会覆盖Model中的默认策略。

强制使用缓存

强制使用缓存的方法就是通过覆盖原有find和findFrist方法,并在自己写的方法中额外加入“cache”参数:

//新建model时加入以下方法

//创建key
protected static function _createKey($parameters)
    {
        $uniqueKey = array();

        foreach ($parameters as $key => $value) {
            if (is_scalar($value)) {
                $uniqueKey[] = $key . ':' . $value;
            } else {
                if (is_array($value)) {
                    $uniqueKey[] = $key . ':[' . self::_createKey($value) . ']';
                }
            }
        }

        return join(',', $uniqueKey);
    }

//覆盖默认的find的方法,强制使用缓存
public static function find($parameters = null)
    {
        if (!is_array($parameters)) {
            $parameters = [$parameters];
        }

        if (!isset($parameters['cache'])) {
            $parameters['cache'] = [
                "key" => self::_createKey($parameters),
                "lifetime" => 300
            ];
        }

        // Return the result in the cache
        return parent::find($parameters);
    }

public static function findFirst($parameters = null)
    {
        if (!is_array($parameters)) {
            $parameters = [$parameters];
        }

        if (!isset($parameters['cache'])) {
            $parameters['cache'] = [
                "key" => self::_createKey($parameters),
                "lifetime" => 300
            ];
            // Store the result in the memory cache
        }

        // Return the result in the cache
        return parent::findFirst($parameters);
    }

需要注意的问题

如果直接使用Phalcon官方文档中的示例代码会出现如下问题:

当直接使用find()或findFirst()时会遇到 PhalconException: Cache must be started first 错误:

官方文档示例中会遇到的错误

问题原因:

这是由于直接调用find()或findFirst()时,参数为null:

public static function find($parameters = null)
public static function findFirst($parameters = null)

用null调用self::_creatKey,得到的结果还是null,而用null是不能做为memcache的key用的

解决方法

在上述find和findFirst代码中的最开始加入如下部分, 如果$parameters为null,就自定义一个key:

// if parameters == null, create a paramters
        if (!isset($parameters)) {
            $parameters = [get_class() => 'all'];
        }
// if parameters == null, create a paramters
        if (!isset($parameters)) {
            $parameters = [get_class() => 'first'];
        }

最终代码

public static function find($parameters = null)
    {
        // if parameters == null, create a paramters
        if (!isset($parameters)) {
            $parameters = [get_class() => 'all'];
        }

        if (!is_array($parameters)) {
            $parameters = [$parameters];
        }

        if (!isset($parameters['cache'])) {
            $parameters['cache'] = [
                "key" => self::_createKey($parameters),
                "lifetime" => 300
            ];
        }

        // Return the result in the cache
        return parent::find($parameters);
    }

    /**
     * Implement a method that returns a string key based
     * on the query parameters
     */
    protected static function _createKey($parameters)
    {
        $uniqueKey = array();

        foreach ($parameters as $key => $value) {
            if (is_scalar($value)) {
                $uniqueKey[] = $key . ':' . $value;
            } else {
                if (is_array($value)) {
                    $uniqueKey[] = $key . ':[' . self::_createKey($value) . ']';
                }
            }
        }

        return join(',', $uniqueKey);
    }

    public static function findFirst($parameters = null)
    {
        // if parameters == null, create a paramters
        if (!isset($parameters)) {
            $parameters = [get_class() => 'first'];
        }

        if (!is_array($parameters)) {
            $parameters = [$parameters];
        }

        if (!isset($parameters['cache'])) {
            $parameters['cache'] = [
                "key" => self::_createKey($parameters),
                "lifetime" => 300
            ];
            // Store the result in the memory cache
        }

        // Return the result in the cache
        return parent::findFirst($parameters);
    }

上述代码是通用的,不需要任何修改,直接复制到新建的Model中就可以使用!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值