Доброго времени суток. У меня пара вопросов, косательно моего кода, в частности они касаются производительности. В программировании далеко не новичек. Но только сейчас пришлось озаботиться такой проблемой. Заранее всем благодарен. Вопрос 1-й (закрыт): //шаблонизатор Код (PHP): public function OUT(){ $this->loadTemplate(); $a = $this->getEnabledModules(); foreach($a as $b => $key){ $this->tpl = str_replace($a[$b]['location'], $this->getModuleContent($a[$b]), $this->tpl); $c = array_search($a[$b]['location'], $this->tplPositionsUnUsed); if($c != false) { unset($this->tplPositionsUnUsed[$c]); } } foreach($this->tplPositionsUnUsed as $b){ $this->tpl = str_replace($b, '', $this->tpl); } return $this->tpl; } Массив $this->tplPositionsUnUsed изначально содержит все позиции в шаблоне ('{footer}', '{logo}', '{topmenu}'). Я использовал его для того чтобы нижний цикл проверял весь шаблон реже. Производительней ли это без строк: Код (PHP): $c = array_search($a[$b]['location'], $this->tplPositionsUnUsed); if($c != false) { unset($this->tplPositionsUnUsed[$c]); } Вопрос 2: //'передача' переменных. Код (PHP): #index.php include_once('engine/engine.class.php'); include_once('engine/config.class.php'); include_once('includes/mysql.class.php'); include_once('includes/anything.class.php'); include_once('includes/anything2.class.php'); include_once('engine/templateengine.class.php'); $config = new config(); $mysql = new mysql($config->get('system', 'db', 0)); $engine = new engine(); $anything = new anything($config->getThree('anything')); $anything2 = new anything2(); $te = new templateEngine(); $te->setAll($mysql, $config->getThree('templateEngine'), $engine); $engine->setAll($mysql, $anything, $anything2, $te); #примерное содержимое setAll public function setAll($mysql, $config, $engine){ $this->db = $mysql; $this->config = $config; $this->engine = $engine; } Передаю в классы переменные таким образом. Правильно ли это, есть ли другие варианты? Для умников про мой стаж программирования отвечу сразу - я самоучка, книги не читал. Знаю что есть такие вещи как GLOBAL и extends, но думаю что GLOBAL менее выгодный в данной ситуации, а extends не подходит. Вопрос 3-й: //реализация конфига Сам конфиг: Код (PHP): <?php $this->config = array ( 'system' => array ( 'charset' => 'utf8', 'db' => 0, 'timezone' => '+3', ), 'templateEngine' => array ( 'checkRestrictedVariableNames' => false, 'template' => 'first', ), ); Класс который им заправляет: Код (PHP): <?php class config{ public function __construct(){ include_once('config.php'); $this->wasEdited = false; $this->temp = array(); } public function get($cat, $param, $default){ return isset($this->config[$cat][$param]) ? $this->config[$cat][$param] : $default; } public function getThree($cat){ return isset($this->config[$cat]) ? $this->config[$cat] : false; } public function get2Three($cat, $cat2){ return isset($this->config[$cat][$cat]) ? $this->config[$cat][$cat2] : false; } public function get2($cat, $cat2, $param, $default){ return isset($this->config[$cat][$cat2][$param]) ? $this->config[$cat][$cat2][$param] : $default; } public function get3($cat, $cat2, $cat3, $param, $default){ return isset($this->config[$cat][$cat2][$cat3][$param]) ? $this->config[$cat][$cat2][$cat3][$param] : $default; } public function setByArray($value){ $this->wasEdited = true; $this->config = $value; } public function set($cat, $param, $value){ $this->wasEdited = true; $this->config[$cat][$param] = $value; } public function set2($cat, $cat2, $param, $value){ $this->wasEdited = true; $this->config[$cat][$cat2][$param] = $value; } public function set3($cat, $cat2, $cat3, $param, $value){ $this->wasEdited = true; $this->config[$cat][$cat2][$cat3][$param] = $value; } public function setForThisSession($cat, $param, $value){ $this->temp[] = array($cat, $param, $this->config[$cat][$param]); $this->config[$cat][$param] = $value; } public function set2ForThisSession($cat, $cat2, $param, $value){ $this->temp[] = array($cat, $cat2, $param, $this->config[$cat][$param]); $this->config[$cat][$cat2][$param] = $value; } public function set3ForThisSession($cat, $cat2, $cat3, $param, $value){ $this->temp[] = array($cat, $cat2, $cat3, $param, $this->config[$cat][$param]); $this->config[$cat][$cat2][$cat3][$param] = $value; } public function unsetOld(){ foreach($this->temp as $t){ switch(count($t)){ case 3: $this->config[$t[0]][$t[1]] = $t[2]; break; case 4: $this->config[$t[0]][$t[1]][$t[2]] = $t[3]; break; case 5: $this->config[$t[0]][$t[1]][$t[2]][$t[3]] = $t[4]; break; } } } public function getAllConfig(){ return $this->config; } public function __destruct(){ //TODO что-то не так, помоему... if($this->wasEdited) { $this->unsetOld(); $txt = '<?php' . "\n" . '$this->config = ' . var_export($this->config, true) . ';'; $txt = str_replace("=> \n", '=>', $txt); $txt = str_replace(' => ', ' => ', $txt); $file = fopen(str_replace('config.class.php', '', __FILE__) . 'config.php', 'w'); fwrite($file, $txt); } } } ?> Конфиг реализовал многомерным массивом, так как прочитал статью на хабре, что это самый быстрый способ. Тут есть немного не ООП, но дальше третьей ветви массива уже бессмыслено лезть. Функция set будет использоваться не часто, поэтому заблокированный файл - не страшно. Правильна ли реализация? Весь код мой, задавайте любые вопросы. Вопросы буду дописывать в шапке, поэтому, пожалуйста, пишите номер вопроса, на который отвечаете.
Любой вопрос - почему вы не соорудили синтетический тест и не проверили, просто напросто? Добавлено спустя 17 секунд: Учитывая, что
Потому что только пишу всю систему. Шаблон полностью не заполнен, и модули доконца не написаны. Результаты будут явно не соответсвтовать.
Вам нужно проверить производительность конкретного решения. Сделайте синтетический тест с повторением текущего и с альтернативой. И смотрите, что производительнее. Относительную производительность.
Ок, спасибо. Странно что сразу не додумался, хотя дебагер написал. Первый вопрос закрыт. Второй посмотрите?
Код (PHP): include_once('engine/engine.class.php'); include_once('engine/config.class.php'); include_once('includes/mysql.class.php'); include_once('includes/anything.class.php'); include_once('includes/anything2.class.php'); include_once('engine/templateengine.class.php') Код (PHP): $array = [ 'engine/engine.class.php', 'engine/config.class.php', // .. и все остальные пути к файлам ]; foreach($array as $path) { include_once($path); }
По-моему так только больше кода , да и никчему лишний цикл заводить. Вопрос в этой строке: $engine->setAll($mysql, $anything, $anything2, $te);
В этом случае да, но если данных больше или сделать "универсальную" функцию, которая будет делать подобное, будет полезно. А что такого страшного в цикле. Я вот тоже неравнодушен к производительности и много выяснял что да как, так вот выяснил такое, что много времени отнимает процесс - открыть файл РНР, проверить его содержимое на ошибки ну собственно потом интерпретировать в понятный для РНР вид код, как то так. т.е. исходя из этого кода должно быть как можно меньше и желательно чаще использовать встроенные функции РНР. А что в ней не так? что именно смущает? или как по вашему это должно быть?
Очень похоже на изначально неправильное архитектурное решение, которое порождает костыли, тянущие за собой костыли. Вам нужно сделать некий класс, который будет агрегировать в себя все остальные классы, эдакий супер-класс? Чтобы прям раз и из одного и того же места дергать и БД и все на свете? В таком случае, быть может, нужно заранее определять поля этого класса, а инициализацию их проводить в его конструкторе? Результат будет тот же, но код будет чище и логичнее. Добавлено спустя 3 минуты 50 секунд: Советую избегать многомерности в данном случае. Она тут просто не нужна. Профиту с нее что с коня молока, а удобству она во вред. Класс с конфигом сделайте статичным. Не нужно будет создавать экземпляр конфига, и он будет доступен из любой точки кода, это очень удобно. А зачем делать конфиг через нагромождение методов? Не проще ли просто в явном виде задать массив и обращаться к нему напрямую? Посмотрите, как это сделано, например, у Joomla.
Многомерность тут используется в целях безопасности. Каждый класс может использовать только переданный ему элемент конфига. За информацию спасибо. По поводу инициализации в конструкторе - невозможно, ибо классы инициализируется не одновременно, а поочереди. Добавлено спустя 2 минуты 45 секунд: Просто конструкция кажется неправильной, ибо раньше такой нигде не видел, написал что первым в голову взбрело. Добавлено спустя 1 минуту 4 секунды: Всмысле дергать БД? Это только будет занимать 1кб памяти, по-моему.
Безопасности кого от кого? Может не стоит решать проблемы, которых нет? Тогда читай про проектирование и архитектуру. Ну та там некое API собираешь, как я понял.
Будут использоваться нетолько мои скрипты - это будет некая исполняемая среда для чужих скриптов. Ну API доступно только в шаблонизаторе, грубо говоря, и то экранировано.