【问题标题】:PHP function returns false even if executed successfullyPHP 函数即使执行成功也会返回 false
【发布时间】:2021-07-19 15:47:51
【问题描述】:

我有以下功能。

function generateOTP($theUser, $thePhone){
  global $pdo;

  $stmt = $pdo->prepare("DELETE FROM otp WHERE phone = :phone");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> execute();

  $stmt = $pdo->prepare("INSERT INTO otp(phone, otp, type, validity)VALUES(:phone, :otp, :type, :val)");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> bindValue(':otp', rand(1000, 9999));
  $stmt-> bindValue(':type', 'new');
  $stmt-> bindValue(':val', date('Y-m-d H:i:s', strtotime('+5 mins')));
  $stmt-> execute();
}

function sendOTP($theUser, $thePhone){
  global $pdo;
  generateOTP($theUser, $thePhone);
}

// CALLED SOMEWHERE LIKE THIS
if(sendOTP($theUser, $thePhone){
  echo "OTP SENT";
}else{
  echo "OTP SENDING FAILED";
}

我遇到的问题是,即使sendOTP()函数执行得很好,并且所有记录都已插入数据库,它总是移动到else块并打印OTP SENDING FAILED。换句话说,假设函数未能成功执行,它总是返回 false。但实际上,函数执行得很好,所有查询都正确执行。这是一个我以前从未遇到过的奇怪问题。我该如何解决这个问题?

【问题讨论】:

  • 你的函数没有返回任何东西,所以我不确定你期望如何知道真实的结果。尝试获取没有 return 语句的函数的结果将始终导致 null,这是 false-y,这就是您的 if 行为如此的原因。
  • 如果你真的想知道是否所有的 PDO 代码都成功了然后启用 PDO 错误处理:php.net/manual/en/pdo.error-handling.php。如果你需要处理这些,你可以将它包装在 try/catch 中。
  • 您的输出消息也具有误导性(除非您省略了一些代码),因为您的代码所做的只是删除并将值插入数据库。它实际上并没有将值 发送 到任何人的手机。插入发生后发送仍然很容易失败,但我假设该过程在您的应用程序的其他地方处理(或在您上面的示例中从 sendOTP() sn-p 省略的某些代码中)。
  • @ADyson 你是对的,我什至尝试以if(generateOTP($theUser, $thePhone){ return true; } 返回true,但结果仍然相同。在尝试了我知道的所有可能的方法后,我不得不提出一个问题。
  • @ADyson 我知道 PDO 代码执行得很好,因为记录被插入到数据库中。我真的还需要使用 try catch 方法吗?

标签: php function


【解决方案1】:

我可以建议下一个解决方案(otp 表必须具有唯一/主键 phone):

<?php
function generateOTP($theUser, $thePhone){
    global $pdo;
    try {
        $stmt = $pdo->prepare("
            INSERT INTO otp(phone, otp, type, validity) 
            VALUES (:phone, :otp, :type, :val)
            ON DUPLICATE KEY UPDATE
                otp = :otp,
                type = :type,
                validity = :val");
        $stmt-> bindValue(':phone', $thePhone);
        $stmt-> bindValue(':otp', rand(1000, 9999));
        $stmt-> bindValue(':type', 'new');
        $stmt-> bindValue(':val', date('Y-m-d H:i:s', strtotime('+5 mins')));
        return $stmt-> execute();
    } catch (PDOException $Exception ) {
        // print_r($Exception);
        // here you can log Exception
        return false;
    }
}

function sendOTP($theUser, $thePhone){
  global $pdo;
  return generateOTP($theUser, $thePhone);
}

这里可以test PHP code online

【讨论】:

  • 太好了.. 谢谢:)
【解决方案2】:

您的函数不会返回您需要更改代码的任何值:

function generateOTP($theUser, $thePhone){
  global $pdo;

  $stmt = $pdo->prepare("DELETE FROM otp WHERE phone = :phone");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> execute();

  $stmt = $pdo->prepare("INSERT INTO otp(phone, otp, type, validity)VALUES(:phone, :otp, :type, :val)");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> bindValue(':otp', rand(1000, 9999));
  $stmt-> bindValue(':type', 'new');
  $stmt-> bindValue(':val', date('Y-m-d H:i:s', strtotime('+5 mins')));
  $stmt-> execute();
}

function sendOTP($theUser, $thePhone){
  global $pdo;
  generateOTP($theUser, $thePhone);
}

到:

function generateOTP($theUser, $thePhone){
  global $pdo;

  $stmt = $pdo->prepare("DELETE FROM otp WHERE phone = :phone");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> execute();

  $stmt = $pdo->prepare("INSERT INTO otp(phone, otp, type, validity)VALUES(:phone, :otp, :type, :val)");
  $stmt-> bindValue(':phone', $thePhone);
  $stmt-> bindValue(':otp', rand(1000, 9999));
  $stmt-> bindValue(':type', 'new');
  $stmt-> bindValue(':val', date('Y-m-d H:i:s', strtotime('+5 mins')));
  if ($stmt-> execute()) {
   return true;
  } else {
   return false;
  }
}

function sendOTP($theUser, $thePhone){
  global $pdo;
  if (generateOTP($theUser, $thePhone)) { 
   return true;
  } else {
   return false;
  }
}

现在你让你的函数返回真/假

【讨论】:

  • 除了最后的 execute() 语句之外,PDO 代码失败的方式还有很多。启用 PDO 错误处理(可能使用 try/catch)将是一种更强大的方法
  • 哦,我现在明白了。我只是尝试在 sendOTP() 函数中返回 true。我需要在这两个功能中都这样做。知道了。此外,else{ return false; } 不是必需的。我可以只检查true 并查看if(sendOTP($theUser, $thePhone)),这意味着如果它是真的,否则默认总是意味着假。
  • @RelaxingMusic 请注意,如果您的 DELETE 未能执行(),或者任何 prepare() 或 bindValue() 调用因任何原因而失败,那么您接受的这个半生不熟的答案不会正确检测。
  • @ADyson 当然.. 我会记住这一点:)
  • @ADyson 或者,您能否给出一个完整的答案以使其更安全?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
相关资源
最近更新 更多