首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟PDOStatement::execute

模拟PDOStatement::execute
EN

Stack Overflow用户
提问于 2014-12-04 14:51:21
回答 2查看 78关注 0票数 0

我试图用Memcache中的函数扩展我的PDO类。特别是,我创建了一个调用cache_execute的函数,该函数允许我首先检查缓存中是否存在结果,然后返回缓存中的信息,如果缓存中还不存在信息,则返回数据库中的信息(如果还不存在,则将信息放入缓存中)。

下面是我当前代码的一个示例:

代码语言:javascript
复制
namespace trf;
class StatementWithCaching extends \PDOStatement {
    public $db;
    public $cache;
    protected function __construct(&$db) {
        $this->db =& $db;
    }

    function cache_execute( $array = NULL , $cache = FALSE , $cacheTime = 1800 ) {
        if( is_a( $cache , 'Memcache' ) ) {
            $query = $this->queryString;
            foreach ($array as $key => $value) {
                $query = str_replace(':' . $key , "'" . addslashes( $value ) . "'", $query );
            }
            try {
                $memResults = $this->mconn->get( md5( $this->queryString ) );
            }
            catch ( \Exception $e ) {
                $memResults = FALSE;
            }

        } else {

        }
    }
}

我的问题是-如何将从缓存中检索到的信息放在PDOStatement::fetch()PDOStatement::fetchAll()等可以检索的位置。

我的目标是能够运行StatementWithCaching::execute()StatementWithCaching::cache_execute(),并且仍然以相同的方式检索结果(使用StatementWithCaching::fetch()StatementWithCaching::fetchAll() )。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-04 16:56:58

我能够通过扩展PDOStatement::fetch()PDOStatement::fetchAll()函数来解决这个问题。

代码语言:javascript
复制
namespace trf;
class StatementWithCaching extends \PDOStatement {
    protected $db;
    protected $cache;
    protected $cacheReturn;
    protected $cacheQuery;
    protected $queryCacheTime;
    protected function __construct(&$db) {
        $this->db =& $db;
    }

    function cache_execute( $array = NULL , $cache = FALSE , $cacheTime = 1800 ) {
        if( is_a( $cache , 'Memcache' ) ) {
            $this->cache = $cache;
            $this->queryCacheTime = $cacheTime;
            $this->cacheQuery = $this->queryString;
            if( $array !== NULL ) {
                foreach ($array as $key => $value) {
                    $this->cacheQuery = str_replace(':' . $key , "'" . addslashes( $value ) . "'", $this->cacheQuery );
                }
            }
            $this->debugData( 'Trying to get data from cache for query: ' . $this->cacheQuery . ' (' . md5( $this->cacheQuery ) . ')' );
            $this->cacheQuery = md5( $this->cacheQuery );
            try {
                $this->cacheReturn = $this->cache->get( $this->cacheQuery );
                $this->debugData( 'Reporting return: ' . var_export( $this->cacheReturn , TRUE ) );
            }
            catch ( \Exception $e ) {
                $this->cacheReturn = FALSE;
                $this->debugData( $e->getMessage() );
            }
            if( is_null( $this->cacheReturn ) || $this->cacheReturn == FALSE || is_null( $this->cacheQuery ) || !is_a( $this->cache , 'Memcache' ) ) {
                if ($array === null) {
                    parent::execute();
                } else {
                    parent::execute($array);
                }
            }   
        } else {
            if ($array === null) {
                parent::execute();
            } else {
                parent::execute($array);
            }
        }
    }

    function fetch( $fetchStyle = \PDO::FETCH_BOTH, $cursor_orientation = \PDO::FETCH_ORI_NEXT , $cursor_offset = 0 ) {
        if( is_null( $this->cacheReturn ) || $this->cacheReturn == FALSE || is_null( $this->cacheQuery ) || !is_a( $this->cache , 'Memcache' ) ) {
            $fullResults = parent::fetchAll();
            if( is_a( $this->cache , 'Memcache' ) ) {
                $this->debugData( 'Inserting data into cache:' . print_r( $fullResults , TRUE ) );
                $this->cache->set($this->cacheQuery , $fullResults , MEMCACHE_COMPRESSED , $cacheTime );
            }
            return parent::fetch( $fetchStyle , $cursor_orientation = \PDO::FETCH_ORI_NEXT , $cursor_offset = 0 );
        }
        else {
            $this->debugData( 'Returning Cached Results' );
            switch ($fetchStyle) {
                case \PDO::FETCH_BOTH:
                    return $this->cacheReturn[$cursor_offset];
                    break;

                case \PDO::FETCH_ASSOC:
                    $data = $this->cacheReturn[$cursor_offset];
                    foreach ($data as $key => $value) {
                        if( is_numeric( $key ) ) {
                            unset( $data[$key] );
                        }
                    }
                    return $data;
                    break;

                case \PDO::FETCH_LAZY:
                    $data = $this->cacheReturn[$cursor_offset];
                    $return = new \stdClass();
                    foreach ($data as $key => $value) {
                        if( !is_numeric( $key ) ) {
                            $return->$key = $value;
                        }
                    }
                    return $return;
                    break;

                case \PDO::FETCH_OBJ:
                    $data = $this->cacheReturn[$cursor_offset];
                    $return = new \stdClass();
                    foreach ($data as $key => $value) {
                        if( !is_numeric( $key ) ) {
                            $return->$key = $value;
                        }
                    }
                    return $return;
                    break;

                default:
                    return $this->cacheReturn[$cursor_offset];
                    break;
            }
        }
    }

    function fetchAll() {
        if( is_null( $this->cacheReturn ) || $this->cacheReturn == FALSE || is_null( $this->cacheQuery ) || !is_a( $this->cache , 'Memcache' ) ) {
            $fullResults = parent::fetchAll();
            if( is_a( $this->cache , 'Memcache' ) ) {
                $this->debugData( 'Inserting data into cache: ' . print_r( $fullResults , TRUE ) );
                $this->cache->set($this->cacheQuery , $fullResults , MEMCACHE_COMPRESSED , $this->queryCacheTime );
            }
            return $fullResults;
        } else {
            $this->debugData( 'Returning Cached Results' );
            return $this->cacheReturn;
        }
    }

    private function debugData( $data ) {
        if( isset( $_GET['debug'] ) && $_GET['debug'] = DEBUGVAL ) {
            print('<pre>');
            print_r( $data );
            print('</pre>');
        }
    }
}

虽然该解决方案仍然没有处理可以为PDOStatement::fetch()PDOStatement::fetchAll()设置的所有标志,但可以对其进行进一步扩展。

到目前为止,我已经做了一些测试,结果非常好。

票数 0
EN

Stack Overflow用户

发布于 2014-12-04 16:06:50

我强烈建议您不要将缓存访问逻辑与DB访问逻辑混合使用。换句话说,我不会为了写入缓存而扩展特定于DB的类。毕竟,当您不需要时,为什么尝试将诸如语句、结果集等概念引入一个简单的缓存层。

相反,我将寻找一个更高级别的抽象,可能是一个类,您可以将一个有效的DB连接和一个有效的连接传递到您的缓存层(在您的例子中是Memcache),并让该类编排用于对缓存和DB进行读写的逻辑。

作为一个高级示例(显然,这省略了错误/异常处理等):

代码语言:javascript
复制
class WriteTroughCache {
    protected $pdo;
    protected $cache;
    protected $cache_ttl = 1000;
    // not shown variouos other options that might be needed for cache or DB

    public function __construct(PDO $pdo, Memcache $cache, $options = array()) {
        $this->pdo = $pdo;
        $this->cache = $cache;
        if (!empty($options)) {
            // not shown load options from array into option properties including cache_ttl
        }    
    }

    public get($key) {
        $result = $this-cache->get($key);
        if ($result) {
            return $result;
        }
        // not in cache, get from DB
        $value = $this->db_get($key);
        if (false === $value) {
            // key did not exist in DB
            return false;
        } else {
            // key found in DB
            $this->cache->set($key, $value, 0, $this->cache_ttl);
            return $value;
        }
    }

    public function set($key, $value) {
        // see if key exists
        // if so, update cache first
        $value = $this->get($key);
        if($value) {
            $this->cache->set($key, $value, 0 , $this->cache_ttl);
        }           
        return $this->db_set($key, $value);
    }

    public function db_get($key) {
        // not shown perform DB query using PDO object
        // return value at key if found or false if not found
    }

    public function db_set($key, $value) {
        // not shown perform DB query using PDO object
        // return true or false based on success of insert
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27296972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档