База данных PMA и PHP-сайт (Денвер)
Вложений: 2
Здравствуйте еще раз! Я пытаюсь решить это - правильно (конкретно для базы данных и ее кодировки) вывести в PHP таблицу с данными, затем организовать с этим же PHP их добавление и удаление по полям ввода (для добавления - вводить все данные для полей, для удаления - лишь id поля).
Как примерно сейчас выглядит БД на PMA показано ниже. Я надеюсь, что здесь все в порядке, хотя если что будет не так - я слушаю. Разрешение постаралась сделать как можно больше - вроде все видно. А вот с кодом все сложнее, конечно - как уже упоминалось выше, все данные из базы данных вывелись нормально, в кодировке utf-8 BOM, но когда я пытаюсь добавить записи через форму PHP на русском в БД - весь текст деформируется. Советовали изменить AddDefaultCharset или другие кодировки попробовать - лучше не становилось, к сожалению. Я думала, может смена кодировки для текстовых полей в базе данных как-то поможет, но, я так понимаю, что все-таки надо разбираться именно в php. Удаление вообще не работало, поэтому я его убрала. Денвер в целом очень часто жалуется на все mysql-и в коде, и я пыталась их менять по-разному, но в итоге пришлось оставить, как есть, на данный момент. Вот такие коды: Основная страница с таблицей и кнопками: <meta http-equiv="content-type" content="text/php; charset=utf-8" /> <?php echo "<h1>Создание базы данных</h1><br>"; echo "<table border=1><tr align=center><td width=10%><b>Номер</td><td width=30%><b>Название</td><td width=20%><b>Цена</td><td width=20%><b>Количество</td><td width=20%><b>Примечание</td></tr>"; $sqlhost="localhost"; $sqluser="homeuser"; $sqlpass=""; $bd="TOVAR"; mysql_connect($sqlhost,$sqluser,$sqlpass) or die ("нет доступа!".mysql_error()); mysql_query("SET NAMES utf8"); mysql_select_db($bd) or die ("нет соединения".mysql_error()); $zap="SELECT * FROM tov ORDER BY id"; $zap_res=mysql_query($zap); while (list($id, $name, $cost, $kol, $prim)=mysql_fetch_row($zap_res)) { echo "<tr> <td>$id</td> <td>$name</td> <td> $cost</td> <td>$kol</td> <td>$prim</td> </tr>"; } echo "</table>"; ?> </br> <form action="add.php" method="POST"> <input type="submit" value="Добавить данные"> </form> <form method="GET"> <input type="submit" value="Удалить запись"> <input type="text" name="id"> </form> Форма для добавления записи: <html> <head> <meta charset="utf-8"> <title>Add</title> </head> <body> <?php if(isset($_POST['id']) && isset($_POST['name']) && isset($_POST['cost']) && isset($_POST['kol']) && isset($_POST['prim'])){ $sqlhost="localhost"; $sqluser="homeuser"; $sqlpass=""; $bd="TOVAR"; $link = mysqli_connect($sqlhost, $sqluser, $sqlpass, $bd) or die("Ошибка " . mysqli_error($link)); $id = htmlentities(mysqli_real_escape_string($link, $_POST['id'])); $name = htmlentities(mysqli_real_escape_string($link, $_POST['name'])); $cost = htmlentities(mysqli_real_escape_string($link, $_POST['cost'])); $kol = htmlentities(mysqli_real_escape_string($link, $_POST['kol'])); $prim = htmlentities(mysqli_real_escape_string($link, $_POST['prim'])); $query ="INSERT INTO tov VALUES('$id', '$name','$cost', '$kol', '$prim')"; $result = mysqli_query($link, $query) or die("Ошибка " . mysqli_error($link)); if($result) { echo "Данные добавлены"; } mysqli_close($link); } ?> <h2>Введите данные для новой записи в базе данных</h2> <form method="POST"> <p>Номер: <br> <input type="text" name="id" /> </p> <p>Назание: <br> <input type="text" name="name" /> </p> <p>Цена: <br> <input type="text" name="cost" /> </p> <p>Количество: <br> <input type="text" name="kol" /> </p> <p>Примечание: <br> <input type="text" name="prim" /> </p> <input type="submit" value="Добавить запись"> </form> </body> </html> Простите за общую неказистость - я раньше вообще никогда не работала с БД в таком плане. Как всегда, заранее спасибо за ваше внимание к моей проблеме. Из местной поддержки многое выучила. |
Выбрасывайте Денвер, он давно умер, установите вместо него Open Server.
1) В коде нет создания базы, она уже вас создана, а здесь вы заполняете ее таблицу. Создавая базу, сразу указывайте кодировку (при создании таблицы также можно указывать кодировку ее полей). 2) Вместо mysqli_real_escape_string используйте подготовленные запросы и псевдопеременные. 3) При записи в базу не стоит пропускать данные через функцию htmlspecialchars, а тем более через htmlentities. Подумайте и попробуйте ответить сами - почему? or die("Ошибка " . mysqli_error($link)); - такое только в режиме отладки показывать надо. |
Цитата:
Цитата:
Мне не совсем это нужно. Мне надо, чтобы добавление и удаление здесь заработало. Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Здесь дамп тестовой таблицы, можете ее импортировать, запустить этот код и все будет работать. Создавая в РМА таблицу, нужно правильно задать и кодировку сравнения, почитать тут. У вас просто путаница. Стоит только заметить, проверки входных данных нет, это просто легкий пример. На самом же деле вы обязаны их проверять, для этого в РНР есть фильтры. <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> </head> <body> <h4>Структура таблицы Сотрудники</h4> <pre>-- -- Структура таблицы `employees` -- CREATE TABLE `employees` ( `id` int(11) NOT NULL COMMENT 'Идентификатор', `surname` varchar(32) NOT NULL COMMENT 'Фамилия', `name` varchar(12) NOT NULL COMMENT 'Имя', `post` varchar(24) NOT NULL COMMENT 'Должность' ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Сотрудники'; -- -- Индексы таблицы `employees` -- ALTER TABLE `employees` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT для таблицы `employees` -- ALTER TABLE `employees` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Идентификатор'; COMMIT;</pre> <h4>Содержание таблицы Сотрудники</h4> <? $db = new mysqli('localhost', 'root', '', 'test'); $db->set_charset("utf8"); if($_POST) { if(isset($_POST['add'])) { if($q = $db->prepare("INSERT INTO `employees` (`surname`, `name`, `post`) VALUES (?, ?, ?)")) { $q->bind_param("sss", $_POST['surname'], $_POST['name'], $_POST['post']); $q->execute(); } } if(isset($_POST['del']) && $id = (int)$_POST['del']) $db->query("DELETE FROM `employees` WHERE id=$id"); } if($q = $db->query("SELECT * FROM `employees`")) { if($q->num_rows) { ?> <form method="post"> <table> <tr><th>Фамилия</th><th>Имя</th><th>Должность</th><th>Удаление</th></tr> <? while($row = $q->fetch_row()) echo '<tr><td>' . implode('</td><td>',array_map('htmlspecialchars', array_slice($row, 1))) . "</td><td><button type=\"submit\" name=\"del\" value=\"$row[0]\">Удалить</button></td></tr>"; ?> </table> </form> <? } else echo '<p>Таблица Сотрудники не имеет записей</p>'; ?> <h4>Добавление сотрудников</h4> <form method="post"> <input name="surname" required="" pattern="[а-яёА-ЯЁ-]{5,32}" placeholder="Фамилия" /> <input name="name" required="" pattern="[а-яёА-ЯЁ]{4,12}" placeholder="Имя" /> <input name="post" required="" pattern="[а-яёА-ЯЁ]{5,24}" placeholder="Должность" /> <button name="add">Добавить</button> </form> <? } else echo 'xxxx'; $db->close(); ?> PS. В структуре вашего кода есть один "очень неприятный сюрприз". Я в примере тоже таковой "оставил сознательно". Большой плюс для вас будет, если вы поймете о каком "сюрпризе" речь. Подсказка - поставить себя на место пользователя, вспомнить о своих возможных действиях на странице. |
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
То что выше запустить, отправить форму, а затем нажать F5. Если на запрос браузера "Повторить" ответить утвердительно, то в базе появится дубликат предыдущей записи. Это и есть "неприятность", которая может возникнуть при отправлении формы естественным путем, при асинхронном обмене данными между сервером и клиентом такой проблемы не возникает. Не пытайтесь защитится очищением массива $_POST, ибо это браузер повторную отправку производит, а не сервер сам себе шлет данные. Один из способов избежать дубликатов, это сделать перенаправление после приема формы. Здесь перенаправление производится "на саму себя", то есть на ту же самую страницу. Если при приеме формы были обнаружены ошибки заполнения, то нужно сохранить пришедшие данные, чтобы заполнить ими форму, негоже заставлять пользователя вводить все заново. Хранить эти данные, а также информацию какие поля с ошибками заполнены, можно в сессии. Старт/обновление сессии, а также перенаправление, это передача в браузер заголовков, а вывод заголовков должен производиться до любого вывода в браузер. По этой причине прием и обработка формы определена в самом начале кода страницы (работая с UTF, имея кодировку эту же и на странице, нужно сохранять и код страницы в UTF, и обязательно без BOM, так как он станет причиной ошибки, ибо будет выводится до заголовков). Хотя можно буферизировать вывод данных до поры до времени, но в данном случае представленная структура проще. <? //стартуем/продолжаем сессию session_start(); $db = new mysqli('localhost', 'root', '', 'test'); $db->set_charset("utf8"); //опции фильтра проверки полей формы //объявление массивов под версию PHP >= 5.4 //если будет ниже, будут "маты" $args = [ 'surname' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => "/^[а-яё-]{5,32}$/iu"] ], 'name' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => "/^[а-яё]{4,12}$/iu"] ], 'post' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => "/^[а-яё]{5,24}$/iu"] ] ]; //параметры полей формы $fields = [ 'surname' => ['label' => 'Фамилия', 'reg' => '^[а-яёА-ЯЁ-]{5,32}$'], 'name' => ['label' => 'Имя', 'reg' => '^[а-яёА-ЯЁ]{4,12}$'], 'post' => ['label' => 'Должность', 'reg' => '^[а-яёА-ЯЁ]{5,24}$'] ]; //если запрос формы, массив $_POST не пуст if($_POST) { if(isset($_POST['add'])) { //добавление сотрудника? //получаем данные формы, удаляя крайние пробелы у значений $post = array_map('trim', array_slice($_POST, 0, -1)); //фильтруем данные формы if(!$error = array_filter(filter_var_array($post, $args), function($v) {return !$v;})) { //если проверка фильтрами не вернула пустых значений, все Ок, то пишем в базу //подготавливаем запрос, экранированием займется драйвер $q = $db->prepare("INSERT INTO `employees` (`surname`, `name`, `post`) VALUES (?, ?, ?)"); //привязываем переменные (метки) к данным формы $q->bind_param("sss", $post['surname'], $post['name'], $post['post']); //выполняем запрос $q->execute(); } else $_SESSION['error'] = ['key' => $error, 'post' => array_map('htmlspecialchars', $post)]; //есть ошибки заполнения формы, сохраняем ключи полей с ошибками и данные формы } //запрос на удаление? if(isset($_POST['del']) && $id = (int)$_POST['del']) $db->query("DELETE FROM `employees` WHERE id=$id"); //если id не 0, выполняем запрос $db->close(); //защита от F5 - сброс POST header('Location: ' . $_SERVER["PHP_SELF"]); exit; } ?> <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> </head> <body> <? //выборка из таблицы if($q = $db->query("SELECT * FROM `employees`")) { if($q->num_rows) { //есть записи, выводим в таблице с возможностью их удаления ?> <h4>Содержание таблицы Сотрудники</h4> <form method="post"> <table> <tr><th>Фамилия</th><th>Имя</th><th>Должность</th><th>Удаление</th></tr> <? while($row = $q->fetch_row()) echo '<tr><td>' . implode('</td><td>',array_map('htmlspecialchars', array_slice($row, 1))) . "</td><td><button type=\"submit\" name=\"del\" value=\"$row[0]\">Удалить</button></td></tr>"; ?> </table> </form> <? } else echo '<p>Таблица Сотрудники не имеет записей</p>'; ?> <h4>Добавление сотрудников</h4> <!-- Если были ошибки заполнения полей формы, выводим имена этих полей Версия РНР должна быть не ниже 5.5.0, иначе будет ругаться на функцию array_column --> <p><?=$_SESSION['error'] ? 'Ошибки заполнения полей: ' . implode(', ', array_column(array_intersect_key($fields, $_SESSION['error']['key']), 'label')) . '!' : null?></p> <form method="post"> <? //выводим форму добавления сотрудников, если были ошибки при приеме формы, заполняем поля пришедшими значениями foreach($fields as $k=>$v): ?> <input name="<?=$k?>" required="" pattern="<?=$v['reg']?>" placeholder="<?=$v['label']?>" value="<?=$_SESSION['error']['post'][$k]?>" /> <? endforeach ?> <button name="add">Добавить</button> </form> <? } else echo 'Ошибка'; //удаляем сохраненные в сессии ошибки unset($_SESSION['error']); $db->close(); ?> </body> </html> При выводе в браузер (и только при нем), данные формы возвращаемые клиенту, а также данные из базы обрабатываются функцией htmlspecialchars(), дабы избежать XSS атак на клиенте, и прочих неприятностей. При записи в базу этого делать не стоит. |
Если по кодировкам у вас не получается то гляньте тут.
Еще бы я обратил внимание как вы добавляете новую запись, обычно id автоматом проставляется базой, через auto_increment. mysql_ расширение вы имеете полное право использовать, если древняя версия php. Но если новая, то или mysqli_ или pdo. Про проблему редиректа сказали выше. |
Цитата:
Цитата:
Цитата:
Цитата:
Спасибо большое снова - вы мне много чего из этого дали понять. |
Цитата:
И потом, ваш код может еще быть как "проба пера", но в реальности такое представить сложно. |
Часовой пояс GMT +3, время: 15:37. |