Monday, September 22, 2008

Php, агрегация, псевдонаследование

Задача на примере.
 Есть класс View. Хочется создать класс Cache_View который будет агрегировать внутри себя объект класса $view, а внешне иметь такой же интерфейс как и класс view.

Понятно что на это многие покрутят пальцем у виска, отправят учить ооп, и скажут что нибудь про наследование. Для остальных продолжу мысль.

Простейшая реализация (наследование не подходит, нужно агрегировать)- агрегировать, и определить кучу методов вида


public function xxx($param1,$param2)
{
return $this->agregatedObject->xxx($param1, $param2);
}
?>



Реализация где не придется реализовывать эту кучу методов.


class A
{
public function f1()
{
}
}

class B
{
protected $_a = null;
public function __construct(A $a)
{
$this->_a = $a;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_a, "A::$function"), $params );
}
}

//как работает
$a = A();
$b = B($a);

$a->f1();
$b->f1();// тоже самое что и строчкой выше. Произойдет вызов метода f1 объекта $a
?>


Если кому то еще интересно, ниже пример использования.

class View
{
public function render($template)
{
//return html
}
public function f1()
{
}
//...
public function f120()
{
}
}

class Cache_View
{
protected $_view = null;
protected $_cache = null
public function setCache($cache)
{
$this->_cache = $cache;
}
public function __construct(View $v)
{
$this->_view = $v;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_view, "View::$function"), $params );
}

public function render($template)
{
if ( $this->_cache != null && ! $this->_cache->mis($this->makeKey($template))// если объект кэша есть и в нем чего то лежит
return $this->_cache->get($this->makeKey($template));// то вернем закэшированные данные

$out = $this->_view->render($template);
if ( $this->_cache != null)
$this->_cache->set($this->makeKey($template), $out);
return $out;
}

public function makeKey($str)
{
retirm md5($str);
}
}

//примеры исползования

$view = View();
$cache = Cache::create(Cache::File);
$cachedView = Cached_View($view);
$cachedView->setCache($cache):

$view->test();
$cachedView->test();// тоже самое что и строчкой выше. Вызов метода агрегированного класса
$cachedView->render('splash.php'); // а вот здесь будет предприняты попытка заглянуть в кэш и вернуть закэшированные результаты, если их нет, то произойдет отработка обычного $view->render и результат положится в темплейт
?>


Пример реализации чего то похожего внешне на множественное наследование



class Base()
{
public function base_function() {};
}

class A
{
public function f1()
{
}
}

class B extends Base
{
protected $_a = null;
public function __construct(A $a)
{
$this->_a = $a;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_a, "A::$function"), $params );// понятно что тут можно проверять наличичие метода поочереди у пула объектов, и вызывать их
}
}

$a = new A();
$b = new B($a);
$b->base_function(); //ok child Base
$b->f1(); // looks like child A

Wednesday, September 17, 2008

Простые вещи, php

При работе с проектом хотелось не слишком много, просто отслеживать время выполнения скриптов, а также количество вызвов скриптов.
   Простое решение - в конце каждого скрипта ( у нас правда это один index.php) пишется в файл uri + и время выполнения скрипта.

  Однако выяснилось, что из за кусков кода вроде этого

header("Location: bla bla bla");
exit();

Некоторые вещи просто не ловятся. А очень хочется понять не в них ли вся проблема :)

Решение оказалось простым. Использовать

register_shutdown_function('callback');

Например в нашем проекте есть класс Rapid в котором лежат жизненно необходимые нам вещи.

class Rapid
{
//...
  public static function quit()
  {
    //write to log
  }
//..
}
// тут как раз регистрируем статическую функцию, как функцию по завершению
register_shutdown_function(array('Rapid', 'quit'));

Ньюанс : эта функция вызвается даже после php fatal error!

cd@cd-laptop:~/tmp$ cat 2.php


register_shutdown_function('quit');
echo 'start';
require_once('none.php'); // у меня нет файла, будет фатал.
echo 'end';
function quit()
{
    echo 'quit';
}


cd@cd-laptop:~/tmp$ php 2.php
start
Warning: require_once(none.php): failed to open stream: No such file or directory in /home/cd/tmp/2.php on line 7
Fatal error: require_once(): Failed opening required 'none.php' (include_path='.:/usr/share/php:/usr/share/pear') in /home/cd/tmp/2.php on line 7
quit
cd@cd-laptop:~/tmp$

Sunday, July 20, 2008

Распределённые системы управления версиями

Давным давно читал похвальные отзывы об mercurial, bazaar и иже с ними.
В силу природного любопытства нашел таки время прочитать про них подробнее - понравилось.
Очень порадовала возможность забирать себе изменения с какого то конкретного бранча, причем делается это легко и непринужденно.
Прочитав - забыл. Т.к. основной проект на svn и проблема в том чтобы обучить дизайнеров и flash программистов новой софтине (на svn то с трудом заставили их переходить).
Тут возникает новый проект, ни с чем не связанный, отказываемся от php (устал я от него) в пользу python + django (интересно, удобно) заодно решили и репозиторий сменить.
Из консоли вдвоем поделали тесты (я bazaar, другой сотрудник mercurial) в общем простейшие операции прошли на ура. Все просто. (Для базаар пришлось пару модулей питоновских поставить только)

В чем же жопа? В плагинах к эклипсу. Я давным давно пришел ко мнению что ide должно быть ide а не редактором, и eclipse (полюбился он мне тем, что есть поддержка многих языков) плагины к двум вышеперечисленным клиентам убогие. mercurial плагин отмел сразу, три кнопки и в тех не разобраться. С bazaar ковырялся чуть подольше в надежде на чудо, сам плагин нормальный, в плане локальный commit, diff etc... . Танцы с бубном начались на push, и заявленная поддержка (только sftp) у меня не работала.
Осталось впечатление крайней сырости и недоделанности.

В общем как ни грустно, буду сидеть на svn + через полгодика попробую опять.

P.S. В голове еще крутится идея чтобы испльзовать bzr-svn, но крайне боюсь глюков, что может быть черевато на основном проекте, хотя может через некоторое время попробую, хотя бы из интереса.

Tuesday, July 15, 2008

debian/ubuntu apt-get NO_PUBKEY

Все время забываю
Проблема

apt-get update
W: GPG error: http://mirror.yandex.ru stable Release: Следующие подписи не могут быть проверены, так как недоступен общий ключ: NO_PUBKEY 07DC563D1F41B907


Решение

# gpg --keyserver wwwkeys.eu.pgp.net --recv-keys 07DC563D1F41B907
gpg: requesting key 1F41B907 from hkp server wwwkeys.eu.pgp.net
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 1F41B907: public key "Christian Marillat <marillat@debian.org>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg: imported: 1
# gpg --armor --export 1F41B907 | apt-key add -


Wednesday, July 9, 2008

Все гениальное просто

Блин. Сколько я мучался с zend debuger + zend studio.
А ларчик открывался просто

Thursday, May 8, 2008
ZSE + XDEBUG
3:07AM PDT · dtaylor7
I think Zend hates xdebug... But the ZSE contains a full PDT (it has xdebug support). So, remove (move) the plugins/com.zend.php.debug*, then start the studion with "ZendStudio -clean"

Hmm, there will be xdebug support in the PHP Debugger select... I tested it, works.


test

test

Sunday, June 22, 2008

Флаги языков в апплете индикатора расскладки gnome.

Долго мучался без флагов с дефолтным индикатором расскладки.
В итоге нашел решение.
копируем флаги в папоку ~/.icons/flags
обызываем ru.png us.png
открываем gconf-editor
desktop/gnome/peripherals/keyboard/indicator/showFlags

ставиь галочку show country flag
и все.
 
Каталог сайтов, Добавить сайт