8791 sujets

Développement web côté serveur, CMS

Bonjour à tous !

Je suis débutant en PHP. Pour m'entraîner j'ai créé ce script très simple qui permet d'enregistrer un nom et une adresse email dans une base de donnée.

Voici mon script :


	<?php
		$mysql = mysql_pconnect('localhost','root','motDePasse');
		if(!$mysql) {
			echo '<h1 class="alert">Cannot connect to database.</h1>';
			exit;
		}
		$mysql = mysql_select_db('users');
		if(!$mysql) {
			echo '<h1 class="alert">Cannot select to database.</h1>';
			exit;
		}
	?>
	
	<h1>Register</h1>
	
		<form method="post" action="index.php">
			<fieldset>
				<label for="username">Username :</label>
				<input type="text" name="username" />
			</fieldset>
			
			<fieldset>
				<label for="email">Email :</label>
				<input type="text" name="email" />
			</fieldset>
			
			<input type="submit" name="register" value="Register" />
		</form>
	
	<?php	
		if (isset($_POST['register'])) {
			if(!empty($_POST['username']) && !empty($_POST['email'])) {
				$username = mysql_real_escape_string($_POST['username']);
				$email = mysql_real_escape_string($_POST['email']);
				
				$checkusername = mysql_query("select username from users where username = '".$username."'");
				if(mysql_num_rows($checkusername) == 1) {
					echo '<h1 class="alert">Sorry, <span>'.$username.'</span> is taken. Please try again.</h1>';
					
					$checkemail = mysql_query("select email from users where email = '".$email."'");
					if(mysql_num_rows($checkemail) == 1) {
						echo '<h1 class="alert">Sorry, <span>'.$email.'</span> is already used. Try again.</h1>';
						exit;
					}
				} else {
					$checkemail = mysql_query("select email from users where email = '".$email."'");
					if(mysql_num_rows($checkemail) == 1) {
						echo '<h1 class="alert">Sorry, <span>'.$email.'</span> is already used. Try again.</h1>';
						exit;
					} else {
						$query = mysql_query("insert into users values('', '".$username."', '".$email."')");
						if($query) {
							echo '<h1 class="alert">Congrats! You are registered, you can now <a href="#">login</a>!</h1>';
						} else {
							echo '<h1 class="alert">Sorry, but we cannot register you.</h1>';
						}
					}
				}
			} else {
				echo '<h1 class="alert">Sorry, but you need to complete all the field!';
				exit;
			}
		}
	?>


J'ai créé le script de tel façon que si le nom ou le mail existent déjà, il renvoi une erreur.
Ce que j'ai pour l'instant fonctionne bien, c'est à dire que si je rentre un nom + un mail qui existe déjà il me renvoi deux erreur : une pour le nom et une pour le mail.

Ma question est : comment simplifier ce script tout en conservant l'accumulation des erreurs ?

Car pour l'instant pour que sa fonctionne comme je veux les vérifs d'existence ou non en BDD sont imbriquées, et je n'ose pas imaginer la complexité du script si je rajoute des champs.

(Bien sûr ce script n'est pas du tout sécurisé mais là n'est pas la question).

Merci d'avance !
Modifié par Remay (13 May 2009 - 02:52)
Salut,

Remay a écrit :
Ma question est : comment simplifier ce script tout en conservant l'accumulation des erreurs ?

Car pour l'instant pour que sa fonctionne comme je veux les vérifs d'existence ou non en BDD sont imbriquées, et je n'ose pas imaginer la complexité du script si je rajoute des champs.
Ben en même temps pour une inscription il ne doit pas y avoir des dizaines de champs uniques à vérifier en plus d'un pseudo et d'un email ! Smiley murf

Sinon quelques remarques :
* as-tu une bonne raison de vouloir utiliser une connexion persistante ? D'autant plus que tu te connectes avant même que le formulaire ait été soumis.
* le LABEL FOR fait référence à un id or tes INPUT ne possèdent qu'un name.
* ce serait sympa de réafficher ce qui a été saisi en cas d'erreur ou de champ déjà existant dans la base.
* du coup il ne faudrait appliquer le mysql_real_escape_string qu'au moment d'effectuer les requêtes (comme c'est le cas dans les exemples de php.net)...
* ...et réafficher à l'aide de htmlspecialchars.
* que voudrais-tu rajouter quand tu parles de "pas du tout sécurisé" ?
* pourquoi avoir tout rédigé en anglais ? Smiley langue
Modifié par Heyoan (13 May 2009 - 03:47)
Un exemple (sans vérification de la validité de l'email) :
<?php
// Récupération ou initialisation des variables
$username = !empty($_POST['username']) ? trim($_POST['username']) : '';
$email = !empty($_POST['email']) ? trim($_POST['email']) : '';
$city = !empty($_POST['city']) ? trim($_POST['city']) : '';
$state = !empty($_POST['state']) ? trim($_POST['state']) : '';
$errors = array();

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	// Connexion si nécessaire
	if(!empty($username) || !empty($email)) {
		$mysql = @mysql_connect('localhost','root','');
		if(!$mysql) {
			echo '<h1 class="alert">Cannot connect to database.</h1>';
			exit;
		}
		$mysql = @mysql_select_db('test');
		if(!$mysql) {
			echo '<h1 class="alert">Cannot select to database.</h1>';
			exit;
		}
	}

	// Vérification des champs
	if(!empty($username)) {
		$query = sprintf("SELECT username FROM users WHERE username='%s'", mysql_real_escape_string($username));
		$result = mysql_query($query);
		if(mysql_num_rows($result) == 1) {
			$errors[] = 'Sorry, <strong>'.htmlspecialchars($username).'</strong> is taken.';
		}
	} else {
		$errors[] = 'Username is required.';
	}

	if(!empty($email)) {
		$query = sprintf("SELECT email FROM users WHERE email='%s'", mysql_real_escape_string($email));
		$result = mysql_query($query);
		if(mysql_num_rows($result) == 1) {
			$errors[] = 'Sorry, <span>'.htmlspecialchars($email).'</span> is already used.';
		}
	} else {
		$errors[] = 'Email is required.';
	}

	if(empty($city)) {
		$errors[] = 'City is required.';
	}

	if(empty($state)) {
		$errors[] = 'State is required.';
	}

	// Si tout est OK --> Insertion
	if(count($errors) == 0) {
		$query = sprintf("Insert into users Values ('', '%s', '%s', '%s', '%s')", 
			mysql_real_escape_string($username),
			mysql_real_escape_string($email),
			mysql_real_escape_string($city),
			mysql_real_escape_string($state));
		$result = mysql_query($query);
		if(!$result) {
			$errors[] = 'Sorry, but we cannot register you.';
		} else {
			header("Location: confirmation.php"); // Redirection pour éviter de ressoumettre 
		}
	}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Test</title>
<style type="text/css">
.alert {
	color: #990000;
}
</style>
</head>
<body>
<?php
// Affichage des erreurs
if(count($errors) > 0) {
	foreach($errors as $error) {
		echo '<p class="alert">'.$error."</p>\n";
	}
}
?>
<h1>Register</h1>
<form method="post" action="index.php">
	<fieldset>
		<p>
			<label for="username">Username :</label>
			<input type="text" name="username" id="username" value="<?php echo htmlspecialchars($username); ?>" />
		</p>
		<p>
			<label for="email">Email :</label>
			<input type="text" name="email" id="email" value="<?php echo htmlspecialchars($email); ?>" />
		</p>
		<p>
			<label for="city">City :</label>
			<input type="text" name="city" id="city" value="<?php echo htmlspecialchars($city); ?>" />
		</p>
		<p>
			<label for="state">State :</label>
			<input type="text" name="state" id="state" value="<?php echo htmlspecialchars($state); ?>" />
		</p>
		<p>
			<input type="submit" value="Register" />
		</p>
	</fieldset>
</form>
</body>
</html>

Modifié par Heyoan (26 Jul 2009 - 14:38)
Tout d'abord merci beaucoup pour ton aide.

a écrit :
as-tu une bonne raison de vouloir utiliser une connexion persistante ? D'autant plus que tu te connectes avant même que le formulaire ait été soumis.

- Je n'ai pas vraiment de bonnes raisons d'utiliser une connexion persistante. Je l'ais fait de cette façon uniquement parce que je m'entraine et je n'y ai pas vraiment fait attention. Dans le cas d'un déploiement sur le web je prendrai en compte le fait que ce ne soit pas forcement utile.


a écrit :
le LABEL FOR fait référence à un id or tes INPUT ne possèdent qu'un name.

- Bien vue, même justification que pour la connexion persistante, dans le cas qu'un déploiement sur le web je compléterai comme il faut mes balises. Accessibilité avant tout!


a écrit :
ce serait sympa de réafficher ce qui a été saisi en cas d'erreur ou de champ déjà existant dans la base.

- Alors en fait justement je prévoyais ça pour la prochaine étape! Mais comme je débute je préfère y aller doucement. Donc je ne me suis pas encore vraiment penché sur la question.


a écrit :
* du coup il ne faudrait appliquer le mysql_real_escape_string qu'au moment d'effectuer les requêtes (comme c'est le cas dans les exemples de php.net)...
* ...et réafficher à l'aide de htmlspecialchars.

- Bon donc là je ne me suis pas encore vraiment attardé sur le problème.


a écrit :
* que voudrais-tu rajouter quand tu parles de "pas du tout sécurisé" ?

- Je veux parler du faite de vérifier que l'adresse mail est correcte par exemple. Je regarderai ça une fois que j'aurais bien saisie le reste. J'ai besoin de faire les choses par étapes. Trop d'un coup et je comprend plus rien. Smiley smile


a écrit :
* pourquoi avoir tout rédigé en anglais ? Smiley langue

- Eh eh! Bonne question Smiley smile . N'étant pas vraiment bon en anglais, mais ayant le désir de m'améliorer je m'entraine par la même occasion à pratiquer un peu d'anglais. J'espère que ça ne pose pas de problème ? (au cas ou : je n'ai pas copier/coller bêtement ce script depuis je ne sais quel tuto en anglais. J'ai galérai tout seul mais il n'y à que comme ça que j'apprends!)


Encore merci pour ton aide. Je vais regarder plus précisément la solution que tu me suggères. Essayer de décortiquer tout ça. Et je reviens bientôt avec d'autres questions à priori. Smiley biggrin
Modifié par Remay (13 May 2009 - 13:01)
Perso pour vérifier une adresse email par exemple j'utilise cette fonction :

<?php
function check_mail($mail)
{
	if(!preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $mail)) {
		return false;
	}
	
	$domain = substr(strstr($mail, '@'), 1);

	if(!function_exists('checkdnsrr')) {
		return true;
	}
	
	if(!checkdnsrr($domain)) { 
		return false;
	}
	
	return true;
}
?>