Ngoài tài nguyên / đối tượng kết nối mysqli bị thiếu, còn có một số vấn đề khác với tập lệnh:
- nó dễ bị tiêm sql
- bạn không kiểm tra kết nối mysql như được hiển thị tại http://docs.php .net / mysqli.quickstart.connections
- tập lệnh nói chung thiếu khả năng xử lý lỗi. Bất kỳ hàm / phương thức mysqli_ * nào đều có thể bị lỗi. Ví dụ. cảnh báo về
mysqli_num_rows
có liên quan đến việc không kiểm tra giá trị trả về củamysqli_query
. - hàm test_input () của bạn không kiểm tra bất kỳ điều gì nhưng thay đổi giá trị; và địa chỉ email không liên quan gì đến htmlspecialchars () et al. Chỉ cần bỏ chức năng đó.
- xác thực địa chỉ email có vẻ quá phức tạp mà không rõ ràng đáng khen ngợi.
- Thay vì tổ hợp CHỌN / CHÈN để ngăn địa chỉ email được chèn hai lần, chỉ cần tạo chỉ mục duy nhất trên trường đó và máy chủ mysql sẽ ngăn các bản sao một cách đáng tin cậy.
ví dụ.
<?php
define('MYSQL_ER_DUP_KEY', 1022); // see https://dev.mysql.com/doc/refman/5.6/en/error-messages-server.html#error_er_dup_key
$errors = array();
if($_POST) // might be superfluous
{
// simplified email validation
// improve if needed
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ( !$email ) {
// removed html/style from error message, better do that when printing the error
$errors['email1'] = "A valid email address is required";
}
// you only need the database connection after the email address is validated
$mysqli = new mysqli('localhost', 'root', '','ecommerce');
// see http://docs.php.net/mysqli.quickstart.connections
if ($mysqli->connect_errno) {
trigger_error("Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error, E_USER_ERROR);
}
// not checking if this email address is already in the database
// instead create a unique index for that field
// see https://dev.mysql.com/doc/refman/5.6/en/constraint-primary-key.html
// - otherwise you'd at least have to lock the table to avoid race conditions -
// sql injections: see http://docs.php.net/security.database.sql-injection
// to prevent sql injections you either have to make sure string literals are
// properly encoded/escaped or use preparead statements+parameters
$stmt = $mysqli->prepare('INSERT INTO subscriptions (email) VALUES (?)');
if ( !$stmt ) {
trigger_error("prepare statement failed (" . $mysqli->errno . ") " . $mysqli->error, E_USER_ERROR);
}
else if ( !$stmt->bind_param('s', $email) ) {
trigger_error("bind_param failed (" . $stmt->errno . ") " . $stmt->error, E_USER_ERROR);
}
else if ( !$stmt->execute() ) {
// email has a unique index, inserting an email address a second time
// results in a ER_DUP_KEY error
if ( MYSQL_ER_DUP_KEY==$stmt->errno ) {
$errors['email2'] = "email address already in subsription list";
}
else { // otherwise it's "really" an error
trigger_error("execute failed (" . $stmt->errno . ") " . $stmt->error, E_USER_ERROR);
}
}
else {
[... inserted ...]
}
}