dark-demon Не согласен Такой подход не соответствует 99% (грубо говоря) всех CMS, выложенных в общедоступное пользование на настоящий момент - почти все они являются готовыми сайтами, а не "универсальными заготовками", и используют их соответственно - просто ставят и пользуются, ничего или почти ничего не меняя. Даже дизайн зачастую оставляют как есть, только шапку переделывают и все. Существуют, конечно, исключения, когда систему перед использованием нужно серьезно дорабатывать под себя, и без этого никак, но почти все они предпочитают называть себя CMF. Имхо: 1. CMS = готовая к употреблению система управления содержанием сайта, кулинарной обработки не требует, поставить может любой желающий; 2. CMF = "движок" = не сайт, а только костяк будущего сайта (в предельном случае - вообще голый набор библиотек), поставить может только программист с руками; 3. CMF + заточка под конкретный функционал + удобная админка для манипулирования данными = CMS.
1. ядро, минимальный код, необходимый для работы 2. 2. framework, cmf, движок - набор библиотек, модулей и т.д. 3. cms, сайт 3.1. минимальный код, необходимый для инициализации 1 1.2. индивидуальные особенности сайта/cms
специально подчеркну: работающий комплекс, который надо ещё конфигурировать под конкретную задачу, менять дизайн, подключать модули и тп. если изменят хотябы список разделов - уже другой сайт ну в общем, мы друг друга поняли :-D
Такс, если помните, я обещал выложить свой вариант, вот выкладываю. Сразу оговорюсь, что это не код, который будет работать out of box, это пример конкретный, вырезка из конкретного реального проэкта (часть модулей которые я выложил я обрезал по причине сами понимаете какой, не обрезаны только forums и forums_topis, рабочего форума там нету, не хватает ещё одного самого большого модуля ). Так что смотрите, оценивайте, кто захочет - можете взять саму основу, подогнать под себя и юзать. собственно качать здесь: http://file.lv/framework.rar (71,6 KB) Весь код в UTF-8 (without signature). Так же в папке есть фаил Zend Project'a - у меня фаилы лежали в C:\framework\
- код читается хорошо. это радует. - почему работа с базой идет напрямую, а не через класс, хотя код объектно ориентированный?
440Hz А зачем нагружать код ещё какими-то классами по работе с БД? 1). Оно замедляет работу 2). У нас почти нету простых запросов, поэтому писать их всёравно руками надо. К тому же посмотрите код - методы в основном только и делают, что выбираю данные с базы данных и передают данные шаблонам. Всё чётко, ясно и понятно. В данном случае абстракция только усугубит всё. Ну лично я бы заюзал бы MySQLi в объектном синтаксисе, но я не с самого начала работаю в фирме, поэтому пишу так, как писали уже до меня. 3). У нас только одна БД, других не планируеться. Ti Да да, ты прав. Так что при желании можете попробовать зарегаться (если в Латвии есть знакомые) и посмотреть в действии
а нахрена все вообще тут делается? =) и насколько? микросекунды? не на том экономим... тебе, но мне вот не очень.
440Hz Я же написал, так было до меня. Так что как есть так есть. В своих проэктах уже юзаю MySQLi и объектный синтаксис Ну чужой код конечно ещё надо понять, что бы оценить его возможности и недостатки.
После моего поста как-то все утихли... Изучают что-ли? Когда можно ждать вердикт? mclaud А зря, тебе бы за бесплатно указали слабые стороны, дали бы советов что можно улучшить или сделать более эффективно
Psih ну если так экономить время хочешь - попробуй переписать на простых запросах...... а класс...... ну микросекунды....... хотя если планируется только с мускулем работать и никакой универсализации - то тут класс не принципиален...... упростив вот это до пары простых запросов: SELECT IFNULL((fra_access + 0), 2) AS fra_access, fra_for_id, for_id, for_title, (for_level + 0) AS for_level, (for_hidden + 0) AS for_hidden, (for_new_topic_level + 0) AS for_new_topic_level FROM forums LEFT JOIN forums_areas ON for_far_id = far_id LEFT JOIN forums_access ON fra_prf_id = '.(int)$session['auth'].' WHERE for_id = '.(int)$id, $database); думаю больше времени сэкономить можно......
Vah В данном случае это довольно простой запрос, который практически базу не нагружает. Хуже будет если это будет 3 запроса. Не только нагрузит саму базу, но ещё и PHP ьудет заметно медленее тормозить. Надо же всё-же рационально смотреть на оптимизацию. Можно не писать класс-прослойку для базы данных, потому что оно практически ничего не поменяет (а его отсутствие позволит немного съэкономить на ресурсах) в отличии от того, что писать вместо одного запроса - 3-4, каждый отдельно связать и слинковать данные с приведущими, что бы получить один целостный масив данных, который отправить на вывод. Вообщем, ИМХО, глупость вы сказали.
Предлагаю обсудить мою СУСку. Для примера дам код движка и код модуля по генерации страницы. Движок: PHP: <? session_start(); $global_module = array();//глобальная переменная доступных модулей $global_active_module = array();//глобальная переменная модулей используемых в шаблоне $global_idsheet = 0;//ИД активной страницы $global_options_result = 0;//загруженные настройки сайта из базы в формате mysql $global_message = array();//передача сообщений между модулями и подача системных сообщений require "config.php";//загрузка конфигурации //require "func_link.php"; load_options(); load_modules(); engine_sheet(); function load_options()//загрузка настроек { $db = dbconnect(); $sql = "SELECT * FROM ".$GLOBALS["_prefix"]."options"; $GLOBALS['global_options_result'] = mysql_query($sql,$db); mysql_close($db); mysql_data_seek($GLOBALS['global_options_result'], 0); while($row = mysql_fetch_array($GLOBALS['global_options_result'])) { if($row['name'] == "send_email") $GLOBALS['send_email']; } } function load_modules()//загрузка модулей из папки /modules { if ($handle = opendir('modules')) { while(false !== ($file = readdir($handle))) { if ($file != "." && $file != ".." && preg_match("/(.*)\.php|inc$/",$file)) { require("modules/".$file); } } closedir($handle); } } function engine_sheet() //генерирует страницу { global $PHP_SELF, $REQUEST_URI; //echo $REQUEST_URI."<br>"; if(empty($_GET['page']))//есть ли ссылка на страницу по ИД { preg_match("/\/([0-9a-zA-Z.]*)[\/]?/",$REQUEST_URI,$res);//вырезает из урла название страницы // echo $res[1]."<br>"; if(empty($res[1])) //если нет названия страницы, то запуск главной страницы { $sql="SELECT id, design FROM ".$GLOBALS["_prefix"]."sheet WHERE url='index.htm'"; // echo $sql."<br>"; } else//запуск страницы по названию в ссылке { $sql="SELECT id, design FROM ".$GLOBALS["_prefix"]."sheet WHERE url='".$res[1]."'"; // echo $sql."<br>"; } } else//если есть page значит запустить страницу через ИД { if(ctype_digit($_GET['page']) && strlen($_GET['page']) < 10){//проверка переменной page на правельность $sql="SELECT id, design FROM ".$GLOBALS["_prefix"]."sheet WHERE id='".$_GET['page']."'"; /*echo $sql."<br>";*/} else echo "неправельный параметр"; } $db = dbconnect(); $sheetrow = mysql_fetch_array(mysql_query($sql)); $GLOBALS['global_idsheet'] = $sheetrow['id']; //echo "id: ".$sheetrow['id']."<br>"; $sql = "SELECT id, template FROM ".$GLOBALS["_prefix"]."design WHERE id='".$sheetrow['design']."'"; $result =mysql_query($sql); $templ = mysql_fetch_array($result); $templ['template'] = stripslashes($templ['template']); mysql_close($db); //Подготовка списка якорей шаблона preg_match_all("/\<\!--\s(.*)\s--\>/",$templ['template'],$anchor_list); $GLOBALS['global_active_module'] = $anchor_list[1]; //echo implode(",", $anchor_list[1])."<br>"; //запуск загруженных модулей и вставка их в шаблон reset($GLOBALS['global_module']); foreach($GLOBALS['global_module'] as $value) { if($value->checket()) $templ['template'] = $value->toPage($templ['template']); } //просмотр и обработка системных сообщений reset($GLOBALS['global_message']); foreach($GLOBALS['global_message'] as $value) { if($value[0] == "ref_win_adr")//комманда перезагрузки страницы на указанный адрес { echo "<script language=javascript>self.location.replace('".$value[1]."');</script>"; return; } if($value[0] == "go_home") { echo $value[1]; return; } } echo $templ['template']; } Модуль: PHP: <?php //вставка дополнительных элементов в страницу class mod_sheet { var $name_module = array("titlecode", "headercode", "stylesheet", "textsheet"); var $anchor = array("<!-- titlecode -->", "<!-- headercode -->", "<!-- stylesheet -->", "<!-- textsheet -->"); var $data = ""; function mod_sheet() { } function checket() { foreach($GLOBALS['global_active_module'] as $value) { foreach($this->name_module as $value2) {if($value == $value2) return true;} } return false; } function toPage($template) { $db = dbconnect(); $sql="SELECT * FROM ".$GLOBALS["_prefix"]."sheet WHERE id='".$GLOBALS['global_idsheet']."'"; $sheetrow =mysql_fetch_array(mysql_query($sql)); mysql_close($db); // echo "title: ".$sheetrow['title']."<br>"; if(!empty($sheetrow['metakeywords'])) $datahead.="<meta name=\"keywords\" content=\"".$sheetrow['metakeywords']."\">\n"; if(!empty($sheetrow['metadescription'])) $datahead.="<meta name=\"description\" content=\"".$sheetrow['metadescription']."\">\n"; $template = str_replace($this->anchor[0], $sheetrow['title'], $template); $template = str_replace($this->anchor[1], $datahead, $template); $template = str_replace($this->anchor[2], "<link href=\"css.css\" rel=\"stylesheet\" type=\"text/css\">", $template); $template = str_replace($this->anchor[3], stripslashes($sheetrow['data']), $template); // echo $template; return $template; } } array_push($GLOBALS['global_module'], new mod_sheet());//инициализация модуля и запись его в список глобальных модулей ?> Хотелось бы ваши советы по поводу создания движка на объектах хотя бы абстрактно?
Psih начал чтение и не смог не высказаться ;-) includes/shared.inc 1/ для определения параметров вызова лучше бы использовать explode, а не split 2/ с конструкцией for($i=0; $i++ < 7 надо бы быть поосторожнее. здесь в цикле $i никогда не будет иметь значения 0. операцию вы не выиграли (что после тела цикла, что до него, $i всё равно увеличивается), а wtf фактор усилили. в качестве побочного эффекта -- отсутствие обработки $request[0]... 3/ а можно было настроить конфигурацию мускула так, чтобы обойтись без двух вызовов set charset и set names при каждом коннекте? 4/ Код (Text): /* Если на сервер зашли через IP - Перебросить на www */ if ($_SERVER['SERVER_NAME'] == $_SERVER["SERVER_ADDR"]){ header('Location: http://www.boomtime.lv'); die(); } ... можно было бы переместить в начало файла (до соединения с базой) 5/ разборки с $server_name и $server_domain, возможно, упростятся, если их разруливать на уровне апача и устанавливать не в этом файле, а в index.php, который для каждого домена будет свой. скорее всего у вас конечное число вариантов [jenya-dev]-[friends]. во всяком случае однозначно должно исчезнуть пугающее условие count($server_name) > 2 && $server_name != '' дальше начинается что-то очень интимное. понравился код Код (Text): $db_lng = '_'.$session['language']; $time = time(); $domain = 'friends'; switch($session['language']){ case 'ru': header('Content-language: ru'); $db_lng = '_ru'; /* Locale */ putenv("LANG=ru_RU"); setlocale (LC_MESSAGES, "Russian"); bindtextdomain ($domain, "locale"); textdomain($domain); bind_textdomain_codeset($domain, 'UTF-8'); break; case 'en': header('Content-language: en'); $db_lng = '_en'; /* Locale */ putenv("LANG=en_EN"); setlocale(LC_MESSAGES, "en_US"); bindtextdomain ($domain, "locale"); textdomain ($domain); bind_textdomain_codeset($domain, 'UTF-8'); break; case 'lv': header('Content-language: lv'); $db_lng = '_lv'; /* Locale */ putenv("LANG=lv_LV"); setlocale (LC_MESSAGES, "lv_LV"); bindtextdomain ($domain, "locale"); textdomain ($domain); bind_textdomain_codeset($domain, 'UTF-8'); } давайте вместе заценим использование $db_lng и $domain. в подробности работы с шаблонами я не вдавался, но уверен, что там всё в порядке. Dagdamor я тут уже высказывался в какой-то теме довольно неприлично по поводу шаблонов времени выполнения и их влияния на ресурсы сервера. по адресу http://osbtools.googlepages.com/ находится моя система работы с шаблонами. свободное скачивание и использование. открытый исходный код. но абсолютно другой подход.
stas_t 1) Делал не я, так что кому что нравиться. Впринципе что split, что explode - одно и тоже помоему. 2) $i++ - это пост-инкремент. Сперва сработает сравнение, потом $i будет инкрементирован. Опять же, писал этот кусок не я, так что в плане непонятности согласен. 3) Говорят это не всегда помогает и бывают глюки. Сам не проверял. Так что думаю стоит проверить. 4) Не все юзают Apache 5) На самом деле там веьма сложная ботаника конкретно для нашего случая. У нас у каждого свой dev хост с собственным префиксом (arvid-dev-(www|friends|groups|...).boomtime.lv) и без префикса dev (live сервер) и есть просто dev сервер без префиксов перед словом dev. Вообщем для остальных оно впринципе особо не нужно - просто упростить для каждого так, как нужно, я не модифицировал код Про интимное - это gettext $db_lng - оно потом используеться в запросах, т.к. все поля, которые имеют переводы прмо в базе называються field_ru, field_en, field_lv , соотвественно в запросе просто пишем 'SELECT field'.$db_lng.' AS field...'. Каждому своё. Я сразу писал, что это не готовый работать из коробки код и его надо подгонять ещё немного
Psih 1/ split для разбиения строки использует регулярное выражение, причём ereg-вариацию (posix), то есть очень медленную. explode делит по строке, без активирования механизма регулярных выражений. что и требуется. 2/ собственно, неразумно с моей стороны было бы спорить с тем, что $i++ -- это пост-инкремент я обратил внимание на нестандартное использование for, где этот пост-инкремент стоит не на отведённом для него месте, а прямо в условии, провоцируя побочный эффект. подобный стиль опасен при групповой разработке. 3/ я бы проверил 4/ апач тут не при чём. просто логичнее код, который проверяет параметр и прерывает скрипт поместить до того, как мы соединились с базой данных, ибо соединение пройдёт вхолостую. 5/ вместо: Код (Text): $server_name = explode('.', $_SERVER['SERVER_NAME']); if (count($server_name) > 1){ $server_domain = $server_name[count($server_name)-2].'.'.$server_name[count($server_name)-1]; }else{ $server_domain = $_SERVER['SERVER_NAME']; } /* Имя домена - после 2ой точки с конца */ $server_name = count($server_name) > 2 && $server_name != '' ? $server_name[count($server_name)-3] : 'www'; можно попробовать вот это: Код (Text): list ($server_name, $server_domain) = explode ('.', $_SERVER['SERVER_NAME'], 2); про интим/ использование gettext само по себе в разряд интима не попадает. однако в приведённом куске кода следующие довольно повеселившие моменты: - $db_lng сначала инициируется некоторым значением, а потом внутри switch получает то же самое значение. - $domain вообще непонятно что делает внутри switch, ибо bindtextdomain, textdomain и bind_textdomain_codeset могут спокойно быть вынесены за его пределы. я вот тут подумал, а что скажут люди, которые писали этот код, когда узнают, что он здесь выложен в открытом доступе и мы об него здесь вот так ноги вытираем ;-)
stas_t Ничего не подумают, основу никто не прячет и коллега знает что я его сюда выкладывал Т.к. я его основательно подготовил перед выкладкой, ничё криминального в этом нету 1). Ок 2). well, we work 5 programmers here, no questions were asked. Собственно впринципе то поменяю 3). 4). Ага, надо пнуть будет коллегу на работе по этому поводу 5). А если ввести просто boomtime.lv ? Будет глюк про интим - да эт уже мелкие придирки. И, между прочим, всё корректно отработает, если вдруг получиться так, что ни один CASE не отработает