Je suis un peu confus au sujet de Prepared Statements
en PHP, je surveille le tutoriel suivant sur youtube: https://www.youtube.com/watch?v=aN5KqxK1slcPHP: la préparation des états à l'intérieur d'un projet basé POO
Après que j'ai reçu la note suivante sur mon actuellement code source mysqli:
Vous êtes ouverts à SQL injections et devrait vraiment utiliser préparés déclarations au lieu de concaténer vos requêtes. Spécialement depuis vous n'échappez pas du tout aux entrées de l'utilisateur!
Ma question:
Comment puis-je préparer la déclaration puisque je crée la syntaxe de l'instruction dans ma classe registre et ne transmettre la déclaration à ma classe de base de données pour exécuter -il en utilisant la fonction execute_query
? Est-ce que je juste préparer l'instruction à l'intérieur de la fonction execute_query
et vérifier si c'est soit une déclaration du format INSERT
ou SELECT
, puis préparer les valeurs?
J'apprécie toute sorte de suggestions et de commentaires.
Mon code actuel ressemble à ce qui suit:
classe Registre:
<?php
class register extends database
{
function __construct($username, $password, $email)
{
$this->username = $username;
$this->password = password_hash($password, PASSWORD_DEFAULT);
$this->email = $email;
$this->activation_id = $this->generateActivationId();
$this->sender_email = '[email protected]';
$this->activation_link = 'http://url.com/folder/activate.php?id=' . $this->activation_id;
$this->database = new database();
}
function generateActivationId()
{
$generator = bin2hex(random_bytes(10));
return $generator;
}
function registerAccount()
{
$this->database->connect();
$user_lookup = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'");
if (mysqli_num_rows($user_lookup) > 0)
{
return false;
}
else
{
$this->database->execute_query("INSERT INTO users (username, password, email, activation_id) VALUES ('" . $this->username . "', '" . $this->password . "', '" . $this->email . "', '" . $this->activation_id . "')");
$user_lookup_comfirm = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'");
if (mysqli_num_rows($user_lookup_comfirm) > 0)
{
$this->sendRegisterEmail();
return true;
}
else
{
return false;
}
}
}
function sendRegisterEmail()
{
$subject = 'Registration - Activate your account';
$message = 'Thank you for registering. Please activate your account by visiting the following site: <a href="' . $this->activation_link . '">Website link</a>';
$headers = 'From: ' . $this->sender_email . "\r\n" .
'Reply-To: ' . $this->sender_email . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($this->email, $subject, $message, $headers);
}
}
?>
classe Database:
<?php
class database
{
function __construct()
{
$this->dBusername = 'xxx';
$this->dBpassword = 'xxx';
$this->dBhost = 'localhost';
$this->dBdatabase = 'xxx';
$this->dBcharset = 'utf8';
}
function connect()
{
$mysqli = new mysqli($this->dBhost, $this->dBusername, $this->dBpassword, $this->dBdatabase);
if ($mysqli->connect_errno)
{
$this->_mysqli = false;
}
else
{
$mysqli->set_charset($this->charset);
$this->_mysqli = $mysqli;
}
}
function execute_query($sql)
{
if($results = $this->_mysqli->query($sql))
{
return $results;
}
else
{
return false;
}
}
}
?>
Cette classe 'database' ne fait * rien *. Débarrassez-vous de cela, utilisez directement une instance mysqli ou PDO. – deceze
Donc je devrais juste créer une classe entière de gestionnaire de base de données qui crée une instance de mysqli et ensuite préparer les déclarations là et appeler ces fonctions de la classe de registre? – stackvisual
Vous devriez simplement utiliser l'interface MySQLi ou PDO directement. Vous n'avez pas besoin d'un wrapper, il finit par causer plus de maux de tête que cela résout dans la plupart des cas. – Qirel