Эта тема на forum.dklab.ru


Константин Жинько [tIT]: tIT-GP CMF v.01b
Чего не хватает, что глючит, что работает не так, как хотелось бы?
Ваши предложения, Ваши пожелания, Ваши жалобы, Ваше мнение, Ваши вопросы.

Предмет обсуждений в tar.gz архиве
Константин Жинько [tIT]:
И еще: есть ли перевод лицензии PHP?
Юрий Насретдинов:
tIT:
Хм... Хотелось бы увидеть, что можно сделать на основе данной CMF... Потому что просто так - голое ядро, и еще зачем-то сделанный стек... Ничего непонятно, хотелось хотя бы README к нему почитать, может быть попонятнее стало...
Константин Жинько [tIT]:
yUAC:
Вы меня удивляете:
1) На основе ЭТОЙ CMF можно только попытаться что-нмбудь сделать, - это не релиз, а альфа, и, вдобавок, версия 0.1, а не 1.0
2) А что Вам еще надо, кроме ядра? Это же не CMS! Да и модуль для работы с БД там исключительно тестовый - в перспективе нормальный... Плюс к ядру будет написана какая-нибудь админка для работы с модулями, мини-отладчик.
3) README! А чем index.php не подошел? Там вроде черным по-белому описано, что и как можно делать с ядром на стороне клиента... А в exts/dbi.php описано, как работать с ядром на стороне модуля.

Вопрос "Чего не хватает в ядре?" остается открытым.
Юрий Насретдинов:
<?
require_once "core/core.php";

$timer = new Timer();

$timer->start();
$core = new Core();
$timer->stop();

$timer->start();
$core->loadModule("dbi");
$timer->stop();

$timer->start();
$dbi = $core->createObject("dbi", "mysql");
$timer->stop();

$timer->start();
$dbi->query("SELECT ? FROM db", "*");
$dbi->exec();
$timer->stop();

$timer->start();
$dbi->query("SELECT * FROM db WHERE User=?", "yohoho");
$dbi->query("SELECT * FROM db WHERE User=?", "ohohoy");
$dbi->exec();
$timer->stop();
?>
<pre>
Дамп ядра:
<?var_dump($core);?>
Дамп слоя DBI:
<?var_dump($dbi);?>
<?
echo "\nДва запроса выполнялись: ".$timer->getLast();
echo "\nОдин запрос выполнялся: ".$timer->getLast();
echo "\nСоздание объекта DBI длилось: ".$timer->getLast();
echo "\nЗагрузка модуля DBI длилась: ".$timer->getLast();
echo "\nСоздание ядра длилось: ".$timer->getLast();
echo "\nИтого: ".$timer->getTotal();
?>
</pre>
Где здесь описание???
Константин Жинько [tIT]:
А сам код Вам разве ни о чем не говорит???
Anonymous:
tIT:

Очень очень сильно, особенно по внутреннему построению, напоминает SAPID (SAPI (XML Sapiens) Based CMS). Просто до удивления похоже! Не находите? Причём у них пока тоже не релиз, а тестовая демо версия, только с примером реализации CMS.
Константин Жинько [tIT]:
Гость:
В первый раз про такую слышу...
Ладно посмотрю... Вряд ли они умудрились залезть на мою машину, отключенную от инета %-)
bæv:
Очень очень сильно, особенно по внутреннему построению, напоминает SAPID
Лично я ничего общего не заметил -- видать, это просто попытка рекламы...
Rumata:
не знаю - зачем Вам стек, но если он Вам нужен, то Вы большой извращенец, сли пишете для этого класс, который используется для внутрнних целей. простите, не удержался - в любом случае я никого не хотел обидеть

стек в PHP рализован с помощью массивов и парой функций array_push/array_pop. аналог метода Stack::isEmpty - функция count(массив)
если вам так необходим стек, то можно было бы написать и более простое


class Stack
{
var $_stack;

function clear()
{
$this->_stack = array();
}

function copy()
{
return ($this->isEmpty()) ? null : end($this->_stack);
}

function isEmpty()
{
return (bool)!count($this->_stack);
}

function Stack()
{
$this->clear();
}

function pop()
{
return array_pop($this->_stack);
}

function push($value)
{
$this->_stack[] = $value;
}

}

Юрий Насретдинов:
Вы большой извращенец, сли пишете для этого класс, который используется для внутрнних целей. простите, не удержался - в любом случае я никого не хотел обидеть
полностью согласен...
Rumata:
ваше Stack::extractStack() бессмысленно, стек это такое хранилище данных, из которого можно взять только одно значение за один раз. этот метод - очевидная избыточность кода, к тому же Вы не по правилам наследуете классы

переопределяя методы в TimerStack::метод() вы должны вызывать родительские методы строчкой parent::метод() - иначе тряется смысл ООП: наследование свойств
см. свой метод TimeStack::push()
Константин Жинько [tIT]:
см. свой метод TimeStack::push()
Согласен... Просто забыл про такую штуку - бывает (-%

ваше Stack::extractStack() бессмысленно
Думая над ответом, пришел к выводу, что действительно не нужен.

М-да... Такая красивая вещь была - придется прибить...%
Юрий Насретдинов:
tIT:
Хех, красивая, но абсолютно ненужная.
Константин Жинько [tIT]:
yUAC:
Увы (-%
Ant:
Уезжаем в мусорку?
scalpel:
Подождите уезжать :).
Вообще предположить даже не могу в каком случае можно применить этот стек...
Может быть есть случаи, когда он действительно нужен? У кого-нибудь есть мысли по этому поводу?
Константин Жинько [tIT]:
Ant:
Вы что, с ума сошли?
Это же ТЕМА!
Для нее вообще можно отдельную ветку отделить. Например PHP::CMF. Я даже готов модератором стать =)

scalpel:
Нечто похожее я вычитал из второго Wrox'овского издания по PHP. Правда забыл, где он применялся %
scalpel:
Нечто похожее я вычитал из второго Wrox'овского издания по PHP. Правда забыл, где он применялся %
А Вы когда реализовывали стек, Вы помнили где его можно будет применить? :)...
А то смешно получается: писал... писал... оказалость что это никому не нужно. :)
Константин Жинько [tIT]:
scalpel:
Забавно...
Когда писал - думал, что будет удобно этой штукой пользоваться...
Константин Жинько [tIT]: tIT-GP CMF v.01b
Выкладываю новую версию.

Произведен небольшой рефакторинг кода с учетом пожеланий.
Rumata:
честно говоря мне непонятн до сих пор код, который имеет основную смысловую нагрузку - демонстрация работы стека. удалив класс стека, тм не менее Вы его оставили в неявной форме в классе Timer. если Вам так жизненно необходим стек используйте мою конструкцию, приведенную выше - http://forum.dklab.ru/viewtopic.php?p=62487#62487 .

Ваш код с моими комментариями

function setError(){
$num_args = func_num_args();
if($num_args > 1){
$args = func_get_args();
$prepared = call_user_func_array('sprintf', $args);
$this->errorStack[] = $prepared;
}
elseif($num_args === 1){
$str = func_get_arg(0);
$this->errorStack[] = $str;
}
return false;
}

function setWarning(){
$num_args = func_num_args();
if($num_args > 1){
$args = func_get_args();
$prepared = call_user_func_array('sprintf', $args);
$this->warningStack = $prepared; // !!! здесь или ...
}
elseif($num_args === 1){
$str = func_get_arg(0);
$this->warningStack[] = $str; // ... или здесь - опечатка ???
}
return true;
}


две функции практически идентичны - имеет смысл вынести в три отдельных функции, например

function getMessage()
{
// здесь творим и выдумывает свое
}

function setError()
$this->errorStack[] = $this->getMessage();
}

function setWarning()
$this->warningStack[] = $this->getMessage();
}

Константин Жинько [tIT]:
Rumata:
Опечатку не заметил сначала - спасибо.

две функции практически идентичны
Ваша реализация мне известна. Попробую и ее. Просто чем-то она мне вначале не понравилась и я не стал ее применять.
Rumata:
Ваша реализация мне известна
это стандартное решение в ООП:


class Core{

var $errorStack;
var $warningStack;

function _setMessage(&$stack, $message)
{
if (!$message) return;
$stack[] = (count($message) == 1) ? $message[0] : call_user_func_array("sprintf", $message);
}

function setError()
{
$args = func_get_args();
$this->_setMessage($this->errorStack, $args);
}

function setWarning()
{
$args = func_get_args();
$this->_setMessage($this->warningStack, $args);
}

}

Egor Ermakov:
Как-то слабо это все на ООП смахивает imho. Вот взять допустим те же модули, каждый отдельно реализованный модуль (например ваш "слой" DBI ) это элемент общей сущности -- "модуль системы" . Здесь явно направшивается базовый класс для всех модулей, возможно сделанный примерно так:

class _module{
var $core;
var $duration;
var $duration_total;
var $is_valid; /* Признак, находится ли объект в нормальном(рабочем) состоянии */

/* Вероятно, любому модулю понадобиться адрес объякта ядра, так почему бы
не реализовать это в базовом классе? Договоримся что будем передовать ядро
первым параметром функции */
function _module(&$core){
$this->is_valid = true;
$this->duration = array();
$this->duration_total = 0;
$this->core = $core;
$args = array();
for($i = 1;$i < func_num_args(); $i++){
$args[] = func_get_arg($i);
}
call_user_func_array(array(&$this, "init"), $args);
}
/* Разве не надоедливо перед вызовом метода, время работы которого нужно замерить вызвать
$timer->start, а в конце $timer->stop ? Почему бы не сделать возможность
в базовом классе вызвать любой метод, замерив время его выполнения?
Впринципе, можно сделать еще лучше, хранить еще массив с именами вызваемых
методов, тогда вывод статистики будет не рутинным, но это я оставлю для вас :)*/
function time_wrapper($func){
$start = getmicrotime();
$args = array();
for($i = 1;$i < func_num_args(); $i++){
$args[] = func_get_arg($i);
}
$result = call_user_func_array(array(&$this, $func), $args);
$this->duration_total =+ ($this->duration[] = getmicrotime() - $start);

return $result;
}
/* Ну и функции получения этих замеров */
function duration_last(){
return array_pop($this->duration);
}
function duration_total(){
return $this->duration_total;
}

/* Проверка состония объекта */
function is_valid(){
return $this->is_valid;
}
}
Причем в этом классе специально нет метода init, так как его экземпляр сам по себе бессмысленен.
Тогда метод ядра createObject() примет примерно такой вид:

/* .... */
function createObject(){
$name = func_get_arg(0);
$args = array();
$args[] = $this; /* Помните, первым параметром ядро :) */
for($i = 1;$i < func_num_args(); $i++){
$args[] = func_get_arg($i);
}
$obj = new $name($args);
return $obj->is_valid ? &$obj : NULL; /* Возвращаем адрес, а не копию */
}

Ну и соответсвенно создавать класс DBI уже как потомок _module:

class DBI extends _module{
/*...*/
}

Вообщем что-то вроде этого. Да кстати, если placeholder-ы это часть DBI, то зачем вы их выделили как просто функции?
Rumata:
Egor Ermakov:
$this->duration[] = $this->duration_total = getmicrotime() - $start;

исправлено на
$this->duration_total += ($this->duration[] = getmicrotime() - $start);
Константин Жинько [tIT]:
Ну и соответсвенно создавать класс DBI уже как потомок _module
Этого как раз и не хочется. Каждый класс (модуль) должен работать и без ядра дабы использоваться в любых проектах без изменения кода.

Разве не надоедливо перед вызовом метода, время работы которого нужно замерить вызвать
$timer->start, а в конце $timer->stop ?
Это как раз лишняя нагрузка...
Я сделал замеры для демонстрации скорости ключевых моментов (инит ядра и ДБИ), подача SQL-запросов.

Класс Timer для того и создан - замерить время выполнения участка кода.
Представьте ситуацию:


$timer->start();
$core->func1();
$core->func2();
$core->func3();
/*...*/
$core->func15();
$timer->stop(); //Замеров и вычитаний меньше, чем при вызове timer_wrap() для каждого метода => замер точнее


По хорошему исправлений и Ц.У. достаточно, чтобы еще раз взять бумагу и ручку и спроектировать ядро с нуля. =)
Константин Жинько [tIT]:
С ручкой и бумагой справился -- красивая картинка получилась ==)))
Теперь думаю, как же мне эту красоту реализовать...%
Жалко, сканера нет, а то бы выложил красоту-то.

Эта тема на forum.dklab.ru