Я попытался реализовать memcache для хранения результатов Db (в пределах tablegateway), но у меня есть проблема. Без «SetItem» и методы «GetItem», запрос работает отлично, но если я использую их, он выводит сообщение об ошибке:Zend Framework 2 - Использование Memcache/Memcached для хранения результатов DB
An error occurred
An error occurred during execution; please try again later.
Additional information:
PDOException
File:
C:\Program Files (x86)\xampp\htdocs\ZF-Tutorial\vendor\zendframework\zendframework\library\Zend\Serializer\Adapter\PhpSerialize.php:48
Message:
You cannot serialize or unserialize PDOStatement instances
Внутри моей tablegateway есть
namespace Application\Model;
use Zend\Cache\Storage\StorageInterface;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Sql;
use Application\Model\Defaultlanguage;
class AccessoriesTable
{
protected $tableGateway;
protected $cache;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function setCache(StorageInterface $cache)
{
$this->cache = $cache;
}
public function fetchAll($lang = null)
{
if(!isset($lang)) {
$lang = DefaultLanguage::LANG;
}
if(($result = $this->cache->getItem('testcache')) == FALSE) {
$adapter = $this->tableGateway->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select();
$select->columns(array(
'id',
'accessories' => $lang
));
$select->from('cat_accessories');
$select->order('accessories ASC');
$statement = $sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$this->cache->setItem('testcache', $result);
}
return $result;
}
внутри моего модуля. php
'Application\Model\AccessoriesTable' => function($sm) {
$tableGateway = $sm->get('AccessoriesTableGateway');
$cacheAdapter = $sm->get('Zend\Cache\Storage\Memcache');
$table = new AccessoriesTable($tableGateway);
$table->setCache($cacheAdapter);
return $table;
},
'AccessoriesTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Accessories());
return new TableGateway('cat_accessories', $dbAdapter, null, $resultSetPrototype);
},
Я попытался использовать memcache внутри своего контроллера и просматривать и работать нормально. Я не понимаю, где (есть) ошибка (ы). Спасибо всем вам за помощь.
EDIT 28-06-2015
Я нашел решение здесь, работает нормально, но я не люблю так много: https://samsonasik.wordpress.com/2012/09/27/zend-framework-2-using-zendcache-and-hydratingresultset-to-save-database-resultset/
внутри module.php
'Application\Model\AccessoriesTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$cacheAdapter = $sm->get('Zend\Cache\Storage\Memcache');
$table = new AccessoriesTable($dbAdapter);
$table->setCache($cacheAdapter);
return $table;
},
Внутренние принадлежности Класс:
namespace Application\Model;
class Accessories
{
public $id;
public $accessories;
public function exchangeArray($data)
{
$this->id = (!empty($data['id'])) ? $data['id'] : null;
$this->accessories = (!empty($data['accessories'])) ? $data['accessories'] : null;
}
public function getArrayCopy()
{
return get_object_vars($this);
}
}
Внутри AccessoriesTable:
namespace Application\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\ResultSet\HydratingResultSet;
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\Db\Sql\Select;
use Zend\Cache\Storage\StorageInterface;
use Application\Model\Accessories;
use Application\Model\Defaultlanguage;
class AccessoriesTable extends AbstractTableGateway
{
protected $table = 'cat_accessories';
protected $cache;
public $lang;
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->resultSetPrototype = new HydratingResultSet();
$this->resultSetPrototype->setObjectPrototype(new Accessories());
$this->initialize();
}
public function fetchAll($lang = null)
{
$this->setLang($lang);
$cacheName = md5('accessories-'.$this->lang);
if(($resultSet = $this->cache->getItem($cacheName)) == FALSE) {
$resultSet = $this->select(function (Select $select){
$select->columns(array('id', 'accessories'=> $this->lang));
$select->order(array($this->lang. ' asc'));
});
$this->cache->setItem($cacheName , $resultSet);
}
return $resultSet;
}
}
НОВЫЙ ВОПРОС: как я могу реализовать его с "традиционным" tablegateway конструкции ????
Я попытался использовать традиционный tablegateway, но ошибка такая же.
внутри tablegateway:
public function fetchAll($lang = null)
{
$this->setLang($lang);
$cacheName = md5('accessories-'.$this->lang);
if(($resultSet = $this->cache->getItem($cacheName)) == FALSE) {
$resultSet = $this->tableGateway->select(function (Select $select){
$select->columns(array('id', 'accessories'=> $this->lang));
$select->order(array($this->lang. ' asc'));
});
$this->cache->setItem($cacheName , $resultSet);
}
return $resultSet;
}
Works! но current() возвращает только строку результатов запроса. –
Хорошо, так. Попробуйте вызвать $ result-> toArray(), но я предполагаю, что это вызовет исключение. Другой способ - просто перебрать это с помощью цикла foreach. foreach ($ result as $ key => $ res) {$ this-> cache-> setItem ('testcache', $ res); } ' Кроме того, это моя собственная реализация простой функции запроса mysql. С помощью этой функции вы получите простой результат массива (просто массив, а не массивный объект или что-то еще), который вы можете напрямую вставить в свой memcache. http://paste.ofcode.org/ujWdDnkm6FmQ5b6GHBQYJB – Stanimir
посмотреть новое редактирование, I нашел решение, но мне не очень нравится –