PHP准备语句插入查询

There is an error in the following code.

demo.php:

<form method="post" action="">
  <table border="1">
    <tr>
      <td> Enter Name </td>
      <td> <input type="text" name="txtname"/> </td>
    </tr>
    <tr>
      <td> Enter Email </td>
      <td> <input type="text" name="txtemail" /> </td>
    </tr>
    <tr>
      <td colspan="2" align="center">
      <input type="submit" name="btnsubmit" value="Add" />
      </td>
    </tr>
    <tr>
      <td colspan="2" align="center">
      <?php
      if(isset($_REQUEST['message']))
      {
      echo $_REQUEST['message'];
      }
      ?>
      </td>
    </tr>
  </table>
</form>

<?php
include 'db_operations.php';
  if(isset($_POST['btnsubmit']) and isset($_POST['btnsubmit']) == "Add")
  {
    extract($_POST);
    $insertQuery = "INSERT INTO author(name,email) VALUES (?,?)";
    $param_type = "ss";
    $param = $txtname.','.$txtemail;
    $result = $db->executeQuery('insert',$insertQuery,$param_type,$param);
    header("Location:demo.php?message=$result");  
  }
?>

db_operations.php:

<?php
  function executeQuery($query_type,$query_string,$param_type,$param)
  {
      $result = "Error";

      set_error_handler("logError");

      if(!$stmt = $this->con->prepare($query_string))
      {
          trigger_error("Failed to prepare statement for " . $query_type ." query");
      }

      if(!$stmt->bind_param($param_type,$param))
      {
          trigger_error("Failed to bind parameter for " . $query_type ." query");
      }
      if(!$stmt->execute())
      {
          trigger_error("Failed to execute " . $query_type ." query");
      }
      else
      {
          $result = "Record ".$query_type."ed successfully";
      }

      $this->stmt->close();
      $this->con->close();
      return $result;
  }
?>

There are 2 php files. The first script accepts a record and makes an insert query, and the second script execute that query.

However, when I execute the program, it shows me the following error:

*Error Type : E_WARNING *Error String : mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables *Error Line : 55 *Error File : F:\wamp\www\food_app\inc\admin_db_operations.php *Error Date : 09-02-2018 06:43:09 pm

*Error Type : E_USER_NOTICE *Error String : Failed to bind parameter for insert query *Error Line : 57 *Error File : F:\wamp\www\food_app\inc\admin_db_operations.php *Error Date : 09-02-2018 06:43:09 pm

*Error Type : E_USER_NOTICE *Error String : Failed to execute insert query *Error Line : 61 *Error File : F:\wamp\www\food_app\inc\admin_db_operations.php *Error Date : 09-02-2018 06:43:09 pm

Please guide me on how I can improve my function to work correctly.

Well, according to the error message:

Number of elements in type definition string doesn't match number of bind variables

You're specifying a different number of variables than you're supplying. Let's take a look at where you bind the values:

$stmt->bind_param($param_type,$param)

You're passing the string "ss", indicating that there are two parameters to bind. But then you're passing only a single value in $param. That value is a single string composed of the two different values you want.

You have to bind the values separately, not as a single string.

The bind_param() function expects a variable number of arguments. So you should be able to pass through that same concept in your function. It's been a while, but I think it might look something like this:

function executeQuery($query_type, $query_string, $param_type, ...$params)

That ... would tell PHP that $params is a variable-length argument list. Then I think you can just pass that list along to bind_param():

$stmt->bind_param($param_type, $params)

And when you call your function, instead of concatenating your values into a single string, pass them as separate values:

$db->executeQuery('insert', $insertQuery, $param_type, $txtname, $txtemail)

In this part of your code:

$insertQuery = "INSERT INTO author(name,email) VALUES (?,?)";
$param_type = "ss";
$param = $txtname.','.$txtemail;

This line is wrong:

$param = $txtname.','.$txtemail;

Why? because you are converting 2 variables in just 1. Then when you try to bind the parameters you get the error mentioned on your description because the query is expecting 2 parameters not 1. If your idea is to pass this parameters "all-in-one" you can create an array:

//$param = $txtname.','.$txtemail; // this line is wrong
$param = array($txtname, $txtemail); // This line is correct!

Then you change the way you "bind" the values on your code, changing this code:

if(!$stmt->bind_param($param_type,$param))
      {
          trigger_error("Failed to bind parameter for " . $query_type ." query");
      }

for this one:

if(!$stmt->bind_param($param_type,$param['0'],$param['1']))
      {
          trigger_error("Failed to bind parameter for " . $query_type ." query");
      }

More information of binding parameters here: mysqli stmt bind and the ways you can use an array here: PHP Arrays

First of all, none of your PHP code will run because your condition includes this :

isset($_POST['btnsubmit']) == "Add"

while you surely meant

$_POST['btnsubmit'] == "Add"

Because the result of isset() is gonna be either true or false but surely not "Add"

Second your $param variable should be an array like this :

$param = [$txtname, $txtemail];

Because now, you only passed one parameter consisting of a string that has a comma in the middle but still only one string so that would go fill the first ? in your query and MySQL is waiting for a second parameter. That's what the WARNING says