пятница, 27 января 2012 г.

Memcached and tags

Сегодня произошла очень странная вещь.
Сижу, обдумываю проект, встраиваю memcashed в проект и думаю, как бы мне оптимизировать придыдущую версию этой реализации. Это все с учетом того, что я работаю с движком Yii.
В предыдущей версии я сохранял данные возвращенные из базы в моделях..., а сейчас думаю, а какого фига я тут корячусь.
Есть же возможность кешировать запросы средствами движка практически без моего участия. Сделал, работает, порадовался. Остается одна небольшая проблема, как сделать так, чтобы оперативно удалять устаревшие кеши при обновлении таблиц.
Сижу думаю.
А использую я ActiveRecord.
Надо поставить какие-то параметры, которые будут сообщать модели, что его таблица изменилась и нужно все перекешировать заного при запросе. Параметры эти запихнуть в тот же кеш. И осталось каким-то фигом при сохрании кеша эти параметры менять обратно. В общем система не эфективна...
Оказалось, что я не так уж и далек от решения, оказавшегося уже кем-то придуманым, кстати, чему не удивляюсь.
А нужно было всеголишь иметь не параметры для каждого запроса, а один, и определять изменения по нему не булевой операцией, а простым наращиванием! Просто как все гениальное.
А нашел я это тут http://www.opennet.ru/base/dev/memcached_tips.txt.html.
Теперь осталось придумать как запихнуть этот тег в кеш при записи в кеш и все будет пучком.
...
После полудня разбирательства в этой фигне, сообразил такую штуку. Фигачим класс:


class CTagCacheDependency extends CCacheDependency
{
public $tag;
        public $cache;
public function __construct($tag=null, $cache=null)
{
$this->tag=$tag;
$this->cache=($cache)?$cache:Yii::app()->cache;
}
       
protected function generateDependentData()
{
if($this->tag!==null)
                {
                        $t = $this->cache->get($this->tag);
                        if ($t === false) {
                                $t = time();
                                $this->cache->set($this->tag, $t);
                        }
                        return $t;
                }
}
}


L. 1

Используем его таким макаром в модели:

$this->cache(60, new CTagCacheDependency(get_class($this)));
L. 2

И не забываем после каждого изменения в базе (afterDelete, afterSave) делать это:

Yii::app()->cache->set(get_class($this), time(), 0);
L.3

Теперь у нас есть тег на кажду модель (таблицу) которая при любом обновлении будет кешироваться заного благодаря измененному тегу, распространяющемуся на кажду модель(таблицу).

Поясню немного.
L. 1 - это класс так называемой Зависимости кеша. В нем мы выбираем тег, если его нету, создаем новый и записываем его обратно в кеш.
В L. 2 мы устанавливаем эту зависимость для каждого кеша который будет выбираться и проверяться с данной зависимостью.
L. 3 - нужно для того, чтоб сказать нашей модели (через тег), что ее данные в таблице были обновлены.







среда, 25 января 2012 г.

Новая запись в таблице через Yii


PHP
Движок Yii 1.1.9
Работа с базой через CActiveRecord

Если захотите сохранить новую запись методом save(), воспользовавшись конструкцией Model::model(), ничего не получиться. Почему-то движек считает, что запись уже есть и $this->getIsNewRecord() возвращает false при использовании insert().
Интересно еще то, что save() вам вернет true и ошибок ни каких не выдаст, типа сохранил. А в таблице пусто.


Возвращаемся к старой доброй и надежной new Model().

суббота, 14 января 2012 г.

Как можно так писать!?

В один запрос возвращать данные с такими ключами:
[errorCode] => 0
[errorMessage] => ""

А на другой с такими:
[ErrorCode] => 0
[ErrorMessage] => ""

Где у таких людей мозги или там что у них в место них...?