0

I created the MySQLi query function below, and it works great with SELECT queries and does everything dynamically so it can work with result sets of any size, but when I try INSERT INTO, I get the message Fatal error: Call to a member function fetch_field() on boolean. I want it to return TRUE or FALSE for queries like INSERT INTO, UPDATE, etc. based on if the query was successful or not. Any suggestions?

Here's the full query function:

    /**
     * Querying the database
     *
     * @param string $query_string The query string to be executed
     * @param array $params The parameters for the query if it is a prepared statement
     *
     * @return mixed The results of the query, either in an array or NULL, or FALSE if executing the query failed
     */
    final public function query($query_string, $params = array()) {

        // Resetting error and result data
        $this->error = FALSE;
        $this->result = array();
        $this->result_metadata = array();

        // Initiating the query statement
        $this->stmt = $this->DB->stmt_init();

        // Preparing the query statement and binding parameters if provided
        if ($this->stmt->prepare($query_string) and count($params)) {

            // Setting the types of each parameter in $params
            $param_types = "";
            foreach ($params as $param) {
                if (is_int($param)) {
                    $param_types .= "i"; continue;
                }
                if (is_float($param)) {
                    $param_types .= "d"; continue;
                }
                if (is_string($param)) {
                    $param_types .= "s"; continue;
                }
                else {
                    $param_types .= "b";
                }
            }

            // Appending the parameter types to the beginning of $params for use in call_user_func_array
            array_unshift($params, $param_types);

            // Creating a reference array and passing all values from $params into it by reference
            $reference = array();
            foreach ($params as $key => $param) {
                $reference[$key] = &$params[$key];
            }

            // Binding the parameters to the query statement
            call_user_func_array(array($this->stmt, "bind_param"), $reference);
        }

        // Executing the query statement
        if (@$this->stmt->execute()) {

            // Fetching the metadata of the result
            $this->result_metadata = $this->stmt->result_metadata();

            // Populating $fields with variables whose name is the value of $field_name indexed under $field_name
            while ($field = $this->result_metadata->fetch_field()) {
                $field_name = $field->name;
                $$field_name = NULL;
                $fields[$field_name] = &$$field_name;
            }

            // Binding the results of the query to $fields
            call_user_func_array(array($this->stmt, "bind_result"), $fields);

            // Storing the results of the query
            $this->stmt->store_result();

            // Fetching the results of the query and storing them in $result_array
            $row = 0;
            while ($this->stmt->fetch()) {
                $result_array[$row] = array();
                foreach ($fields as $key => $field) {
                    $result_array[$row][$key] = $field;
                }
                $row++;
            }

            // Storing the number of rows to self::$num_rows
            $this->num_rows = $this->stmt->num_rows;                

            // Closing the query statement
            $this->stmt->free_result();
            $this->stmt->close();

            // Returning $result_array, or the only element of $result_array if $result_array is of size 1
            return @((count($result_array) === 1) ? $result_array[0] : $result_array);
        }

        // Setting $this->error equal to the DB error and returning FALSE
        else {
            $this->error = $this->DB->error;
            return FALSE;
        }

    }

1 Answer 1

1

According to the docs, the result_metadata function will only return an object if the query returns a result set. Since an INSERT query only reports success/failure, result_metadata only returns false. See this answer for more details.

But since it only returns FALSE, you can't call fetch_field on it, of course.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect, thanks! I modified the code to detect if $this->result_metadata is FALSE and return if it is. Works flawlessly now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.