|
|
|
| Здравствуйте, продолжаю мучаться с HTML Select Multiple:)
Есть форма, которую пользователь заполняет на сайте, в ней он выбирает страны , куда хочет поехать. Надо эти страны записать в MySQL и потом сделать выбор по критерию "hostcountry" по всем пользователям.
Я пытаюсь в MySQL записать страны в поле с типом SET, но у меня не получается.
Саму базу я создаю в MySQL, а структуру таблицы в базе делаю через phpMyAdmin.
<html>
<head>
<title>Страница управления</title>
</head>
<body>
<form method='post' action='insert.php'>
Host countries:
<select multiple="" name="hostcountry[]" size="4">
<option value="1"> Australia </option>
<option value="2"> Austria </option>
<option value="3"> Belgium </option>
<option value="4"> Canada </option>
<option value="5"> Denmark </option>
<option value="6"> Finland </option>
<option value="7"> France </option>
<option value="8"> Germany </option>
<option value="9"> Ireland </option>
<option value="10"> Netherlands</option>
</select>
<input type='submit' value='Добавить запись' />
</body>
</html>
|
PHP скрипт для внесения данных в таблицу я написала такой, но он не работает
<?php
include ('connect.php');
$hostcountry = $_POST["hostcountry"];
foreach ($_POST["hostcountry"] as $keys=>$values) echo "hostcountry:", $values, "<br>"; .//это для отладки, работает
foreach ($_POST["hostcountry"] as $keys=>$values) $sql ='INSERT INTO members(hostcountry) $values'; // это не работает
if(!mysql_query($sql))
{echo '<center><p><b>Ошибка при добавлении данных!</b></p></center>';}// это и выдается
else
{echo '<center><p><b>Данные добавлены!</b></p></center>';}
?>
|
Соединение с базой в скрипте 'connect.php' работает.
Кажется, распростаннная задача записать данные в тип SET, но почему-то нигде не могу найти, как это сделать. Может быть кто-то поможет?
С уважением
danga | |
|
|
|
|
|
|
|
для: danga
(23.10.2013 в 11:33)
| | Попробуйте так:
<?php
$hostcountry = array_map('trim', $_POST["hostcountry"]);
// это для отладки
print "<pre>";
print_r($hostcountry);
print "</pre>";
// это не для отладки
$values = mysql_real_escape_string(implode(',', $hostcountry));
$sql = "INSERT INTO members(hostcountry) VALUES('$values')";
// это для отладки
echo $sql . '<br>';
|
Данные для записи в тип SET должны быть перечислены через запятую как одно значение http://dev.mysql.com/doc/refman/5.0/en/set.html + вспоминаем правильный синтаксис команды INSERT | |
|
|
|
|
|
|
|
для: danga
(23.10.2013 в 11:33)
| | А вам точно тип SET подходит?
Он не может содержать более 64 вариантов значений.
Стран, на сколько я знаю, несколько больше..... | |
|
|
|
|
|
|
|
для: Sfinks
(23.10.2013 в 19:16)
| | Да, вот именно. А какой может быть другой вариант? Я уже думала сделать отдельную таблицу для стран, в которой каждый столбец-новая страна. Но тогда столбцов будет очень много. | |
|
|
|
|
|
|
|
для: danga
(23.10.2013 в 20:01)
| | Не столбец, а строка. А столбцы, это идентификатор, имя и прочие параметры страны. | |
|
|
|
|
|
|
|
для: danga
(23.10.2013 в 20:01)
| | Это решается использованием 3х таблиц вместо одной.
Таблица 1 - пользователи (id, name, login, pass, и т.д.)
Таблица 2 - страны (id, name)
Таблица 3 - связь пользователя со странами (user_id, country_id). И каждая строка этой таблицы - Связь одного пользователя с одной страной:
user_id | country_id
--------------------
1 | 10
1 | 15
1 | 164
2 | 34
2 | 12
3 | 10
4 | 252
4 | 11
|
| |
|
|
|
|
|
|
|
для: Sfinks
(25.10.2013 в 07:55)
| | Спасибо! Это проще и понятнее, чем с типом SET. | |
|
|
|
|
|
|
|
для: danga
(25.10.2013 в 19:22)
| | Здравствуйте.
Спасибо большое еще раз за совет, но я наверное такая бестолковая, что все равно не могу решить задачу до конца. В таблице 3 у меня никак не получается сделать несколько строк для одного пользователя.В лучшем случае получается только одна строка по последнему выбранному значению. Я пыталась сделать несколькими способами, и через цикл и с использованием ON DUPLICATE KEY UPDATE в разных комбинациях, наконец все собрала в одном скрипте - эффект тот же.
Вот этот вариант - выдает в таблицу только одно последнее из выбранных значений.
$hostcountry[] = $_POST["hostcountry"];
foreach ($_POST["hostcountry"] as $keys=>$values) {
$sql = 'INSERT INTO hostcountries(name, idcountry)
VALUES("'.$name.'", "'.$values."') ON DUPLICATE KEY UPDATE idcountry=idcountry+1';
|
А этот вообще выдает ошибку.
$hostcountry = array_map('trim', $_POST["hostcountry"]);
$sql = 'INSERT INTO hostcountries(name, idcountry)
VALUES("'.$name.'", '.$values.')
ON DUPLICATE KEY UPDATE idcountry=idcountry+1';
|
А уж как прилепить в эту таблицу user_id из первой таблицы внутри одной операции ввода - это вообще для меня загадка. Мне надо это динамическую форму регистрации добавить на готовый и работающий статический сайт. Помогите пожалуйста. | |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 13:19)
| | У вас похоже не правильная структура таблицы.
Выполните и покажите результат запроса:
SHOW CREATE TABLE hostcountries
|
Тоже самое по двум остальным таблицам.
Плюс покажите саму HTML форму и ее пхп-обработчик.
Тогда можно будет что-то сказать.
> А уж как прилепить в эту таблицу user_id из первой таблицы внутри одной операции ввода - это
> вообще для меня загадка. Мне надо это динамическую форму регистрации добавить на готовый
> и работающий статический сайт. Помогите пожалуйста.
Вот этого я вообще не понял. сайт или статический, т.е. состоит из html-файлов, или он динамический, пользуется базой данных и формирует страницы пхп-скриптами. | |
|
|
|
|
|
|
|
для: Sfinks
(27.10.2013 в 13:44)
| | Изначально я сделала сайт статический ( полностью html), но в нем есть форма регистрации, которую мне пользователи присылают на е-майл. А теперь я хочу сделать, чтобы пользовательские анкеты с фотографиями записывалось в базу, и потом пользователи могли бы выбирать из нее анкеты по критериям и редактировать и удалять свои собственные анкеты. Это вообще мой первый и единственный пока сайт:))) | |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 18:51)
| | Это конечно не вся анкета, а тест для отладки. Мне осталось научиться записывать и выводить потом из базы фотографии и массивы Select Multiple, все остальное у меня уже получаестя.
Вот такая тестовая HTML форма
<html>
<head>
<title>Страница управления</title>
</head>
<body>
<form enctype="multipart/form-data" method='post' action='insert.php'>
Name: <input type='text' size='30' name='name'><br>
Famale: <input type='text' size='30' name='surname'><br>
E-mail: <input type='text' size=30 name='email'><br>
Gender:
<input type = "radio" name = "gender" value = "m"> male
<input type = "radio" name = "gender" value = "f" checked> female
<br>
Host countries:
<select multiple="" name="hostcountry[]" size="4">
<option value="1"> Australia </option>
<option value="2"> Austria </option>
<option value="3"> Belgium </option>
<option value="4"> Canada </option>
<option value="5"> Denmark </option>
<option value="6"> Finland </option>
<option value="7"> France </option>
<option value="8"> Germany </option>
<option value="9"> Ireland </option>
<option value="10"> Netherlands</option>
</select>
<br>
Add photo:<br>
<input type="file" name="photo" multiple accept="image/*,image/jpeg">
<br>
<input type='submit' value='Submit' />
</body>
</html>
|
| |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 19:08)
| | Проверки на корректоность ввода делаются скриптами JavaScript И PHP, там все нормально. Осталось записать в базу MySQL все до конца.
Для отладки я закачала Apache2.2, MySQL Server5.1, PHP и phpMyAdmin. Базу данных test я сделала в MySQL, а таблицы в phpMyAdmin.
Сейчас у меня 4 таблицы:
1. members
Column Type Collation Attributes Null Default Extra
idaupair int(11) UNSIGNED No None AUTO_INCREMENT
name varchar(30) cp1251_general_ci No None
surname varchar(30) cp1251_general_ci No None
email varchar(30) cp1251_general_ci No None
gender enum('m', 'f') cp1251_general_ci No None
hosrcountry set('1','2','3','4','5','6','7','8','9','10') Yes None
2.hostcountries
idaupair int(11) UNSIGNED No None AUTO_INCREMENT
name varchar(30) cp1251_general_ci No None
idcountry int(3) No None
3. countries
idcountry int(3) UNSIGNED No None AUTO_INCREMENT
country varchar(30) cp1251_general_ci No None
4. photos
idaupair int(11) UNSIGNED No None AUTO_INCREMENT
photo blob BINARY No None
name varchar(30) cp1251_general_ci No None | |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 20:33)
| | В таблице members столбец hostcountry с типом SET отключен, потому что я не знаю как туда записать массив и сейчас пытаюсь эти данные записать в другую таблицу - hostcountries. Но у меня тоже не получается записать туда несколько строк для одного человека.
Последний вариант скрипта такой, он выдает ошибку придобавлении данных:
<?php
include ('connect.php');
$name = $_POST['name'];
$surname = $_POST['surname'];
$email = $_POST['email'];
$gender = $_POST['gender'];
$sql = 'INSERT INTO members(name, surname, email, gender, hostcountry)
VALUES("'.$name.'", "'.$surname.'","'.$email.'", "'.$gender.'", '.$values.')';
$hostcountry = array_map('trim', $_POST["hostcountry"]);
for ($i=0; $i<count($hostcountry); $i++) {
$sql = 'INSERT INTO hostcountries(name, idcountry)
VALUES("'.$name.'", "'.$values.'")';
}
if(!mysql_query($sql))
{echo '<center><p><b>Ошибка при добавлении данных!</b></p></center>';}
else
{echo '<center><p><b>Данные добавлены!</b></p></center>';}
?>
<?php
]
|
| |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 20:53)
| |
<?php
//обязательно экранировать нужно строковые данные
//перед занесением их в базу
$name = isset($_POST['name']) ? mysql_real_escape_string($_POST['name']) : null;
$surname = isset($_POST['surname']) ? mysql_real_escape_string($_POST['surname']) : null;
$email = isset($_POST['email']) ? mysql_real_escape_string($_POST['email']) : null;
$gender = isset($_POST['gender']) ? mysql_real_escape_string($_POST['gender']) : null;
//а значения списка числа, поэтому их можно приводить к типу integer
$hostcountry = array_map('intval', $_POST["hostcountry"]);
//но помнится, что уже еж говорил об этом, о проверке
//и делать надо так:
$hostcountry = array_diff(array_map('intval', $_POST["hostcountry"]), array(0));
//если все данные присутствуют
if($name && $surname && $email && $gender && $hostcountry) {
$sql = 'INSERT INTO members (name, surname, email, gender, hostcountry)
VALUES("'.$name.'", "'.$surname.'","'.$email.'", "'.$gender.'", '.$values.')'; //что за $values ?
//пишем в базу, и пока не запишем удачно это никаких запросов, так как читайте ниже
if(mysql_query($sql)) {
//второй запрос надо полагать как то связан с первым, то есть таблицы
//members и hostcountries связаны
//а значит эта связь должна быть указана во второй таблице
//и скорее всего она у вас (если только вы не забыли этого сделать)
//по идентификатору пользователя, поле которого в таблице должно быть
//первичным ключом с авто инкрементом
//то есть перед занесением в базу данных о пользователе, мы этого
//идентификатора еще не знаем, и только после успешной записи первого запроса
//получаем этот идентификатор так:
$id = mysql_insert_id();
//вот теперь можно подготавливать второй запрос и делать его
//но много-строчной записью, всего одним запросом к базе
$sql = 'INSERT INTO hostcountries (name, idcountry) VALUES ';
foreach($hostcountry as $v) $sql .= '('.$id.',"'.$name.'",'.$v.'),';
//хотя значение $name в этой таблице совсем не нужно, обращаться к ней
//вы будете при выборке из первой, а в ней есть имя
//в этой же таблице нужно идентификатор пользователя и значения которые он выбрал
//ну и завершающий запрос
echo mysql_query(rtrim($sql,',')) ? '<center><p><b>Данные добавлены!</b></p></center>'
: '<center><p><b>Ошибка при добавлении данных!</b></p></center>';
} else echo '<center><p><b>Ошибка при добавлении данных!</b></p></center>';
//вот так, иначе нет смысла в несвязанных таблицах
//вы же потом из них ничего не получите
} else {
//ошибка, не заполнены данные, возвращаем форму для заполнения
}
|
Всегда форматируйте код свой, делая в нем отступы, если ваш редактор сам этого не умеет делать иначе очень сложно в нем разбираться будет и вам самой.
Применение устаревшего тега center осуждается, хотя небо конечно не рухнет, но выше у вас форма с полем выбора файла позволяющего делать выбор нескольких файлов одним полем (type=file multiple), а это возможно только в современных браузерах, и как-то не вяжется center с этим. ) | |
|
|
|
|
|
|
|
для: danga
(27.10.2013 в 20:33)
| |
SHOW CREATE TABLE hostcountries
| Должен выглядеть примерно так:
CREATE TABLE `hostcountries` (
`idaupair` int(10) unsigned NOT NULL,
`idcountry` int(3) unsigned NOT NULL,
PRIMARY KEY (`idaupair`,`idcountry`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
| Тогда можно будет добавить несколько строк для одного пользователя.
В остальном confirm ответил, за исключением того, что вот это:
<?
$sql = 'INSERT INTO hostcountries (name, idcountry) VALUES ';
foreach($hostcountry as $v) $sql .= '('.$id.',"'.$name.'",'.$v.'),';
echo mysql_query(rtrim($sql,',')) ? '<center><p><b>Данные добавлены!</b></p></center>'
: '<center><p><b>Ошибка при добавлении данных!</b></p></center>';
| я бы записал так:
<?
if($hostcountry){
$sql = "INSERT INTO hostcountries (idaupair, idcountry) VALUES ($id,".implode("),($id,", $hostcountry).")";
echo mysql_query($sql) ? '<center><p><b>Данные добавлены!</b></p></center>'
: '<center><p><b>Ошибка при добавлении данных!</b></p></center>';
}
| Не люблю циклы. | |
|
|
|
|
|
|
|
для: Sfinks
(28.10.2013 в 08:50)
| | Sfinks и Confirm! Спасибо большое за помощь! очень приятно, что есть добрые и умные люди, кто может помочь. Скрипт Confirma в исходном варианте не работает, хотя я добавила в таблицы ключ PRIMARY KEY по столбцу idaupair. Правда, я его добавила в две таблицы - и в members и в hostcountries. Может это не правильно? Читаю сейчас документацию по MySQL, но что-то я плохо воспринимаю. Нужна практика, за неделю эту науку не постичь... Ну ладно, буду дальше разбираться:))) | |
|
|
|
|
|
|
|
для: danga
(29.10.2013 в 00:43)
| | Я вам не код дал, а ваше писанное исправил, хотя в вашем писанном явные ошибки, имеется ввиду ссылки на данные. Поэтому и не работает.
Из того что я написал, вам главное, это понять, что я вам уже не первый раз говорю:
1) необходима обязательная проверка данных приходящих извне;
2) экранирование или приведение к типу данных перед занесением их или при использовании их при обращении к базе.
Два этих важных пункта и выполняют первые пять строк кода, а заодно и проверяют пришли ли данные, хотя если вообще полностью, с применением условной записи (тернарного оператора), должно быть так:
<?
//для строковых значений
$var_1 = isset($_POST['var_1']) ? mysql_real_escape_string(trim($_POST['var_1'])) : null;
//для числовых значений
$var_2 = isset($_POST['var_2']) ? (int)$_POST['var_2'] : null;
|
Такая запись удобна тем, что возвращая форму пользователю при ошибках ввода, в поля ее можно вернуть уже введенные пользователем данные:
<input name=var_1 value="<?=htmlspecialchars($var_1)?>" />
<input name=var_2 value=<?=$var_2?> />
|
И обязательно обезопасить вывод при выводе строковых значений в браузер - htmlspecialchars(). И применяя такое у себя, вы должны знать, что такая вставка php-переменных в html-код, без конструкции echo, возможна только в том случае, если у вас разрешены короткие РНР теги. Если это не так, то разрешите/включите их, это очень удобно.
Все что выше, это элементарные правила, которые вы просто обязаны выполнять при работе с данными извне.
Сам прием данных описанный выше не будет удобен, в смысле не удобна такая проверка и не возможно проверить все, если данных много, и они представляют собой массив с вложениями, да если еще отключены "магические кавычки" (а это лучше сделать). В этом случае удалить экранирование данных пользователем, убрать крайние пробелы, и если не предвидится возврат данных пользователю, то сразу произвести и экранирование (mysql_real_escape_string), можно так:
<?
//этот код вернет массив $_POST с обработанными указанным способом данными
//готовыми для дальнейшего использования их при работе с базой
array_walk_recursive($_POST, function(&$v) {
//здесь можно вообще произвести более сложные проверки входных данных,
//как например, в зависимости от типа ожидаемых данных
//сразу приводить их к этому типу
$v = mysql_real_escape_string(trim(stripslashes($v)));
});
//используя этот код, необходимо знать, что он будет работать только в версии РНР не ниже 5.3
//так как вместо вызова callback-функции используется замыкание
|
PRIMARY KEY которое прописал Sfinks не определяет, что код который я написал, должен обязательно стать рабочим (еще раз говорю, это только исправление вами писанного так, как должно быть "по уму"), это просто применение ключа к полям таблицы, которые нужны для того, чтобы MySQL оптимальнее выполняла свои запросы. Кроме этого он пишет, но не объясняет, что лучше использовать implode(). Это так, легко превратить массив в строку, и даже не просто превратить, а сразу и обработать данные этого массива, например, тоже экранирование их и обрамление кавычками перед записью в базу:
<?
$string = '"' . implode('","', array_map('mysql_real_escape_string', $array)) . '"';
|
Но нужно знать, что таким образом можно поступить только с одномерным массивом, и с подстановкой не изменяющихся переменных (в его примере это идентификатор полученный после первой записи в базу), но нельзя таким способом превратить в строку данные из разных массивов.
Если вы поняли уже, что такое связанные таблицы и как они связываются (на основе чего), то вся блок схема кода простая:
1. получить данные и проверить их
2. если все обязательные данные получены и они корректные, то запись в базу основных данных (первая таблица)
3. если основных данные записались в базу, то получить идентификатор записи в базу
4. подготовить данные для записи во вторую таблицу
5. записать данные во вторую таблицу связывая их с первой по полученному идентификатору
(здесь надо отметить, что "ждать идентификатор" от записи в первую таблицу, чтобы произвести запись во вторую, это не всегда обязательное условие записи данных в связанные таблицы, но в вашем случае, это именно обязательное условие)
а) в шаге 3 и 5, если произошла ошибка при записи в базу, то вывести сообщение
6. если в шаге 1 ошибка с данными от пользователя (не все получены, или введены некорректно), а также, если массив $_POST пуст (первое обращение к странице), то возвращаем форму пользователю | |
|
|
|
|
|
|
|
для: confirm
(29.10.2013 в 06:52)
| | > Кроме этого он пишет, но не объясняет, что лучше использовать implode().
К сожалению, на такую развернутую лекцию у меня ушло бы минимум часа 2, а-то и 3. Поэтому да, мои ответы чаще всего несколько обрывочны. Спасибо, что дополняете =)
Для danga:
> хотя я добавила в таблицы ключ PRIMARY KEY по столбцу idaupair. Правда, я его добавила в две таблицы - и в members и в hostcountries
Вы не поняли.
В таблице members должен быть первичный ключ по ID мембера.
В таблице countries - по ID страны.
А в таблице соответствий hostcountries - должен быть составной первичный ключ, сразу по двум полям ID мембера и ID страны:
PRIMARY KEY (`idaupair`,`idcountry`)
| Тогда можно будет для каждого ID мембера добавить несколько строк с разными ID страны. | |
|
|
|
|