Php 模拟PDO语句::执行

Php 模拟PDO语句::执行,php,caching,pdo,memcached,Php,Caching,Pdo,Memcached,我试图用Memcache中的函数扩展我的PDO类。特别是,我创建了一个调用cache\u execute的函数,该函数允许我首先检查结果是否存在于缓存中,然后从缓存返回信息,如果信息尚未存在于缓存中,则从数据库返回信息(如果信息还不存在,则将其放入缓存) 下面是我当前代码的一个示例: namespace trf; class StatementWithCaching extends \PDOStatement { public $db; public $cache; pr

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

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

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()等检索到的位置


我的目标是能够运行
语句WithCaching::execute()
语句WithCaching::cache\u execute()
,并且仍然以相同的方式检索结果(使用
语句WithCaching::fetch()
语句WithCaching::fetchAll()
).

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

相反,我将寻找更高级别的抽象,可能是一个类,您将向该类传递一个有效的DB连接和一个到缓存层的有效连接(在您的例子中是Memcache),并让该类协调读/写缓存和DB的逻辑

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


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

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>');
        }
    }
}
trf;
class语句WithCaching extends\PDO语句{
受保护$db;
受保护的$cache;
受保护的$cacheReturn;
受保护的$cacheQuery;
受保护的$queryCacheTime;
受保护的函数构造(&$db){
$this->db=&$db;
}
函数cache_execute($array=NULL,$cache=FALSE,$cacheTime=1800){
if(是($cache,'Memcache')){
$this->cache=$cache;
$this->queryCacheTime=$cacheTime;
$this->cacheQuery=$this->queryString;
如果($array!==NULL){
foreach($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);
试一试{
$this->cacheReturn=$this->cache->get($this->cacheQuery);
$this->debugData('Reporting return:'.var_export($this->cacheReturn,TRUE));
}
捕获(\异常$e){
$this->cacheReturn=FALSE;
$this->debugData($e->getMessage());
}
如果(is_null($this->cacheReturn)|$this->cacheReturn==FALSE | | is_null($this->cacheQuery)| |!is_a($this->cache,'Memcache')){
如果($array==null){
父::执行();
}否则{
父::执行($array);
}
}   
}否则{
如果($array==null){
父::执行();
}否则{
父::执行($array);
}
}
}
函数fetch($fetchStyle=\PDO::fetch\u BOTH,$cursor\u orientation=\PDO::fetch\u ORI\u NEXT,$cursor\u offset=0){
如果(is_null($this->cacheReturn)|$this->cacheReturn==FALSE | | is_null($this->cacheQuery)| |!is_a($this->cache,'Memcache')){
$fullResults=parent::fetchAll();
如果(是a($this->cache,'Memcache')){
$this->debugData(‘将数据插入缓存:’。打印($fullResults,TRUE));
$this->cache->set($this->cacheQuery,$fullResults,MEMCACHE\u COMPRESSED,$cacheTime);
}
返回parent::fetch($fetchStyle,$cursor\u orientation=\PDO::fetch\u ORI\u NEXT,$cursor\u offset=0);
}
否则{
$this->debugData('Returning Cached Results');
开关($fetchStyle){
case\PDO::FETCH_两者:
return$this->cacheReturn[$cursor_offset];
打破
case\PDO::FETCH_ASSOC:
$data=$this->cacheReturn[$cursor_offset];
foreach($key=>$value形式的数据){
如果(是数字($key)){
未设置($data[$key]);
}
}
返回$data;
打破
case\PDO::FETCH_LAZY:
$data=$this->cacheReturn[$cursor_offset];
$return=new\stdClass();
foreach($key=>$value形式的数据){
如果(!是数字($key)){
$return->$key=$value;
}
}
return$return;
打破
case\PDO::FETCH_OBJ:
$data=$this->cacheReturn[$cursor_offset];
$return=new\stdClass();
foreach($key=>$value形式的数据){
如果(!是数字($key)){
$return->$key=$value;
}
}
return$return;
打破
违约:
return$this->cacheReturn[$cursor_offset];
打破
}
}
}
函数fetchA
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>');
        }
    }
}