MySQL存储过程参数验证

时间:2015-06-02 23:29:10

标签: php mysql stored-procedures pdo

我想知道从MySQL存储过程到PHP应用程序的返回验证错误的最佳实践是什么。我已经看到了Signals和正在使用的字符串,但我正在寻找一种自动处理错误的方法,以便将它们映射到表单`字段。

例如,如果我有注册表单,我需要确保系统中尚不存在该电子邮件。所以我需要存储过程来返回一个键=>价值"email" => "Duplicate entry for email"

我也在想,在数据库中存储消息(将被发送到客户端)可能没有意义。关闭上面的电子邮件示例"email" => "1062",然后在PHP应用程序中,有一张地图1062 => "$key already exists."

我很高兴能够保持密钥=> (值/错误消息)关联,因此AJAX响应对象可能包含类似

的内容

// Http Status 400
{ "email": "Email already exists", "name": "Name is required" }

这就是电子邮件和姓名的关键,并直接与他们的“姓名”和“电子邮件”输入相关联。

<form>
  <input name="name"/>
  <input name="email"/>
  <input type="submit" value="Submit"/>
</form>


<?php
  $sanitizedInput = $_POST; //Pretend this data is actually sanitized.
  $pdo = new PDO($dsn, $username, $password);
  $stmt = $pdo->prepare("CALL registerUser(?, ?)");
  $stmt->bindParam(1, $sanitizedInput["name"]);
  $stmt->bindParam(2, $sanitizedInput["email"]);

  #Whats the best method for processing?
  try{
      if($stmt->execute()){

      }else{

      }
  }catch(PDOException $e){
     //I want to prevent doing string comparisons if possible
     //Signal example
     //It seems like this step could be automated and reused.
     //For example, if we allow a user to update their email address,
     //we could have the string 'Duplicate entry for email' in the
     //codebase twice, and it seems like the process could be easily broken.
     if($stmt->errorInfo[2] == 'Duplicate entry for email'){
        return array('email' => 'Email already exists');
     }
  }
?>

#SQL
signal sqlstate = '45000' set message_text = 'Duplicate entry for email'

 create procedure registerUser(
   name varchar(50),
   email varchar(50)
 )
 begin
 declare emailExists int(0);

 select count(*) into emailExists from users where email = email;

 if emailExists = 0 then
     insert into users values(default, name, email);
 else
     //Return {email: 'Duplicate entry for email'}
 end

1 个答案:

答案 0 :(得分:1)

为什么要在存储过程中运行验证?为什么不先使用php来验证格式。然后第二次检查将是此查询

SELECT 1 FROM email where email ='abc@nb.com'LIMIT 1

如果此查询返回1表示该记录存在?

如果你想在这里使用过度杀戮的存储过程。

您可以使用SQLEXCEPTION HANDLER

类似这样的事情

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    BEGIN
        GET DIAGNOSTICS CONDITION 1
        @err_sqlstate = RETURNED_SQLSTATE,
        @err_message = MESSAGE_TEXT,
        @err_num = MYSQL_ERRNO;

        SET @hasError = TRUE;
    END;

运行查询后,您可以执行类似这样的操作

IF(@hasError)

 SELECT CONCAT("[",
      GROUP_CONCAT(
           CONCAT("{message:'", @err_message,"'"),
           CONCAT(",sqlState:'",@err_sqlstate),"'}")
      )
 ,"]") AS jSON
END IF;