Fatal error: Call to a member function fetch_assoc() on boolean

Hi

i have been trying to create a code with pdo that can store items orders in a cart with sessions. but i have been getting errors like
Fatal error: Call to a member function fetch_assoc() on boolean, please can someone help me out. there is my code

cartAction.php

<?php
// initialize shopping cart class
include 'Cart.php';
$cart = new Cart;


// include database configuration file
require_once 'dbConfig2.php';
if(isset($_REQUEST['action']) && !empty($_REQUEST['action'])){
    if($_REQUEST['action'] == 'addToCart' && !empty($_REQUEST['id'])){
        $productID = $_REQUEST['id'];
		
		 // get product details
       $query = $db->query("SELECT * FROM product WHERE id = ".$productID);
        $row = $query->fetch_assoc();
        $itemData = array(
            'id' => $row['id'],
            'name' => $row['name'],
			'name' => $row['title'],
            'price' => $row['price'],
            'qty' => 1
        );
        
        $insertItem = $cart->insert($itemData);
        $redirectLoc = $insertItem?'viewCart.php':'index.php';
        header("Location: ".$redirectLoc);
		
		
    }elseif($_REQUEST['action'] == 'updateCartItem' && !empty($_REQUEST['id'])){
        $itemData = array(
            'rowid' => $_REQUEST['id'],
            'qty' => $_REQUEST['qty']
        );
        $updateItem = $cart->update($itemData);
        echo $updateItem?'ok':'err';die;
		
		
    }elseif($_REQUEST['action'] == 'removeCartItem' && !empty($_REQUEST['id'])){
        $deleteItem = $cart->remove($_REQUEST['id']);
        header("Location: viewCart.php");
		
		
    }elseif($_REQUEST['action'] == 'placeOrder' && $cart->total_items() > 0 && !empty($_SESSION['userSession'])){
        // insert order details into database
        $insertOrder = $db->query("INSERT INTO orders (customer_id, total_price, created, modified) VALUES ('".$_SESSION['userSession']."', '".$cart->total()."', '".date("Y-m-d H:i:s")."', '".date("Y-m-d H:i:s")."')");
        
        if($insertOrder){
            $orderID = $db->insert_id;
            $sql = '';
            // get cart items
            $cartItems = $cart->contents();
            foreach($cartItems as $item){
                $sql .= "INSERT INTO order_items (order_id, product_id, quantity) VALUES ('".$orderID."', '".$item['id']."', '".$item['qty']."');";
            }
            // insert order items into database
            $insertOrderItems = $db->multi_query($sql);
            
            if($insertOrderItems){
                $cart->destroy();
                header("Location: orderSuccess.php?id=$orderID");
            }else{
                header("Location: checkout.php");
            }
        }else{
            header("Location: checkout.php");
        }
    }else{
        header("Location: index.php");
    }
}else{
    header("Location: index.php");
}

Cart.php

<?php session_start();
class Cart {
    protected $cart_contents = array();
    
    public function __construct(){
        // get the shopping cart array from the session
        $this->cart_contents = !empty($_SESSION['cart_contents'])?$_SESSION['cart_contents']:NULL;
		if ($this->cart_contents === NULL){
			// set some base values
			$this->cart_contents = array('cart_total' => 0, 'total_items' => 0);
		}
    }
    
    /**
	 * Cart Contents: Returns the entire cart array
	 * @param	bool
	 * @return	array
	 */
	public function contents(){
		// rearrange the newest first
		$cart = array_reverse($this->cart_contents);

		// remove these so they don't create a problem when showing the cart table
		unset($cart['total_items']);
		unset($cart['cart_total']);

		return $cart;
	}
    
    /**
	 * Get cart item: Returns a specific cart item details
	 * @param	string	$row_id
	 * @return	array
	 */
	public function get_item($row_id){
		return (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->cart_contents[$row_id]))
			? FALSE
			: $this->cart_contents[$row_id];
	}
    
    /**
	 * Total Items: Returns the total item count
	 * @return	int
	 */
	public function total_items(){
		return $this->cart_contents['total_items'];
	}
    
    /**
	 * Cart Total: Returns the total price
	 * @return	int
	 */
	public function total(){
		return $this->cart_contents['cart_total'];
	}
    
    /**
	 * Insert items into the cart and save it to the session
	 * @param	array
	 * @return	bool
	 */
	public function insert($item = array()){
		if(!is_array($item) OR count($item) === 0){
			return FALSE;
		}else{
            if(!isset($item['id'], $item['name'], $item['title'],$item['price'], $item['qty'])){
                return FALSE;
            }else{
                /*
                 * Insert Item
                 */
                // prep the quantity
                $item['qty'] = (float) $item['qty'];
                if($item['qty'] == 0){
                    return FALSE;
                }
                // prep the price
                $item['price'] = (float) $item['price'];
                // create a unique identifier for the item being inserted into the cart
                $rowid = md5($item['id']);
                // get quantity if it's already there and add it on
                $old_qty = isset($this->cart_contents[$rowid]['qty']) ? (int) $this->cart_contents[$rowid]['qty'] : 0;
                // re-create the entry with unique identifier and updated quantity
                $item['rowid'] = $rowid;
                $item['qty'] += $old_qty;
                $this->cart_contents[$rowid] = $item;
                
                // save Cart Item
                if($this->save_cart()){
                    return isset($rowid) ? $rowid : TRUE;
                }else{
                    return FALSE;
                }
            }
        }
	}
    
    /**
	 * Update the cart
	 * @param	array
	 * @return	bool
	 */
	public function update($item = array()){
		if (!is_array($item) OR count($item) === 0){
			return FALSE;
		}else{
			if (!isset($item['rowid'], $this->cart_contents[$item['rowid']])){
				return FALSE;
			}else{
				// prep the quantity
				if(isset($item['qty'])){
					$item['qty'] = (float) $item['qty'];
					// remove the item from the cart, if quantity is zero
					if ($item['qty'] == 0){
						unset($this->cart_contents[$item['rowid']]);
						return TRUE;
					}
				}
				
				// find updatable keys
				$keys = array_intersect(array_keys($this->cart_contents[$item['rowid']]), array_keys($item));
				// prep the price
				if(isset($item['price'])){
					$item['price'] = (float) $item['price'];
				}
				// product id & name shouldn't be changed
				foreach(array_diff($keys, array('id', 'name')) as $key){
					$this->cart_contents[$item['rowid']][$key] = $item[$key];
				}
				// save cart data
				$this->save_cart();
				return TRUE;
			}
		}
	}
    
    /**
	 * Save the cart array to the session
	 * @return	bool
	 */
	protected function save_cart(){
		$this->cart_contents['total_items'] = $this->cart_contents['cart_total'] = 0;
		foreach ($this->cart_contents as $key => $val){
			// make sure the array contains the proper indexes
			if(!is_array($val) OR !isset($val['price'], $val['qty'])){
				continue;
			}
	 
			$this->cart_contents['cart_total'] += ($val['price'] * $val['qty']);
			$this->cart_contents['total_items'] += $val['qty'];
			$this->cart_contents[$key]['subtotal'] = ($this->cart_contents[$key]['price'] * $this->cart_contents[$key]['qty']);
		}
		
		// if cart empty, delete it from the session
		if(count($this->cart_contents) <= 2){
			unset($_SESSION['cart_contents']);
			return FALSE;
		}else{
			$_SESSION['cart_contents'] = $this->cart_contents;
			return TRUE;
		}
    }
    
    /**
	 * Remove Item: Removes an item from the cart
	 * @param	int
	 * @return	bool
	 */
	 public function remove($row_id){
		// unset & save
		unset($this->cart_contents[$row_id]);
		$this->save_cart();
		return TRUE;
	 }
     
    /**
	 * Destroy the cart: Empties the cart and destroy the session
	 * @return	void
	 */
	public function destroy(){
		$this->cart_contents = array('cart_total' => 0, 'total_items' => 0);
		unset($_SESSION['cart_contents']);
	}
}


dbConfig2.php

<?php
//DB details
$dbHost = 'localhost';
$dbUsername = 'root';
$dbPassword = 'dresscode';
$dbName = 'hmsa';

//Create connection and select DB
$db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);

if ($db->connect_error) {
    die("Unable to connect database: " . $db->connect_error);
} 
?>

I always DEBUG using the following function:

function fred($val)
{
  echo '<pre>';
   print_r( $val );
  echo '</pre>';
}

// YOUR SCRIPT:
// get product details
  $sql = "SELECT * FROM product WHERE id = ".$productID;
fred( $sql ); die;

       $query = $db-&gt;query( $sql );
fred( $query ); die;

        $row = $query-&gt;fetch_assoc();
fred( $row ); die;
        $itemData = array(
            'id' =&gt; $row['id'],
            'name' =&gt; $row['name'],
			'name' =&gt; $row['title'],
            'price' =&gt; $row['price'],
            'qty' =&gt; 1
        );

Once you have established the $val displayed is correct then remove the function call to fred(…) and move on to the next potential problem.

thanks john… let me give it a trial

Hi john

when i debugged i got this

SELECT * FROM product WHERE id =
Notice: Undefined index: id in C:\xampp\htdocs\mywork\Pricorp\cstra8\products.php on line 591

also when i removed the fred() function and ran the code, i got this errors

Notice: Undefined variable: db in C:\xampp\htdocs\mywork\Pricorp\cstra8\cartAction.php on line 16

Fatal error: Call to a member function query() on null in C:\xampp\htdocs\mywork\Pricorp\cstra8\cartAction.php on line 16

John please help me is urgent
Thanks

It looks as though the $productID is NOT being passed.

Try this:

fred( $_REQUEST );die;
$productID = $_REQUEST['id'];

Edit:
For further information try replacing print_r( $val ); with var_dump( $val );


Edit:
I am off out for a late lunch, maybe another member can help?

thanks John but i got this output

array(5) {
[“action”]=>
string(9) “addToCart”
[“id”]=>
string(127) "
Notice: Undefined index: id in C:\xampp\htdocs\mywork\Pricorp\cstra8\products.php on line 591
"
[“Jeans”]=>
string(0) “”
[“Men”]=>
string(0) “”
[“100_00”]=>
string(0) “”
}

i have this piece of code in my submit button

<a class="btn btn-primary" href="cartAction.php?action=addToCart&id=<?php echo $row["id"];?>&name=<?php echo $row["name"];?>&title=<?php echo $row["title"];?>&price=<?php echo $row["price"];?>">Add to cart</a>

please help me John… i really need your help

@shell_inj3ctor: please be patient. Members here are all volunteers who help in their own time. As this is the weekend, there are fewer folk around and responses may be slower. @John_Betong has already told you he won’t be around for a while:

1 Like

I think there is a logic problem with the conditional

 if(!isset($item['id']
, $item['name']
, $item['title']
, $item['price']
, $item['qty'])){ 
return FALSE;

The comma separated variables are not evaluated as ORs but as ANDs
In this case, that return FALSE will only happen when all of those variables are !isset

That should be fixed, but why “id” is not defined will need to be determined as well.
If the code is expecting “id” to be in the REQUEST array it will need to be passed to the file as either a like-named form import or URL query string.

1 Like

thanks Mittineague for your reply, i already passed a URL query string inside the submit button like this below but i still get undefined index: id error… please how will i go about it

<a class="btn btn-primary" href="cartAction.php?action=addToCart&id=<?php echo $row["id"];?>&name=<?php echo $row["name"];?>&title=<?php echo $row["title"];?>">Add to cart</a>

When you look at the pages view-source, do all of the PHP echoes have expected values?

<a class="btn btn-primary" href="cartAction.php
?action=addToCart
&id=<?php echo $row["id"];?>
&name=<?php echo $row["name"];?>
&title=<?php echo $row["title"];?>">Add to cart</a>

@maittineague … yes am sure i have it in my products.php file and also when i debugged the code i get this notice

array(4) {
[“action”]=>
string(9) “addToCart”
[“id”]=>
string(127) "
Notice: Undefined index: id in C:\xampp\htdocs\mywork\Pricorp\cstra8\products.php on line 625
"
[“name”]=>
string(8) “Jeans”
[“title”]=>
string(10) “Men”
}

Try changing the SELECT to use specifically named fields. eg.

 $query = $db->query("SELECT id, name, title FROM product WHERE id = ".$productID);

On debug i got this

array(4) {
[“action”]=>
string(9) “addToCart”
[“id”]=>
string(127) "
Notice: Undefined index: id in C:\xampp\htdocs\mywork\Pricorp\cstra8\products.php on line 625
"
[“name”]=>
string(8) “Jeans”
[“title”]=>
string(10) “Men”
}

It is essential that you discover why Undefined index: id is missing.

It looks as though somewhere the user is selecting a product and the database query is not returning the relevant database → table → id.

Find where the product is being selected and also the SQL request and result.

Use fred(…) to confirm the result which I think will be $row and ensure the product id has been passed back from the query.

1 Like

You’re also a sitting duck for SQL Injection attacks as you’re letting user submitted data near the database without validating it. At the very least it should be validated and a prepared statement used

1 Like

thanks john i think the undefined index id is gone and i can see the value return without errors but it still says Fatal error: Call to a member function fetch_assoc() on boolean in… why

@SpacePhoenix… thanks i will validate just that i want the code to run properly before i validate… thanks alot for your advise