Monday, September 29, 2008

django fixtures использование

Изучаю джанго.

Понадобились fixtures. Полез в новую джанго-книжку, написано много, как использовать. А как их создавать непонятно.
В итоге.

Пусть есть модель page для ее есть админка, лежит в application yyy

Я делал так.


    1. Создал необходимые данные для этой модели через админку.
    2. Перешел в директорию проекта набрал ./manage.py dumpdata --indent=2  yyy > ./data/fixtures/xxx.json
    3. Прописал в settings.py FIXTURE_DIRS = (  PROJECT_ROOT + '/data/fixtures/',)
    4. И уже при установке сначала ./manage syncdb
    5. Затем ./manage.py loaddata xxx

Tuesday, September 23, 2008

Конвертирование ошибок в exceptions.

Задача
Преобразовать все ошибки в исключения (exceptions) для более удобной их обработки.
Решение подсмотрено на php.net в комментариях.

class My_Exception extends Exception {
public static function errorHandlerCallback($code, $string, $file, $line, $context)
{
$e = new self($string, $code);
$e->line = $line;
$e->file = $file;
$e->context = $context;
throw $e;
}

}

set_error_handler(array("My_Exception", "errorHandlerCallback"), E_ALL);



Теперь практически все ошибки будут преобразованны в Exception. Теперь достаточно легко и непринужденно мы можем отлавливать ошибки php в одном месте, например



// bla bla bla
try
{
$controller->dosmth();
}
catch( Controller_Wrong_Data_Exeption $e)
{
// do smth
}
catch ( My_Exception $e)
{
// we know it's php error
}



Такой метод не ловит фаталы, а очень хочется. Где то встречал решение с использованием особенности ob_start, ob_flush, если найду завтра добавлю.

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$
 
Каталог сайтов, Добавить сайт