|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
© Cваял этот сайтик для вас и себя bes13.
-=2009-2013=- |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ⇐ туда | на память | сюда ⇒ |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
гостевая книга в php
это уже можно применять. [2010-04-25] Гостевая книга - самый простой скрипт, который содержит в себе основные моменты интерактивных приложений. Развивая события можно написать блог, форум и целую социальную сеть. Главное понять принципы построения. Вот сейчас мы и попробуем это сделать (понять принципы, не сеть написать)). А принцип очень прост. Юзер пишет что то в элемент формы, браузер упаковывает это в переменные и отправляет в поток - серверу. Тот принимает эти переменные, обрабатывает нужным скриптом и в зависимости от сценария, производит разные действия. Сохраняет данные, преобразует, отправляет обратно или другим юзерам. Но все по порядку. Шаг 2Форма Для того, что бы отправить информацию с Вашего компьютера на сервер, необходимо её как то упаковать. Делается это формой, есть такая штука. Выглядет так: <formaction="?"method="post"></form> /*Всё, что находится между этими тегами, будет упаковано и отправлено на сервер. Не теги имеется ввиду, а данные, которые юзер введет в поля в этой форме. Делаем следующее:*/ <formaction="?"method="post"> <inputname="test"type="text"/><br/> <inputname="ok"type="submit"/> </form> Обратите внимание на: 1. action - это адрес скрипта, на который будут отправлены данные2. method - метод передачи. Есть два меотда - GET и POST. При первом методе всё, что будет написано в поле, прилепится к адресу в адресной строке, при втором методе будут сформированы внутренние переменные. Предпочтительнее второй метод, так как при первом имеется ограничение по количеству передаваемых символов. 3. name - это имя элемента формы, в данном случае текстового поля. Что бы сервер мог знать, от куда именно пришли данные. 4. у кнопки тоже есть имя, для того, что бы знать, какая именно кнопка была нажата. 5. Тип кнопки - submit говорит о том, что при её нажатии данные будут отправлены на сервер. Всё, как говориться "клиент дошел до нужной кондиции". Теперь пишем обработчик, то есть собственно серверную программу, которая будет принимать и обрабатывать полученные данные. Небольшая хитрость - форму и обработчик желательно помещать в один файл, это поможет вернуть данные, если форма заполнена не верно. Знак вопроса в action направит запрос сам на себя. Но всё по порядку.
Готово. Вот теперь в это поле можете написать Helo, World! и нажать кнопку. Что произошло. 1. Браузер отправил запрос из адресной строки на сервер.2. Сервер сформировал вывод и отправил обратно. 4. Браузер получил ответ и "нарисовал" форму. 5. Вы ввели в эту форму данные и отправили обратно на сервер. 6. Сервер получил эти данные, на основании их изменил вывод и отправил обратно. 7. Вы получили новую страницу, на которой кроме формы есть еще результат обработки. Теперь подробнее. При нажатии на кнопку браузер сформировал переменную name, в которую записал то, что было в поле, и отправил на сервер. Сервер принял эту переменную, идентифицировал её и функцией echo (можно использовать print, кому что нравится, это почти одно и то же) сформировал вывод. А теперь тонкости. Наберите в поле вот это: <Helo, World!> И нажмите кнопку. Видно что нибудь? Не видно. Но не потому, что нету, можете посмотреть исходный код страницы. Просто это интерпретируется как тег и не выводится на монитор. Чтоб избежать подобных казусов, необходимо закодировать спецсимволы. Делает это функция htmlspecialchars() Сделайте теперь так: <?php header('Content-Type:text/html;charset=utf-8'); ?> <formaction="?"method="post"> <inputname="test"type="text"/><br/> <inputname="ok"type="submit"/> </form> <?php $test=!empty($_POST['test'])?$_POST['test']:null; echohtmlspecialchars($test); ?>и почуствуйте разницу. Так вот, всё, что выводится в браузер (только туда, никуда иначе), нужно обрабатывать этой функцией. Теперь усложним задачу. При отправке данных запись в поле исчезает. А что, если что то не так? Бедный юзер должен всё заново переписывать? Будем вежливы и вернем ему форму с данными. Для этого немного изменим ход событий. Сначала примем переменную, потом выведем форму. <?php header('Content-Type:text/html;charset=utf-8'); $test=!empty($_POST['test'])?$_POST['test']:null; ?> <formaction="?"method="post"> <inputname="test"type="text"value="<?phpechohtmlspecialchars($test)?>"/><br/> <inputname="ok"type="submit"/> </form> <?php; echohtmlspecialchars($test); ?>Обратите внимание, что в параметре value="" должны быть именно кавычки, а не апострофы, так как апостроф в тексте порвет тег. При вводе имени O'Rally случится примерно следующее: <inputname="test"type="text"value='O'Rally'/>то есть часть имени (Rally) выйдет в тело тега. Это грозит как минимум искажением данных, как худший вариант - XSS атакой. Теперь усложним еще больше. Не просто выведем данные, а изменим содержание страницы в зависимости от. <?php header('Content-Type:text/html;charset=utf-8'); $test=!empty($_POST['test'])?$_POST['test']:null; ?> <formaction="?"method="post"> <inputname="test"type="text"value="<?phpechohtmlspecialchars($test)?>"/><br/> <inputname="ok"type="submit"/> </form> <?php if(isset($_POST['ok'])); echohtmlspecialchars($test); else echo'Напишитечтонибудь'; ?>То есть: Если существует переменная ok (нажата кнопка), выводим текст сообщения. Если нет, то дефолтную (по умолчанию) надпись. Это и есть оператор if... else, основа логической составляющей программы. Еще больше усложним: <?php header('Content-Type:text/html;charset=utf-8'); $test=!empty($_POST['test'])?$_POST['test']:null; ?> <formaction="?"method="post"> <inputname="test"type="text"value="<?phpechohtmlspecialchars($test)?>"/><br/> <inputname="ok"type="submit"/> </form> <?php if(isset($_POST['ok'])&&!$test) echo'Поленезаполнено.'; elseif(isset($_POST['ok'])) echohtmlspecialchars($test); else echo'Напишитечтонибудь'; ?>Обратите внимание на логику. Если есть переменная $ok и переменная $test пуста (функция empty() и знак инверсии !), выводим сообщение об ошибке, еще если нажата кнопка, выводим текст, еще выводим дефолтную надпись. Выполняться программа будет до первого соответствия, то есть если удовлетворяется первое условие (isset($_POST['ok']) && !$test), то второе и третье выполняться не будут. Теперь попробуем текст побольше: <?php header('Content-Type:text/html;charset=utf-8'); $test1=!empty($_POST['test1'])?$_POST['test1']:null; $test2=!empty($_POST['test2'])?$_POST['test2']:null; ?> <formaction="?"method="post"> <inputname="test1"type="text"value="<?phpechohtmlspecialchars($test1)?>"/><br/> <textareaname="test2"cols="40"rows="10"><?phpechohtmlspecialchars($test2);?></textarea><br/> <inputname="ok"type="submit"/> </form> <?php if(isset($_POST['ok'])) { if(!$test1) echo'Текстовоеполенезаполнено.'; elseif(!$test2) echo'Текстоваяобластьнезаполнена.';; else echohtmlspecialchars($test1), '<br>', htmlspecialchars($test2); } else { echo'Напишитечтонибудь'; } ?>Тут, как видите, появились блоки. Сначала проверяем нажата ли кнопка. Потом, если нажата, проверяем заполнение. А если не нажата, сразу выводим дефолтную надпись, игнорируя проверки в первом блоке. Теперь нюансы. Наберите в текстарее текст с переносами, используя enter. Видите, на выводе текст оказался без переносов. Это потому, что браузеру нужен не просто перенос, а тег <br />. Заменить переносы на этот тег поможет функция nl2br() <?php header('Content-Type:text/html;charset=utf-8'); $test1=!empty($_POST['test1'])?$_POST['test1']:null; $test2=!empty($_POST['test2'])?$_POST['test2']:null; ?> <formaction="?"method="post"> <inputname="test1"type="text"value="<?phpechohtmlspecialchars($test1)?>"/><br/> <textareaname="test2"cols="40"rows="10"><?phpechohtmlspecialchars($test2);?></textarea><br/> <inputname="ok"type="submit"/> </form> <?php if(isset($_POST['ok'])) { if(!$test1) echo'Текстовоеполенезаполнено.'; elseif(!$test2) echo'Текстоваяобластьнезаполнена.';; else echohtmlspecialchars($test1), '<br>', nl2br(htmlspecialchars($test2)); } else { echo'Напишитечтонибудь'; }Именно в таком порядке nl2br(htmlspecialchars($test2));не наоборот. И использовать её имеет смысл только в текстовых областях (<textarea>), так как текстовые поля (<input>)не предусматривают переносов. Ну вот и весь принцип в двух словах. Советы: 1. Используйте "прозрачные" имена переменных, то есть имя должно отражать суть. 2. Используйте сквозные имена. То есть они должны быть везде одинаковые, и в форме, и в php и в базе данных (об этом позже). Примерно так: <?php header('Content-Type:text/html;charset=utf-8'); $login=!empty($_POST['login'])?$_POST['login']:null; $message=!empty($_POST['message'])?$_POST['message']:null; ?> <formaction="?"method="post"> Логин:<br/> <inputname="login"type="text"value="<?phpechohtmlspecialchars($login)?>"/><br/> Сообщение:<br/> <textareaname="message"cols="40"rows="10"><?php echohtmlspecialchars($message);?></textarea><br/> <inputname="ok"type="submit"/> </form> if(isset($_POST['ok'])) { if(!$login) echo'Текстовоеполенезаполнено.'; elseif(!$message) echo'Текстоваяобластьнезаполнена.';; else echohtmlspecialchars($login), '<br>', nl2br(htmlspecialchars($message)); } else { echo'Напишитечтонибудь'; } ?> Шаг 3То, что мы сделали - игрушка, не более того. Для нормальной работы приложения часто необходимо запомнить данные и использовать их потом по назначению. Для этого используется запись в файл или в базу данных. Здесь мы рассмотрим вариант с использованием MySQL. Что это такое. Это отдельный сервер, который работает с реляционными базами данных. Он позволяет предоставлять доступ к данным сразу нескольким пользователям, быстро и эффективно обрабатывать эти данные. Работает этот сервер на специальном языке - SQL (Structured Query Language - язык структурированных запросов). Общение с этим сервером из php осуществляется набором специальных функций. Начнем по порядку. Создайте файл с названием config.php и поместите его в корень сайта (папку my_site). Напишите в него следующее: <?php #Настройкиподключения define('MYSQL_SERVER','localhost'); define('MYSQL_DATABASE','guest'); define('MYSQL_USER','root'); define('MYSQL_PASSWORD',''); define('PREFIX', 'guest_'); ?>Теперь по порядку. Вот тут мы определяем сервер. Если Вы используете Денвер, то сервер по умолчанию - localhost. На хостингах по разному, эту информацию дают при регистарации хостинга define('MYSQL_SERVER','localhost');Это название базы данных. Базу нужно создать, об этом позже. define('MYSQL_DATABASE','guest');Это пользователь. То есть по другому - юзер, от лица которого php будет делать запросы в БД. Его тоже надо создать, то есть зарегистрироваться в MySQL. define('MYSQL_USER','root');Ну а это соответственно пароль нашего юзера. define('MYSQL_PASSWORD','');Для того, что бы не бегать по всей базе в поисках таблиц приложения, используйте префикс. Тогда они всегда будут рядышком. То есть таблицы надо называть к примеру guest_users, guest_posts и так далее. define('PREFIX', 'guest_');Дальше идет подключение к серверу MySQL : mysql_connect.php <?php #СоединениесMysql $db_irbis=mysql_connect(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD)ordie(NO_CONNECT); define('CONNECT',$db_irbis); #Выборбазы mysql_select_db(MYSQL_DATABASE,CONNECT)ordie(NO_DB_SELECT); ; #Установкапараметровсоединения query('SETNAMESutf8',__FILE__,__LINE__);; query('SETCHARACTERSETutf8',__FILE__,__LINE__); query('SETCOLLATION_CONNECTION="utf8_general_ci"',__FILE__,__LINE__); ?> Функция mysql_connect() устанавливает соединение. При неудачной попытке мы останавливаем скрипт (die()). Дальше определяем константу с указателем на открытое соединение. Следом выбор нужной базы данных: А еще дальше мы выставляем кодировку соединения. То есть язык, на котором будут общаться PHP и MySQL Вот тут важный момент. Запрос, написанный на языке SQL, PHP отправляет на сервер баз данных функцией mysql_query(). Аргументами она принимает текст запроса и указатель на соединение. Кстати говоря, если второй аргумент не указывать, будет использовано последнее, успешно открытое соединение. А мы, для диагностики ошибок и остановки скрипта в таком случае, будем пользоваться своей функцией с созвучным названием query(), в которую и поместим штатную. Расположим её в этот же файл, чтоб не искать где попало. <?php; #Функциязапроса в MySQL functionquery ($sql,$file,$line) { $res=mysql_query($sql,CONNECT); ; if($res) { return$res; } else { die('<bstyle="color:red">Musqlerror:</b>'.mysql_error().'<br><b>Query:</b>'.$sql.'<br> <b>File:</b>'.$file.'<br><b>Line:</b>'.$line); header('location:error.html'); exit; } }; #СоединениесMysql $db_irbis=mysql_connect(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD)ordie(NO_CONNECT); define('CONNECT',$db_irbis); #Выборбазы mysql_select_db(MYSQL_DATABASE,CONNECT)ordie(NO_DB_SELECT); ; #Установкапараметровсоединения query('SETNAMESutf8',__FILE__,__LINE__);; query('SETCHARACTERSETutf8',__FILE__,__LINE__); query('SETCOLLATION_CONNECTION="utf8_general_ci"',__FILE__,__LINE__); ?> А для удобства передадим в неё аргументами название файла и линию, на которой находится запрос. Это очень удобно, потому что сразу видно где виновник безобразий. А еще мы выведем ответ интерпретатора MySQL и текст запроса. Что бы совсем было все понятно. А когда скрипт отладим, закомментируем строчку от греха по дальше. Порядочному юзеру это совсем не нужно, а хакер может извлечь полезную для себя информацию. Не пытайтесь запустить скрипт: базы данных пока нет, её нужно создать. Ну вот, подготовительные работы закончены. Теперь приступим к изготовлению самой базы. Для работы с MySQL в Денвере установлено специальное проложение - phpMyAdmin. Наберите в адресной строке http://localhost/Tools/phpMyAdmin, оно и откроется. В поле "Создать новую БД" раздела MySQL напишите guest (это название нашей базы), а из списка "Сравнение" выберите "utf8_general_si". В соседнем разделе phpMyAdmin соответственно "Russian (ru-utf8)" и "utf8_general_si". Нажмите кнопку "создать". ![]() Поздравляем - теперь у Вас есть собственная база данных. В верхнем меню найдите "Сервер: localhost" и вернитесь в начало. Нам нужно создать пользователя. Ссылка "Привилегии". Заполните форму, отметьте все превилегии и зарегистрируйте юзера на сервере MySQL, то есть создайте пользователя. Имя и пароль соответственно test или поставьте свои, только не забудьте изменить их в нашем конфигурационном файле config.php. ![]() Теперь слева найдите Вашу новую базу (guest) и в поле "Создать новую таблицу в БД guest:" напишите guest_posts, а ниже (Поля:) поставьте 4. Ну и соответственно "Пошел". Заполните таблицу так, как показано на образце: ![]() и нажмите "Сохранить". Всё, теперь у Вас есть таблица. Пока правда пустая. Выглядет она по аналогии с EXCEL примерно так:
Тут у нас: 1. id - идентификатор записи. Это не порядковый номер, запомните, это важно. Это уникальный ключ. Присваивается он автоматически при появлении новой записи, за это отвечает auto_increment (Вы выбрали его из списка при формировании таблицы). Суть его такова, что буде присвоернным единожды он будет неизменен. Мало того, если запись удалена, то id этой записи сохраняется и не будет повторно использоваться. Можно со спокойной совестью искать нужную запись по id, это как паспорт. 2. date - соответственно дата записи. Тип поля timestamp, что говорит о том, что запись будет автоматически проштампована датой создания. 3. user - логин юзера, оставившего сообщение. Тип поля varchar используется для хранения данных в строчку 4. text - текст сообщения. Тип поля mediumtext используется для хранения данных в с переносами. Давайте попробуем что нибудь в таблицу записать. Для этого организуем запрос. <? query("INSERTINTO`".PREFIX."posts` SET`login`='ВасяПупкин', `text`='МояперваязаписьвБД'" ,__FILE__,__LINE__); ?>Команды в SQL регистронезависимы, но для хорошей читабельности кода рекомендуем писать их большими буквами. Названия полей лучше обрамлять обратными кавычками, хотя работает запрос и без них. Для чего это делать. Дело в том, что если имя поля по трагическому стечению обстоятельств совпадет с каким нибудь служебным словом (допустим count) , то запрос будет ошибочным. А обрамленное обратными кавычками слово воспринимается только как имя поля. Строковые (не числовые) значения, передаваемые в запросе, нужно обрамлять апострофами. Команды, выполняемые при запросе, мы рассмотрим постепенно. А сейчас соединим всё в кучу и попробуем посмотреть результат: index.php <?php #Подключаемконфигурационныйфайл include'./config.php'; ; #Подключаембазуданных include'./libs/mysql_connect.php';; ; query("INSERTINTO`".PREFIX."posts`; SET`login`='ВасяПупкин',; `text`='МояперваязаписьвБД'" ,__FILE__,__LINE__); ?>Запустим скрипт. Ничего на первый взгляд не произошло. Но. Зайдите в phpMyAdmin, слева найдите нашу базу (guest) и нажмите вкладку "ОБЗОР". Вашему взору предстанет первая запись в таблице. Теперь еще одна тонкость. Перепишите запрос таким образом, призвав на помощь нашего старого знакомого: <? query("INSERTINTO`".PREFIX."posts`; SET`login`='O'Rally',; `text`='МояперваязаписьвБД'" ,__FILE__,__LINE__); ?>и запустите скрипт еще раз. Эта запись не появится в базе, а появится ошибка, потому что нарушен синтаксис запроса. Это основа так называемых SQL-инъекций. Получается, что в поле мы пишем только О, а Rally попадает в сам запрос. Если туда написать всяких гадостей(несанкционированных команд), то MySQL может их выполнить и наделать разных неприятностей. Мы не станем рассматривать виды этих нехороших медикаментозных средств, а просто сразу покажем, как от них нужно защищаться. Часто можно встретить такую рекомендацию: <? $text=trim(htmlspecialchars($text)); ?>Никогда так не делайте. Это абсолютно безграмотно. А: Во первых, обязательно нужно экранировать спецсимволы в строковых значениях. Для этого существуют функции mysql_escape_string() и mysql_real_escape_string(). Нужно сразу отметить, что работают они только при открытом соединениии с сервером MySQL. Во вторых числовые значения, допустим id при выборке, приводить в соответствие функциями (int) или intval(). Важный момент: еще есть директива magic_quotes_gpc (магические кавычки), которая зачастую включена по умолчанию. Эта штука автоматически экранирует входящие данные GET, POST И COOKIE. По этому можно получить двойное экранирование. Её можно отключить в настройках либо в .htaccess Но для того, что бы не запутаться при переносе скрипта на другой хостинг, лучше делать это непосредственно в самом сценарии. Делается это так: <?php functionstripslashes_deep($data); {; if(is_array($data)); $data=array_map("stripslashes_deep",$data);; else  $data=stripslashes($data); return$data;; } //Теперь, узнав предварительно, включены ли магические кавычки, мы сможем раз и на всегда избавиться от нежелательных бэкслэшей: if(get_magic_quotes_gpc()) { $_GET=stripslashes_deep($_GET);; $_POST=stripslashes_deep($_POST);; $_COOKIE=stripslashes_deep($_COOKIE); } Кстати говоря, абривеатура gpc в названии функции get_magic_quotes_gpc() Обозначает $_GET $_POST и $_COOKIE Что в данном случае сделала наша функция? Об этом чуть позже, когда узнаем что такое массив. А пока поместим этот код в файл с коннектом. Теперь приведем всё в порядок. Добавим наш запрос в файл с формой и подключим новые файлы: index.php Попробуйте что нибудь написать в полях и отправить на сервер. В phpMyAdmin (вкладка "Обзор") можно увидеть изменения таблицы. Для того, что бы вывести содержимое на экран, нужен еще один запрос, на выборку. Дополните код этим: <?php .; .; #Авотинашзапрос.; query("INSERTINTO`".PREFIX."posts`; SET`login`='".mysql_real_escape_string($login)."',; `text`='".mysql_real_escape_string($message)."'" ,__FILE__,__LINE__); }; else; {; echo'Напишитечтонибудь';; }; #Запроснавыборку; $result=query("SELECT*FROM`".PREFIX."posts`"; ,__FILE__,__LINE__); echomysql_result($result,0,"date");; echo'/';; echohtmlspecialchars(mysql_result($result, 0, 'login'));; echo'<br>';; echonl2br(htmlspecialchars(mysql_result($result, 0, 'text'))); Если сейчас запустить скрипт, то мы увидим последнюю запись из нашей таблицы. Как Вы поняли, выборка осуществляется оператором SELECT. Звездочка обозначает - все поля, FROM соответственно "ИЗ". Далее результат запроса обрабатывается соответствующими функциями, которые позволяют получить желаемое. Вот самый основной принцип работы с базами данных MySQL. Шаг 4А мы пока подумаем о флудерах. Если Вы сейчас еще раз нажмёте кнопку, или обновите страничку (кнопка F5), сообщение запишется еще раз. Что бы надавать флудерам по рукам, нужно сбросить пост данные в случае удачной записи. Делается это формированием новой страницы. Для этого используем хидер. Вспомните, нельзя отправлять заголовок раньше вывода, по этому меняем структуру. Обратите внимание на дополнительный параметр ?rnd='. time() Сам по себе он не несет ни какой информации, но появление в адресной строке браузера нового адреса даст команду на формирование новой страницы, на которой уже не будет данных в полях. Для информации - $_SERVER['PHP_SELF'] - это адрес Вашего файла со скриптом, то есть того, в котором это написано. Функция time() выдаст ткущее время в секундах, а значит число никогда не повториться. Так как мы изменили структуру, то вывод ошибок теперь выше формы, что не всегда интересно. Особенно когда необходимо разделить логику и вывод. По этому делаем так (а за одно выведем сразу оба сообщения об ошибках): <?php; header('Content-Type:text/html;charset=utf-8');; $test1=!empty($_POST['test1'])?$_POST['test1']:null; $test2=!empty($_POST['test2'])?$_POST['test2']:null; $array_error=array();; #Подключаемконфигурационныйфайл; include'./config.php';; #Подключаембазуданных; include'./libs/mysql_connect.php'; ; if(isset($_POST['ok'])); {; if(!$test1) {; $array_error[]='Текстовоеполенезаполнено.'; }; elseif(!$test2) {; $array_error[]='Текстоваяобластьнезаполнена.'; }; else {; #Авотинашзапрос.; query("INSERTINTO`".PREFIX."posts`; SET`login`='".mysql_real_escape_string($test1)."',; `text`='".mysql_real_escape_string($test2)."'" ,__FILE__,__LINE__);; #ПеренаправлениедлясбросаPOST; header('location:'.$_SERVER['PHP_SELF'].'?rnd='.time());; exit(); }; }; else; {; echo'Напишитечтонибудь';; } ?>; ; <formaction="?"method="post">; <inputname="test1"type="text"value="<?phpechohtmlspecialchars($test1)?>"/><br/>; <textareaname="test2"cols="40"rows="10"><?phpechohtmlspecialchars($test2);?></textarea><br/>; <inputname="ok"type="submit"/>; </form>; <?php; #Выводошибок echoimplode('<br>',$array_error).'<br>';; #Запроснавыборку; $result=query("SELECT*FROM`".PREFIX."posts`"; ,__FILE__,__LINE__); $row=mysql_fetch_assoc($result) echo$row['date'];; echo'/';; echohtmlspecialchars($row['login']);; echo'<br>';; echonl2br(htmlspecialchars($row['text'])); ?> Теперь у нас вся логика вверху, а вывод внизу. Заметили, у переменной появилось [ ]? Шаг 5Ну вот мы и добрались до массива. Массив, это та же переменная, только в неё можно записать несколько раздельных значений. Сделать это можно сразу: <?php $array_error=array('Первоезначение', 'Второезначение', 'Третьезначение'); ?> или прибавляя их по очереди: <?php $array_error[]='Первоезначение'; $array_error[]='Второезначение'; $array_error[]='Третьезначение'; ?> Суть этого такова, что в одной переменной находится несколько других. Обратиться к ним (получить их значения) можно либо по порядковому номеру элемента, если это простой массив (заметьте, что нумерация начинается с нуля, а не с единицы): <?php $array_error=array('Первоезначение', 'Второезначение', 'Третьезначение'); $value1=$array_error[0]; $value2=$array_error[1]; $value3=$array_error[2]; echo$value1, '<br>', $value2, '<br>', $value3; ?> либо по ключу (как бы названию переменной), если массив ассоциативный: <?php $array_error=array('Один'=>'Первоезначение','Два'=>'Второезначение','Три'=>'Третьезначение'); $value1=$array_error['Один']; $value2=$array_error['Два']; $value3=$array_error['Три']; echo$value1, '<br>', $value2, '<br>', $value3; ?> Что бы не переписывать все переменные для их вывода, используется функция implode(), где первым параметром указывается разделитель между выводом значений. В нашем случае это <br>. То есть что мы сделали: 1. Объявили переменную массивом. 2. Записали в массив все ошибки (их может быть гороаздо больше) 3. Разобрали массив в нужном месте и выдали ошибки на вывод. Вспомним функцию обработки входящих данных. Что мы сделали в нашей функции. <?php functionstripslashes_deep($data); {; if(is_array($data)); $data=array_map("stripslashes_deep",$data);; else  returnstripslashes($data);; } ?> is_array() проверяет, является ли переменная массивом. Если это так, то вызываем эту же самую функцию, пока не закончатся все элементы. Это назывется рекурсия - вызов функцией самой себя. А когда переменная не является массивом (добрались до самых глубин) обрабатываем её функцией stripslashes(), которая удаляет экранирующие бэкслэши \ . Дальше, уже девственно очищеные данные мы можем смело использовать в скрипте. Ну вот, зная что такое массив, тепеперь мы сможем вывести все сообщения, не только последнее. Так как результат запроса на выборку приходит из MySQL в виде массива, состоящего из рядов и ячеек. Разобрать массив на составляющие поможет функция mysql_fetch_assoc() и цикл while. Цикл, это маленькая программка, которая выполняется по кругу столько раз, сколько определено в условиях цикла. Выглядеть это будет так: <?php $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC" ,__FILE__,__LINE__); while($row=mysql_fetch_assoc($result)) echo$row['date'] .'/'. htmlspecialchars($row['login']) .'<br>'. nl2br(htmlspecialchars($row['text'])) .'<hr>'; ?> Звучит это примерно вот что: Если запрос прошел успешно, проходим по массиву, который сформировала функция mysql_fetch_assoc() взяв данные на основании идентификатора запроса ($result) и по очереди присваивая переменной $row элементы этого массива и выводим каждый элемент (ряд таблицы) отдельно. Оператор ORDER BY в запросе производит сортировку по заявленному полю (у нас по id). DESC означает - обратная. Это нужно, чтоб сообщения выводились сверху вниз. Если хотите наоборот, поставьте ASC. Засуньте это в свой скрипт и полюбуйтесь результатом. <?php $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC" ,__FILE__,__LINE__); $i=0; while($row=mysql_fetch_assoc($result)) { ++$i; if($i==1 && $page==1 ) echo'<spanstyle="color:red" >'; echo$row['date'] .'/'. htmlspecialchars($row['login']) .'<br>'. nl2br(htmlspecialchars($row['text'])); if($i==1 && $page==1 ) echo'</span>'; echo'<hr>'; ; } ?>
Шаг 6Ну а теперь совсем не составит труда снабдить эту цацку ВВ тегами и смайликами. <?php $bb=array('|/color|"', '[B]', '[/B]', '[I]', '[/I]', '[S]', '[/S]', '[U]', '[/U]', '[:)]', '[:(]', '[;)]', '[:D]' ); $tag=array('</span>', '<b>', '</b>', '<i>', '</i>', '<s>', '</s>', '<u>', '</u>', '<imgsrc="smailes/1.gif"/>', '<imgsrc="smailes/2.gif"/>', '<imgsrc="smailes/3.gif"/>', '<imgsrc="smailes/4.gif"/>' ); $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC" ,__FILE__,__LINE__); $i=0; while($row=mysql_fetch_assoc($result)) { ++$i; if($i==1 && $page==1) echo'<spanstyle="color:red" >'; $text=nl2br(htmlspecialchars($row['text'])); $text=str_replace($bb, $tag, $text); ; echo$row['date'] .'/'. htmlspecialchars($row['login']) .'<br>'. $text; if($i==1 && $page==1) echo'</span>'; echo'<hr>';; } ?> Поможет сделать это функция str_replace(), которая заменяет то, что задано первым аргументом на то, что задано вторым в строке, заданной третьим аргументом. К счастью эта функция умеет работать с массивами, заменяя соответствующие элементы. Шаг 7Для полного счастья снабдим её постраничным выводом. Для этого нам нужно выводить информацию из базы не всю сразу, а порциями. Это делается оператором SQL LIMIT. <?php $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC  LIMIT 0, 5 " ,__FILE__,__LINE__); ?> Первая цифра обозначает начало отсчета, вторая - конец. То есть этот запрос выведет пять последних записей. (Последних, потому что стоит сортировка в обратном порядке). На основании этого и сделаем постраничку. Сначала функция, определяющая нужный диапазон: <?php functionlist_page() { $num=10;; ; $page=!empty($_GET['page'])?$_GET['page']:1;; ; $result=query("SELECTCOUNT(*) AS `cnt` FROM`".PREFIX."posts`" ,__FILE__,__LINE__); ; $posts=mysql_result($result, 0);; $total=intval(($posts-1)/$num)+1;; $page=intval($page);; if(empty($page)or$page<0); $page=1;; if($page>$total); $page=$total;; $start=$page*$num-$num; return$start; }Задаем количество выводимых на странице сообщений ($num = 10). Считаем, сколько сообщений (строк) всего в таблице. Сделать это позволяет оператор COUNT(*) и функция mysql_result(). Она выводит результат запроса, который до этого был прсвоен псевдониму `cnt`. Дословно запрос звучит так: вывести количество рядов, удовлетворяющих условию, как значение поля cnt. Так как такого поля в нашей таблицы нет, MySQL создает так называемый алиас или псевдоним. То есть временное поле. Дальше немного арифметики, что бы не пропустить пустых значений и определить начальное положение. В результате мы имеем стартовую позицию, сформированную в зависимости от того, какая страница выбрана в параметре GET. Теперь нужно сформировать этот параметр, то есть вывести меню постраничной навигации. functionlist_mehu() { $page=!empty($_GET['page'])?$_GET['page']:1; for($i=1;$i<=$total;$i++) { $for=$i*$num-$num+1; $end=$i*$num; ; if($page==$i) $menu.='<b>['. $for .'-'. $end .']</b>'; else; $menu.='<ahref="?page='.$i.'" >['. $for .'-'. $end .']</a>'; } return$menu; }Вот тут одна особенность. Для работы нам понадобятся значения переменных $num и $total, а их не видно внутри функции. Первую переменную меняем на константу и выносим в конфигурационный файл: define("NUM",10); ?>Соответственно в функциях меняем $num на NUM. А переменную $total объявим глобальной, то есть видимой внутри функций. Тут есть одна тонкость. Дело в том, что если такая переменная встретится в последующем коде, то она будет уже определена, то есть получившая значение. Это может несколько запутать дело, по этому в больших приложениях не злоупотребляйте глобализацией. Ошибки такого плана очень трудно диагностировать. Теперь это выглядет так: $total=""; functionlist_page() { global$total;; ; $page=!empty($_GET['page'])?$_GET['page']:1;; ; $result=query("SELECTCOUNT(*) AS `cnt` FROM`".PREFIX."posts`" ,__FILE__,__LINE__); ; $posts=mysql_result($result, 0);; $total=intval(($posts-1)/NUM)+1;; $page=intval($page);; if(empty($page)or$page<0); $page=1;; if($page>$total); $page=$total;; $start=$page*NUM-NUM; return$start; } functionlist_mehu() { global$total; $page=!empty($_GET['page'])?$_GET['page']:1; for($i=1;$i<=$total;$i++) { $for=$i*NUM-NUM+1; $end=$i*NUM; ; if($page==$i) $menu.='<b>['. $for .'-'. $end .']</b>'; else; $menu.='<ahref="?page='.$i.'" >['. $for .'-'. $end .']</a>'; } return$menu; }Вообще, что бы не плясать с бубнами, можно упаковать это всё в класс, но это уже ООП, а мы пока ограничимся простыми функциями. Осталось привести в порядок главный запрос: $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC  LIMIT". list_page() ."," .NUM ,__FILE__,__LINE__); ?>А теперь пора привести в порядок и весь скрипт. Шаг 8Теперь пора приводить в порядок структуру приложения, так как накопилось уже изрядное количество кода. Так как этот скрипт планировался, как модуль для рассмотренного раньше ядра сайта, то так мы его и представим. У нас будут функции, которые можно использовать не только в гостевой книге. Допустим та же функция форматирования даты . Вывод смайликов тоже определим сюда же, мало ли что. Для них сделаем отдельный, дефолтный файл в библиотеках (libs) default.php <?php #Функцияbb-теговисмайликов functionbb_tag($text); { $bb=array('|/color|"', '[B]', '[/B]', '[I]', '[/I]', '[S]', '[/S]', '[U]', '[/U]', '[:)]', '[:(]', '[;)]', '[:D]' ); $tag=array('</span>', '<b>', '</b>', '<i>', '</i>', '<s>', '</s>', '<u>', '</u>', '<imgsrc="'.SKIN_PATH.'/images/smailes/1.gif"/>', '<imgsrc="'.SKIN_PATH.'/images/smailes/2.gif"/>', '<imgsrc="'.SKIN_PATH.'/images/smailes/3.gif"/>',; '<imgsrc="'.SKIN_PATH.'/images/smailes/4.gif"/>' ); ; returnstr_replace($bb,$tag,$text); }; ; #Функцияпереводадатыизазиатскогоформатавпрописной; functionformat_date($date); {; global$string_month;; $day=substr($date,8,2);; $month=$string_month[substr($date,5,2)];; $year=substr($date,0,4);; ; return$day.''.$month.''.$year;; } //Выводошибок functionerror_info($array_error) { if(!empty($array_error)) { $error=implode('<br>',$array_error); return$error; } else { returnfalse; } } Туда же, в директорию libs поместим файл коннекта и вынесем функции постраничного режима: connect.php <?php; #Функциязапроса в MySQL functionquery($sql,$file,$line) { $res=mysql_query($sql,CONNECT); ; if($res) { return$res; } else { die('<bstyle="color:red">Musqlerror:</b>'.mysql_error().'<br><b>Query:</b>'.$sql.'<br> <b>File:</b>'.$file.'<br><b>Line:</b>'.$line); header('location:error.html'); exit; } }; #Борьба с магическими кавычками ; functionstripslashes_deep($data); {; if(is_array($data)); $data=array_map("stripslashes_deep",$data);; else  returnstripslashes($data);; } if(get_magic_quotes_gpc()) { $_GET=stripslashes_deep($_GET);; $_POST=stripslashes_deep($_POST);; $_COOKIE=stripslashes_deep($_COOKIE); } #СоединениесMysql $db_irbis=mysql_connect(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD)ordie(NO_CONNECT); define('CONNECT',$db_irbis); #Выборбазы mysql_select_db(MYSQL_DATABASE,CONNECT)ordie(NO_DB_SELECT); ; #Установкапараметровсоединения query('SETNAMESutf8',__FILE__,__LINE__);; query('SETCHARACTERSETutf8',__FILE__,__LINE__); query('SETCOLLATION_CONNECTION="utf8_general_ci"',__FILE__,__LINE__); ?>listiner.php <?php $total="";; functionlist_page($table); {; global$total;; ; $page=!empty($_GET['page'])?$_GET['page']:1;; ; $result=query("SELECTCOUNT(*)AS`cnt` FROM`".PREFIX.$table."`" ,__FILE__,__LINE__); ; $posts=mysql_result($result,0);; $total=intval(($posts-1)/NUM)+1;; $page=intval($page); ; if(empty($page)or$page<0); $page=1; ; if($page>$total); $page=$total; ; $start=$page*NUM-NUM; ; return$start;; }; functionlist_menu($mod=NULL); {; global$total;; $page=!empty($_GET['page'])?$_GET['page']:1;; ; if($mod); $mod='&mod='.$mod; for($i=1;$i<=$total;$i++); {; $for=$i*NUM-NUM+1;; $end=$i*NUM;; ; if($page==$i); $menu.='<b>['.$for.'-'.$end.']</b>';; else; $menu.='<ahref="?page='.$i.$mod.'"">['.$for.'-'.$end.']</a>';; }; return$menu;; } ?>Заметьте, мы передали аргументом в первую функцию название таблицы, а во вторую название модуля. И теперь этот функционал (постраничку) можно использовать не только в гостевой книге, но и при выводе новостей к примеру. Или еще где нибудь. Затем вынесем все служебные слова в языковой файл language/ru.php <?php; define('NO_CONNECT','Произошлаисключительнаяситуация.Сервербазданныхнедоступен. Приносимсвоиизвинения.Попробуйтеповторитьпопыткупозже');; define('LOGIN_ERROR','Текстовоеполенезаполнено.'); define('MESS_ERROR','Текстоваяобластьнезаполнена.'); define('NEW_MESS','Напишитечтонибудь'); ; ; $language=array( 'title'=>'Мойсайт', 'login'=>'Логин:',; 'message'=>'Сообщение:', 'back'=>'Вернутьсянасайт', ); ; ; $string_month=array(; '01'=>'января',; '02'=>'февраля',; '03'=>'марта',; '04'=>'апреля',; '05'=>'мая',; '06'=>'июня',; '07'=>'июля',; '08'=>'августа',; '09'=>'сентября',; '10'=>'октября',; '11'=>'ноября',; '12'=>'декабря'; ); ?>Настройки вынесем в конфигурационный файл, он у нас уже есть в корне config.php <?php #Логин=>Парольдлядоступавадмин-панель; $admins=array(; "root"=>"root",; "Petia"=>"54321"; );; #Выборскина define('SKIN','default'); #Выборязыка define('LANGUAGE','ru'); #Количество сообщений на странице define("NUM",10); #Настройкиподключения define('MYSQL_SERVER','localhost'); define('MYSQL_DATABASE','guest'); define('MYSQL_USER','root'); define('MYSQL_PASSWORD',''); define('PREFIX', 'guest_'); #Путьдоскина; define('SKIN_PATH','http://'.$_SERVER['HTTP_HOST'].'/skins/'.SKIN); ?>А инициализацию переменных в свой - vars.php <?php; #Переключениемодулей $mod=!empty($_GET['mod'])?$_GET['mod']:NULL; #Переключениеразделов $rem=!empty($_GET['rem'])?$_GET['rem']:NULL; #Постраничка; $page=!empty($_GET['page'])?$_GET['page']:NULL; #Форма; $login=!empty($_POST['login'])?$_POST['login']:NULL;; $message=!empty($_POST['message'])?$_POST['message']:NULL; #Удаление; $delet=isset($_POST['delet'])?$_POST['delet']:array(); #Кнопка; $ok=isset($_POST['ok'])?true:false; #Массивошибок $array_error=array(); #Дефолтнаянадпись $default=''; #Переменная сообщений $body_mess=''; #Ключвходавадминку; $key=false; ?>Еще, для полного счастья, в файл .htaccess добавим несколько директив AddDefaultCharsetUTF-8 php_flagmagic_quotes_gpcOff php_flagmagic_quotes_runtimeOff php_flagregister_globalsOff ErrorDocument401/401.html ErrorDocument403/403.html ErrorDocument404/404.htmlЗдесь первая (уже проходили) - кодировка; Вторая и третья - отключаем магические кавычки, что бы при возврате данных в форму небыло лишних бэкслэшей; Четвертая - отключаем глобальные переменные, это не безопасно; Пятая - седьмая - страницы ошибок. Их тоже нужно сделать и положить в корень. Выглядеть они должны как угодно, но что бы было понятно, что юзер ошибся в наборе адреса к примеру. Все ссылки и пути на этих страницах должны быть абсолютными. Вот не мудрствуя лукаво (404.html): <!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/> <title>404</title> </head> <body> <h1>404</h1> </body> </html>Теперь организуем шаблоны. Директория skins/default и в ней два файла header.html <!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/> <title><?phpecho$title;?></title> <linkhref="<?phpechoSKIN_PATH;?>/css/style.css"rel="stylesheet"type="text/css"/> </head> <body> <divclass="content">и footer.html </div> </body> </html>Теперь тут же организуем еще четыре директории - css images js и саму папку для гостевой книги guestbook Как можно уже догадаться, в них мы будем размещать стили, картинки, скрипты и непосредственно шаблоны гостевой книги. Впрочем последний у нас всего один, вот он: show.html <?php echo $default ?> <br/><formaction=""method="post">; <?php echo $language ['login']; ?> <br/>;<inputname="login"type="text"value="<?phpecho$login?>"/><br/>; <?php echo $language ['message']; ?> <br/>;<textareaname="message"cols="40"rows="10"> <?php echo $message; ?> </textarea><br/>; <inputname="ok"type="submit"/>;</form> <spanstyle="color:red"><b> <?php echo $error;?> </b></span><br/> <?phpecho$body_mess;?> <?phpecho$list_menu;?>А теперь самое главное - главный индексный файл. Тот самый диспетчер, который будет переключать модули: index.php <?php; ob_start();; ; #Установкаопределенияошибок; error_reporting(E_ALL&~E_NOTICE); ; #Заголовокскодировкойиконтент-типом header('Content-Type:text/html;charset=utf-8'); ; #Подключаемконфигурационныйфайл include'./config.php'; #Подключаемязыковойфайл include'./language/'.LANGUAGE.'.php'; ; #Подключаемфайлинициализациипеременных include'./vars.php'; #Подключаембазу данных include'./libs/mysql_connect.php'; ; #Подключаемобщиефункции include'./libs/default.php'; #Подключаемшапку include'./skins/'.SKIN.'/header.html'; ; switch($mod) { case'admin': #Подключаемадмин-панель include'./admin/index.php';; break; ; default:; #Подключаеммодульгостевойкниги include'./modules/guestbook/index.php';; break; ; } ; #Подключаемподвал include'./skins/'.SKIN.'/footer.html'; $buffer=ob_get_contents(); ob_end_clean(); echo $buffer; ?> Ну вот, все расставили по полочкам, пора сделать и сам модуль. Шаг 9Продолжаем разговор. В корне у нас есть директория modules, если Вы делали структуру сайта в прошлом разделе. Ну а нет, так сделайте сейчас же. В ней нужно организовать еще один каталог - guestbook. Вот в нем и будет все управление модулем. Сначала индекс модуля, локальный диспетчер. index.php <?php; #Подключаемфункциипостраничного режима include'./libs/listiner.php'; #Контроллердобавлениясообщений; include_once'./modules/guestbook/add_controller.php'; #Контроллерчтениясообщений; include_once'./modules/guestbook/read_controller.php'; #Приводимвыводвпорядок include_once'./modules/guestbook/view.php'; #Подключаемшаблон include_once'./skins/'.SKIN.'/guestbook/show.html'; ?>Затем по порядку. Контроллер добавления сообщений: add_controller.php <?php; ; if($ok); {; if(!$login); {; $array_error[]=LOGIN_ERROR;; }; elseif(!$message); {; $array_error[]=MESS_ERROR;; }; else; {; #Авотинашзапрос.; query("INSERTINTO`".PREFIX."posts`; SET`login`='".mysql_real_escape_string($login)."',; `text`='".mysql_real_escape_string($message)."'"; ,__FILE__,__LINE__);; #ПеренаправлениедлясбросаPOST; header('location:'.$_SERVER['PHP_SELF'].'?rnd='.time());; exit();; }; }; else; {; $default=NEW_MESS;; } ?>Контроллер чтения сообщений read_controller.php <?php $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC  LIMIT". list_page('posts') ."," .NUM ,__FILE__,__LINE__); $count=mysql_num_rows($result); while($row=mysql_fetch_assoc($result)) { if($row['id']==$count) $body_mess.='<spanstyle="color:red" >'; ; $body_mess.='<divclass="header_mess">'. format_date($row['date']) .'/'. htmlspecialchars($row['login']). '</div>'; $text=nl2br(htmlspecialchars($row['text'])); $body_mess.='<divclass="body_mess">'.bb_tag($text).'</div>'; if($row['id']==$count) $body_mess.='</span>'; ; } ?>И файл view.php, в котором мы приведем в порядок переменные вывода: <?php; ; $login=htmlspecialchars($login); $message=htmlspecialchars($message); $error=error_info($array_error); $list_menu=list_menu(); ?> Осталось накрасить губы: cделать верстку шаблона (или нескольких). Вот собственно и всё. Готов модуль. Можно смело ждать хороших отзывов и пожеланий (Сам себя не похвалишь - сидишь как оплеванный). Ну и админка на закуску в следующем разделе. Шаг 10АдминкаНу какая уважающая себя гостевая книга без модерации? Снабдим её админкой. Тем более почти всё для этого уже готово. В корне сделаем еще одну директорию - admin Бытует мнение, что админки нужно маскировать экзотическими именами, но это дело на любителя. Если поставить нормальную защиту, то эта операция и не понадобится вовсе. Вот и сама защита sequrity.php <?php if(empty($_SERVER['PHP_AUTH_USER'])); {; header('WWW-Authenticate:Basicrealm="AdminPage"');; header('HTTP/1.0401Unauthorized');; exit();; }; $key=false; foreach($adminsas$admin=>$password); if($_SERVER['PHP_AUTH_USER']===$admin&&$_SERVER['PHP_AUTH_PW']===$password); $key=true; if(!$key); exit('Нетураздавать.');Как видите, мы не мудрствуя лукаво использовали бэйсик - авторизацию. Обратите внимание на === Это не опечатка, это оператор "строго равно". Он отличается от просто "равно" тем, что не преобразует типы данных. То есть строковые переменные приравнивает только к строковым, а числовые только к числовым. Защита готова. Поместите этот модуль в папку admin в корень сайта Теперь сама админка. Метод POST дает возможность передавать данные массивом. Воспользуемся этим и присвоим им уникальные имена Сделаем отдельный контроллер для админки гостевой книги, нам могут понадобиться и другие контроллеры, что бы управлять всем сайтом. За основу возьмем контроллер чтения и маленько его модернизируем. Метод POST дает возможность передавать данные массивом. Воспользуемся этим и присвоим им нужные имена: guest_controller.php <?php; $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC  LIMIT". list_page('posts') ."," .NUM ,__FILE__,__LINE__); while($row=mysql_fetch_assoc($result)); { ; $body_mess.='<divclass="header_mess"> <inputname="delet['. $row['id']. ']"value="'. $row['id'] .'"type="checkbox"/>' . format_date($row['date']) .'/'. htmlspecialchars($row['user']). '</div>'; $text=nl2br(htmlspecialchars($row['text'])); $body_mess.='<divclass="body_mess">'.bb_tag($text).'</div>'; ; }Ну а теперь нужно удалить отмеченные: if($ok); { $id_arr=isset($_POST['delet']) ? array_map("intval",$_POST['delet']) : array(); query("DELETEFROM`".PREFIX."posts` WHERE`id`IN(".implode(",",$id_arr).")" ,__FILE__,__LINE__); } ?>Оператор DELETE удаляет строку таблицы, указанную в условии WHERE. Так как строк может быть много, используем оператор IN, который позволяет перечислять нужные элемены через запятую.А составить такой список можно собрав в строку элементы массива, используя рвзделитель - запятую. Делает это функция implode() Всё, теперь контроллер админки гостевой книги будет выглядеть так: <?php ; if($ok); { $id_arr=isset($_POST['delet']) ? array_map("intval",$_POST['delet']) : array(); query("DELETEFROM`".PREFIX."posts` WHERE`id`IN(".implode(",",$id_arr).")" ,__FILE__,__LINE__); } $result=query("SELECT*FROM`".PREFIX."posts` ORDERBY`id`DESC  LIMIT". list_page('posts') ."," .NUM ,__FILE__,__LINE__); while($row=mysql_fetch_assoc($result)); { ; $body_mess.='<divclass="header_mess"> <inputname="delet['. $row['id']. ']"value="'. $row['id'] .'"type="checkbox"/>' . format_date($row['date']) .'/'. htmlspecialchars($row['login']). '</div>'; $text=nl2br(htmlspecialchars($row['text'])); $body_mess.='<divclass="body_mess">'.bb_tag($text).'</div>'; ; } ?>Теперь опять приводим все в порядок в файле view.php: <?php; ; $error=error_info($array_error);; $list_menu=list_menu('admin'); ?>и собираем всю конструкцию в индекс админки: <?php include'./admin/sequrity.php'; switch($rem) { case'guestbook': #Подключаемфункциипостраничного режима include'./libs/listiner.php'; #Подключаемконтроллергостевойкниги; include'./admin/guest_controller.php';; break; #Поумолчанию; default: #Подключаемфункциипостраничного режима include'./libs/listiner.php'; #Подключаемконтроллергостевойкниги; include'./admin/guest_controller.php';; break;; } ; include'./admin/view.php'; ; include_once'./skins/'.SKIN.'/admin/guest.html';Теперь в папку со скинами добавим директорию для админки admin, а в неё шаблон guest.html <ahref="index.php?page=<?phpecho$page?>"><?phpecho$language['back'];?></a><br/> <?phpecho$error?> <formaction="?mod=admin&page=<?phpecho$page?>"method="post"> <?phpecho$list_menu;?><br/> <?phpecho$body_mess?><br/> <inputname="ok"type="submit"value="Удалить"/><br/> <?phpecho$list_menu;?> </form> Всё. Теперь нужно набрать в адресной строке примерно следующее: http://my-site.ru/?mod=admin, написать в открывшемся окне логин - пароль, который предварительно указать в конфигурационном файле и смело бороться с флудерами и матершинниками. PS Не забудьте закомментировать строку диагностики в файле коннекта:<?php #ФункциязапросавMySQL; functionquery($sql,$file,$line); {; $res=mysql_query($sql,CONNECT); if($res); {; return$res;; }; else; {; //die('<bstyle="color:red">Musqlerror:</b>'.mysql_error().'<br><b>Query:</b>'.$sql.'<br> <b>File:</b>'.$file.'<br><b>Line:</b>'.$line);; header('location:error.html');; exit;; }; } ?> скопированно с сайта http://irbis-team.ru 6
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||