LINUX.ORG.RU

Начал учить php и тут же есть вопросы

 , ,


0

1

Начал недавно учить PHP. Вроде ничего сложного. В интернете почитал, что для доступа к БД лучше не использовать mysql_*, а лучше PDO. И правильно.

Для тренировки решил сделать простую страничку для работы с БД - просто вводишь имя, страну и телефон, жмешь сабмит и скрипт должен самому себе отправить данные, обработать, записать в БД, считать их и вывести обновленные сведения, включая только что введенные. Вот как у меня получилось:

<?php
$lang="UK";


########## Підключаємось до БД ##################
$db_host='localhost';
$db_name='1';
$db_user='admin';
$db_pass='100500';

try {
	$db = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
	$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}

catch(PDOException $e) {
	print "Помилка під’єднання до сервера БД";
    echo $e->getMessage();
    exit;
}

$q = $db->query('SELECT * FROM users');
$q->setFetchMode(PDO::FETCH_ASSOC);

?>

<table border="1">

	<tr>
		<td width="20%">Звуть</td>
		<td width="20%">Років</td>
		<td width="20%">Країна</td>
		<td width="20%">Місто</td>
		<td>Телефон</td>
	</tr>

<?
while ($row = $q->fetch()) {
	$year=date('Y') - $row[YEAR];
	print "
	<tr>
		<td>$row[NAME]</td>
		<td>$year</td>
		<td>$row[COUNTRY_ID]</td>
		<td>$row[CITY_ID]</td>
		<td>$row[PHONE]</td>
	</tr>";
}
?>
</table><br />
<h1 class="h1_head">Додати данні:</h1>
<?
print "
<form action='{$_SERVER['PHP_SELF']}' method='POST'>
<table>
	<tr>
		<td>Ім’я:</td>
		<td><input type='text' name='NAME' maxlength='15' value='$value'></td>
	</tr>

	<tr>
		<td>Рік народження:</td>
		<td>
			<select name='YEAR'>";
		for ($i = 1960; $i <= 2004; $i++)
			print "<option>$i</option>";
print "			</select></td>
	</tr>

	<tr>
		<td>Стать:</td>
		<td><select name='SEX'>
			<option>Чоловік</option>
			<option>Жінка</option>
		</td>
	</tr>

	<tr>
		<td>Країна:</td>
		<td><select name='COUNTRY'>";

$q = $db->query('SELECT * FROM countries');
$q->setFetchMode(PDO::FETCH_ASSOC);

while ($countrie = $q->fetch()) {
	print "
	<option>
		$countrie[NAME_RU]
	</option>
	";
}
		
print "</select>
</td>
	</tr>
	<tr>
		<td>Номер:</td>
		<td><input type='text' name='PHONE' maxlength='10' value='$value'></td>
	</tr>

	<tr>
		<td>Послання світу<br />(не більше 200 символів):</td>
		<td><textarea rows=\"4\" maxlength=\"200\"></textarea></td>
	</tr>

	<tr>
		<td></td>
		<td>
			<input type='submit' maxlength='15' class='btn btn-primary btn-large' value='Надіслати!'>
		</td>
	</tr>
</table>

</form>

";



############# Обробка масиву GET ###############

//$db->lastInsertId();


if (!isset($_POST['NAME']) or !isset($_POST['SEX']) or !isset($_POST['PHONE']) or !isset($_POST['PHONE']) or !isset($_POST['YEAR'])){
	print "Помилка! Перевірте, чи всі поля заповнено та спробуйте ще раз!";
	} else {
		$num = $db->exec("INSERT INTO users ( ID, NAME, SEX, PHONE, CITY_ID, YEAR, COUNTRY_ID ) values ( '', '$_POST[NAME]', '$_POST[SEX]', '$_POST[PHONE]', '', '$_POST[YEAR]', ''  )");  
		
print "
<div class=\"alert alert-success\">
  <button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>
  <h4>Готово!</h4>
</div>
";
		
}

?>


<? $db = null; ?>
</body>
</html>
Не понимаю, как реализовать проверку ввода данных - если данных в $_POST нету, то выводить сообщение. Проверка через isset срабатывает сразу после первой загрузки, что и логично. Что тут можно придумать? Второй вопрос - $db->lastInsertId(); у меня всегда выводит 0. ЧЯДНТ?

if (isset ($_POST))
{
    if (empty ($_POST[...]) || empty($_POST[...]) ...)
    {
    }
    else
    {
    }
}

lastinsertid появляется только после вставки данных.

metrokto ★★ ()

Не понимаю, зачем ты отказался от mysql_*, если даже в PDO накостылил эталоннейший where student.name = "; drop table student;

man prepared statements

ну и еще поговаривают, что пых по дефолту эмулирует prepared statements, каким-то атрибутом у PDO отключаемо, копни в ту сторону.

GateKeeper ★★ ()
Ответ на: комментарий от metrokto

lastinsertid появляется только после вставки данных.

Хм... У меня примерно такой структура БД:

+-------------------+
| ID | NAME  | CITY |
+-------------------+
Где ID - целое число, которое у меня не заполняется. lastinsertid, как я понял, тут до одного места

KERNEL_PANIC ★★★ ()

Комментарии на Украинском сделали мне кровавые глаза... Лучше сразу приучатся к Английскому.

<form action='{$_SERVER['PHP_SELF']}' method='POST'> == <form action = '' method='POST'>
print "
<div class=\"alert alert-success\"> - почему не print '<div class = "alert...;">' - выглядит же проще. 
И добавь проверки на входящие данные, юзеру НИКОГДА нельзя доверять

Real1tySucks ()
Ответ на: комментарий от KERNEL_PANIC

lastinsertid возвращает последнее вставленное запросом INSERT значение поля, для которого было указано, что оно автоинкрементируемое (AUTO_INCREMENT). Если запроса не было или поле не использует автоинкремент, то lastinsertid будет иметь значение 0.

metrokto ★★ ()
Ответ на: комментарий от metrokto

Естественно, это происходит во время работы с одним и тем же ресурсом $db.

metrokto ★★ ()
Ответ на: комментарий от Real1tySucks

Комментарии на Украинском сделали мне кровавые глаза

А мне норм. это не для публикации где-нибудь, а для себя, для учебы

И добавь проверки на входящие данные, юзеру НИКОГДА нельзя доверять

Конечно же, но есть вопросы и важнее

KERNEL_PANIC ★★★ ()

Для себя, для учёбы по похапе очень рекомендую сразу смотреть на Zend Framework

C1nde ()
Ответ на: комментарий от KERNEL_PANIC

Я так думаю, учится лучше сразу по общепринятым стандартам, иначе потом будет тяжело переучиваться. Как освоишь азы - переходи на фреймворки, т.к. чистый PHP реально никому не нужен. Yii, Symphony и тд.

Real1tySucks ()
print "</select>
</td>
	</tr>
	<tr>
		<td>Номер:</td>
		<td><input type='text' name='PHONE' maxlength='10' value='$value'></td>
	</tr>

	<tr>
		<td>Послання світу<br />(не більше 200 символів):</td>
		<td><textarea rows=\"4\" maxlength=\"200\"></textarea></td>
	</tr>

	<tr>
		<td></td>
		<td>
			<input type='submit' maxlength='15' class='btn btn-primary btn-large' value='Надіслати!'>
		</td>
	</tr>
</table>

</form>

";

Можно так, если уж мешать Пых с HTML:

echo <<<HTML
</select>
</td>
	</tr>
	<tr>
		<td>Номер:</td>
		<td><input type="text" name="PHONE" maxlength="10" value="$value'"></td>
	</tr>

	<tr>
		<td>Послання світу<br />(не більше 200 символів):</td>
		<td><textarea rows="4" maxlength="200"></textarea></td>
	</tr>

	<tr>
		<td></td>
		<td>
			<input type="submit" maxlength="15" class="btn btn-primary btn-large" value="Надіслати!">
		</td>
	</tr>
</table>

</form>

HTML;
Но лучше употреблять раздельно во избежании диареи.

anonymous ()
Ответ на: комментарий от Real1tySucks

Это с того, что сначала нужно понять, как что работает само-по-себе, а уже потом можно обмазываться шаблонизаторами. Иначе по-другому уметь не будет.

metrokto ★★ ()
Ответ на: комментарий от Real1tySucks

Нее, ребята, фреймворки - последнее дело. php изначально будучи заточеный тока для обработки текста, имеет очень слабую поддержку объектного подхода. Даже простые операции с многобайтными кодировками - глючат. Надо колдовать с настройкой нескольких параметров. Пример (utf-8):

echo mb_strlen("Вася test"); // 13

Неявные приведения типов - жесть:

if ("привет поцыки" == true) {
  var_dump((object) array("a","b","c"));
}

Так что сперва нужен полет в чистом пыхе и только потом, в самом конце - лезть во фреймворки. Так еще в самих фреймворках слои надстроек из наследуемых пользовательских классов, попытки инкапсуляции низкоуровневых «абстракций», не встроенных, а писанных руками. Огромное кол-во кода жрущее немерено ресурсов. И не надо говорить что на фреймворках пишут сложные хайлоад приложения. Неа, посмотрите вокруг - сложные хайлоад используют исключительно свои велосипеды. Фреймворк это только удобство разработчика, ускорение его работы, а не самого приложения. И не так уж эти фреймворки нужны. Посмотрите вакансии. Чаще всего, единственное что хочет работодатель - хорошо ориентирующегося работника, не более. И только единицы, да - фанаты того или иного фреймворка.

deep-purple ★★★★★ ()
Ответ на: комментарий от KERNEL_PANIC

А мне норм. это не для публикации где-нибудь, а для себя, для учебы

А потом сидишь и читаешь говнокод человека, который учиться не хотел.

Ubuntu1210 ()
Ответ на: комментарий от Ubuntu1210

А потом сидишь и читаешь говнокод человека, который учиться не хотел.

Ну так не читай, я силой в код не тыкаю

KERNEL_PANIC ★★★ ()

По первому вопросу.

if (!isset($_POST['NAME']) or !isset($_POST['SEX']) or !isset($_POST['PHONE']) or !isset($_POST['PHONE']) or !isset($_POST['YEAR'])) ...

Команда !isset($_POST['PHONE']) указана дважды.

Можно упростить условие if:

if ( !isset($_POST['NAME'], $_POST['SEX'], $_POST['PHONE'], $_POST['YEAR']) )

bool isset ( mixed $var [, mixed $... ] ) Если были переданы несколько параметров, то isset() вернет TRUE только в том случае, если все параметры определены. Проверка происходит слева направо и заканчивается, как только будет встречена неопределенная переменная.

Подробнее

По второму вопросу.

KERNEL_PANIC

Второй вопрос - $db->lastInsertId(); у меня всегда выводит 0. ЧЯДНТ?

INSERT INTO users ( ID, NAME, SEX, PHONE, CITY_ID, YEAR, COUNTRY_ID ) values ( '', '$_POST[NAME]', '$_POST[SEX]', '$_POST[PHONE]', '', '$_POST[YEAR]', ''  )

Для столбца ID задан параметр autoincrement?

Если да, то попробуй передавать NULL в качестве первого параметра в списке values:

INSERT INTO users ( ID, NAME, SEX, PHONE, CITY_ID, YEAR, COUNTRY_ID ) values ( NULL, '$_POST[NAME]', '$_POST[SEX]', '$_POST[PHONE]', '', '$_POST[YEAR]', ''  )
Deleted ()
Последнее исправление: Deleted (всего исправлений: 3)

KERNEL_PANIC

Не понимаю, как реализовать проверку ввода данных - если данных в $_POST нету, то выводить сообщение. Проверка через isset срабатывает сразу после первой загрузки, что и логично. Что тут можно придумать?

С целью пояснения по данному вопросу подготовил страницу, скрипт.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="ru"><head>
	<meta http-equiv="Content-Type" content="text/html; charset=koi8-r">
	<title>Форма для теста</title>
	<style type="text/css">
	span.success, span.error {
		font-weight: bold;
		padding: 1mm 2mm;
		border-radius: 5px;
	}
	span.success {
		background-color: lightgreen;
		border: 1px solid green;
	}
	span.error {
		background-color: pink;
		border: 1px solid red;
	}
	</style>
</head><body>
	<h3>Форма для теста</h3>
	<form action="" method="post">
	<p><input type="text" name="name" maxlength="30"> Ваше имя</p>
	<p><input type="text" name="year" maxlength="4"> Год рождения</p>
	<p>
		Пол:
		<input type="radio" name="sex" value="m" checked> Муж
		<input type="radio" name="sex" value="f"> Жен
	</p>
	<p><input type="text" name="phone" maxlength="12"> Номер телефона, 12 цифр</p>
	<p>
		<input type="submit" value="Готово">
		<input type="reset" value="Очистить">
	</p>
	</form>
<?php
// Функция tail() обеспечивает завершение скрипта c выводом сообщения об ошибке, если имеется.
function tail( $error_message ) {
	if ( !empty($error_message) ) echo "<p><span class=\"error\">$error_message</span></p>\n";
	echo "</body></html>";
	exit;
}

// Если форма открыта впервые, дополнительных действий не производить.
if ( !isset($_POST['name'], $_POST['year'], $_POST['sex'], $_POST['phone']) ) tail('');

// Извлечь параметры скрипта из массива $_POST
$name = trim( $_POST['name'] ); // Устранить пробелы в начале, окончании строки $_POST['name']
$year = $_POST['year'];
$sex = $_POST['sex'];
$phone = $_POST['phone'];

/* if ( empty($name) || empty($sex) || empty($phone) || empty($year) ) >----v
Предпочитаю не использовать функцию empty() в процессе верификации параметров скрипта, т.к. empty()
возвращает значение "истина" для строки "0", которая не является пустой. */
if ( $name === '' || $sex === '' || $phone === '' || $year === '' ) tail('Отдельные поля формы не заполнены!');

if ( strlen($name) < 5 || strlen($name) > 30 ) tail('Укажите имя длиной от 5 до 30 символов!');

// Год - строка из 4-х цифровых символов
if ( strlen($year) !== 4 || !ctype_digit($year) || $year < 1900 || $year > 2010 ) tail('Год указан неверно!');

// m - Male, f - Female
if ( $sex !== 'm' && $sex !== 'f' ) tail('Пол указан неверно!');

// Номер мобильного телефона - строка из 12 цифровых символов  
if ( strlen($phone) !== 12 || !ctype_digit($phone) ) tail('Номер мобильного телефона указан неверно!');

/* Перед добавлением данных к базе рекомендуется "зачистить" параметры вручную,
либо применить т.н. подготовленные выражения (prepared statement). */

echo "<p><span class=\"success\">Запись добавлена к БД успешно!</span></p>\n";
echo "<p>Имя '$name'</p>\n";
echo "<p>Год рождения '$year'</p>\n";
echo "<p>Пол '$sex'</p>\n";
echo "<p>Номер телефона '$phone'</p>\n";
tail('');
?>
Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Спасибо большое, однако подозреваю, что конструкция

// m - Male, f - Female
if ( $sex !== 'm' && $sex !== 'f' ) tail('Пол указан неверно!');
лишняя, так как используя радиобокс неверное значение не введешь)

KERNEL_PANIC ★★★ ()
Последнее исправление: KERNEL_PANIC (всего исправлений: 1)
Ответ на: комментарий от KERNEL_PANIC

KERNEL_PANIC

используя радиобокс неверное значение не введешь)

Согласен.

Это защита от фаззинга (fuzzing), если взломщик попытается передать параметр $_POST['sex'] «вручную», без использования формы, радиобокса.
Указанная конструкция обеспечивает «отсечение» всех непредусмотренных значений для $_POST['sex'], среди которых могла бы присутствовать инъекция: SQL-injection, PHP-injection.

Deleted ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.