【问题标题】:MySQL Stored Procedure parameter validationMySQL 存储过程参数验证
【发布时间】:2015-08-16 23:11:06
【问题描述】:

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

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

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

我很高兴能够保持键 =>(值/错误消息)关联,以便 AJAX 响应对象可以包含类似的东西

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

这样email和name的key就直接和他们输入的“name”和“email”相关联了。

<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

结束

【问题讨论】:

    标签: php mysql stored-procedures pdo


    【解决方案1】:

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

    SELECT 1 FROM emails 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;
    

    【讨论】:

    • 也许验证是错误的术语,在 PHP 中检查字符串格式,但其他因素如强制单个条目必须使用 SQL 完成。我将更新存储过程示例以澄清我的问题。
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多