Click here to Skip to main content
15,881,852 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi, I've got a problem here where I can't get the script to repeat something that I have successfully accomplished some place else.

At my register form, after all the validation and checks have being passed, I'm trying to insert the information into the database to register the user... but this is my first time using MySQLi, especially prepare and bind_params so I'm very rusty on this so far... can't seem to get it right the first time for some reason.

Anyway, I have a function in my MySQLi database access wrapper that uses the passed arguments to create the INSERT SQL and execute it... actually insert it. I have this function be used for all of the situations (which means the bind parameters would be different from time to time and the function needs to accept a dynamic amount of parameters). Here is my insert function.

PHP
public function insert($tbl_name, $fields, $values, $types, $vars)
{
    // Initiating our insert SQL
    $sql = "INSERT INTO `$tbl_name`";
    
    // Generating the fields
    $sql .= " (`" . implode("`, `", $fields) . "`)";
    
    // Generating the values of the SQL
    $sql .= " VALUES ('" . implode("', '", $values) . "')";
    
    // Initiating the mysqli statement
    $stmt = $this->mysqli_link->stmt_init();
    
    // Setting the last sql used
    $this->last_sql = $sql;
    
    // Preparing the statement
    $stmt->prepare($sql) or die($stmt->error);
    
    // The variable array ([0] => $types, [1+] $vars)
    $array = array(array($types), $vars);
            
    // Merging all of the arrays into one array
    $array = call_user_func_array('array_merge', $array);
    
    // The reference array being created
    $refArray = $this->make_ref($array);
    
    // Initiating the mysqli_stmt VIA ReflectionClass
    $ref = new ReflectionClass('mysqli_stmt');
    
    // Getting the bind_param function
    $method = $ref->getMethod('bind_param');
    
    // Invoking the function (actually binding here)
    $method->invokeArgs($stmt, $refArray);
    
    // Checking against errors in the execution of the SQL
    if(!$stmt->execute())
    {
        // There was an error
        throw die($stmt->error);
    }
    
    // Returning true on success
    return true;
}

Here is how I use it
PHP
// The values to be added to the database
$values = array('null', // user id
                'null', // user session id
                '1',    // user permission id
                '1',    // user group id
                '?',    // [s] (username)
                '?',    // [s] (user password)
                'null', // Avatar
                '?',    // [s] (user email)
                '?',    // [i] (Date of birth)
                time()  // Date of register
                );

// The values to be bound (mostly because they are user submitted)
$vars = array($vars['form']['username'],
              $pass,
              $vars['form']['email'],
              $dob
             );

// No errors occurred... we may go ahead and insert the user into the database
$stmt = $db->insert(USER_TABLE, $user_table_schema, $values, 'sssi', $vars);

And I'm getting the following error!
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in C:\xampp\htdocs\www\cms\includes\mmysqli.php on line 406

$refArray shows as:
Array
(
  [0] => sssi
  [1] => userName
  [2] => passWord
  [3] => email@somesite.com
  [4] => 651189600
)

The thing is, I'm doing this exact method to bind_params elsewhere and it works well there. Here is the function that I'm using this thing at:
PHP
public function build_query($sql)
{
    // Checking if $sql was an array
    if(!is_array($sql))
    {
        if($this->silent === false)
        {
            trigger_error('The variable $sql is not an array ', E_USER_ERROR);
        }
        return false;
    }
    
    // Setting a default where clause
    $where = array(null,null,array(),null);
    
    // Checking the WHERE clause
    if(isset($sql[2]) && is_array($sql[2]))
    {
        // Getting our WHERE clause generated
        $where = $this->build_where($sql[2]);
    }
    
    // Checking the ORDER BY clause
    $orderby = ((isset($sql[3])) ? ' ORDER BY ' . trim($sql[3]) : null);
    
    // Checking the LIMIT clause
    $limit = ((isset($sql[4])) ? ' LIMIT ' . trim($sql[4]) : null);
    
    // The generated SQL ready to be prepared and bound (if need be for either)
    $sql = "SELECT {$sql[0]} FROM `{$sql[1]}`{$where[0]}{$orderby}{$limit}";
    
    // Checking if the built query is of correct format
    if($this->valid_query($sql))
    {
        // Initiating the mysqli statement
        $stmt = $this->mysqli_link->stmt_init();
        
        // Setting the last sql used
        $this->last_sql = $sql;
        
        // Preparing the statement
        $stmt->prepare($sql) or die($stmt->error);
        
        // Making sure we have anything to bind
        if(!empty($where[2]))
        {
            // The arguments array
            $array = array(array($where[1]), $where[2]);
            
            // Merging all of the arrays into one array
            $array = call_user_func_array("array_merge", $array);
            
            // The reference array being created
            $refArray = $this->make_ref($array);
            
            // Initiating the mysqli_stmt VIA ReflectionClass
            $ref = new ReflectionClass('mysqli_stmt');
            
            // Getting the bind_param function
            $method = $ref->getMethod("bind_param");
            
            // Invoking the function
            $method->invokeArgs($stmt, $refArray);
        }
        
        // The last stmt object we used
        $this->last_stmt = $stmt;
        
        // Returning the built and prepared SQL query
        return $stmt;
    }
    else
    {
        // There was an error in the SQL Generation, return false
        return false;
    }
}

It works in build_query() but not in insert()!

I have 4 question marks (for binding), 4 types (sssi) and 4 parameters (types and parameters in $refArray)... everything matches... maybe MySQLi forgot how to do math?
Posted

1 solution

I figured it out! I had quotes around the question mark in the generated SQL... so to the SQL, I didn't have any parameters to bind in the SQL. Thanks for checking it out though!

Here is the updated function... not sure how neat it is, but it's functional. Going to try and see if I could optimize it a bit later.

PHP
public function insert($tbl_name, $fields, $values, $types, $vars)
{
    // Initiating our insert SQL
    $sql = "INSERT INTO `$tbl_name`";
    
    // Generating the fields
    $sql .= " (`" . implode("`, `", $fields) . "`)";
    
    // Generating the values of the SQL
    $sql .= " VALUES (";
    
    // Counting the number of values we've got here
    $num_vals = count($values);
    
    // Resetting the counter
    $counter = 1;
    
    // Looping through the values to retrieve the column values
    foreach($values as $column_value)
    {
        // Making sure we keep the datatype of the values
        if($column_value == "?")
        {
            $sql .= $column_value;
        }
        elseif(is_string($column_value))
        {
            $sql .= (string) "'{$column_value}'";
        }
        else
        {
            $sql .= (($column_value === null) ? 'null' : (($column_value === false) ? 'false' : $column_value));
        }
        
        // Making sure we put commas where appropriate
        if($counter !== $num_vals)
        {
            $sql .= ', ';
        }
        
        // Increasing the counter
        ++$counter;
    }
    
    // Finishing up the SQL
    $sql .= ')';
    
    // Initiating the mysqli statement
    $stmt = $this->mysqli_link->stmt_init();
    
    // Setting the last sql used
    $this->last_sql = $sql;
    
    // Preparing the statement
    $stmt->prepare($sql) or die($stmt->error);
    
    // The variable array ([0] => $types, [1+] $vars)
    $array = array(array($types), $vars);
    
    // Merging all of the arrays into one array
    $array = call_user_func_array('array_merge', $array);
    
    // The reference array being created
    $refArray = $this->make_ref($array);
    
    // Initiating the mysqli_stmt VIA ReflectionClass
    $ref = new ReflectionClass('mysqli_stmt');
    
    // Getting the bind_param function
    $method = $ref->getMethod('bind_param');
    
    // Invoking the function (actually binding here)
    $method->invokeArgs($stmt, $refArray);
    
    // Saving the current STMT so we could use it later
    $this->last_stmt = $stmt;
    
    // Checking against errors in the execution of the SQL
    if(!$stmt->execute())
    {
        // There was an error
        throw die($stmt->error);
    }
    
    // Returning true on success
    return true;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900