Jump to content

Archived

This topic is now archived and is closed to further replies.

karin

"Couldn't fetch mysqli" error, but connection isn't closed

Recommended Posts

Hello all, I'm an amateur at PHP coding, and am currently enrolled in a PHP and MySQL class that uses the PHP Programming with MySQL textbook, by Don Gosselin. I'm trying to get this simple Shopping Cart script to work, because it's the step-by-step example script for Chapter 11, but I keep getting the following errors on ShowCart.php when I try to add an item to the cart.

Warning: mysqli_query() [function.mysqli-query]: Couldn't fetch mysqli in C:\xampplite\htdocs\ShoppingCart.php  on line 78

 

Warning: mysqli_errno() [function.mysqli-errno]: Couldn't fetch mysqli in C:\xampplite\htdocs\ShoppingCart.php on line 80

 

Warning: mysqli_error() [function.mysqli-error]: Couldn't fetch mysqli in C:\xampplite\htdocs\ShoppingCart.php on line 81

 

Line 78:

        $QueryResult = mysqli_query($this->DBConnect, $SQLstring)

 

Line 80 and 81:

            . "<p>Error code " . mysqli_errno($this->DBConnect)
            . ": " . mysqli_error($this->DBConnect)) . "</p>";

 

I've read "Couldn't fetch mysqli" errors are because the connection was closed prior to those lines, but I don't see any indication of a connection closure. I have no idea what to do, as all the code was given to me in the book, I merely copied it down.

 

Here's the ShoppingCart.php code:

<?php
class ShoppingCart {
    private $DBConnect = "";
    private $DBName = "";
    private $TableName = "";
    private $Orders = array();
    private $OrderTables = array();
function construct() {
    $this->DBConnect = mysqli_connect("localhost", "root", "passHere");
    if (mysqli_connecT_errno())
        die("<p>Unable to connect to the database server.</p>"
        . "<p>Error code " . mysqli_connect_errno()
        . ": " . mysqli_connect_error()) . "</p>";
}

public function setDatabase($Database) {
    $this->DBName = $Database;
    $this->DBConnect->select_db($this->DBName)
        Or die("<p>Unable to select the databbase.</p>"
        . "<p>Error code " . mysqli_errno($this->DBConnect)
        . ": " . mysqli_error($this->DBConnect)) . "</p>";
}
public function setTable($Table) {echo $table."<br />";
    $this->TableName = $Table;
}
public function getProductList() {
    $SQLstring = "SELECT * FROM $this->TableName";
    $QueryResult = $this->DBConnect->query($SQLstring)
        Or die("<p>Error code " . mysqli_errno($this->DBConnect)
        . ": " . mysqli_error($DBConnect)) . "</p>";
    echo "<table width='100%' border='1'>";
    echo "<tr><th>Product</th><th>Description</th><th>Price Each</th><th>Select Item</th></tr>";
    $Row = $QueryResult->fetch_row();
    do {
        echo "<tr><td>{$Row[1]}</td>";
        echo "<td>{$Row[2]}</td>";
        printf("<td align='center'>$%.2f</td>", $Row[3]);
        echo "<td align ='center'>
              <a href='ShowCart.php?PHPSESSID=" . session_id()
              . "&operation=addItem&productID=" . $Row[0]
              . "'>Add</a></td></tr>";
        $Row = $QueryResult->fetch_row();
    } while ($Row);
    echo "</table>";
}
public function addItem() {
    $ProdID = $_GET['productID'];
    if (array_key_exists($ProdID, $this->Orders))
        exit("<p>You already selected that item! Click your
             browser's back button to return to the
             previous page.</p>");
    $this->Orders[$ProdID] = 1;
    $this->OrderTable[$ProdID] = $this->TableName;
}
function _wakeup() {
    $this->DBConnect = new mysqli("localhost", "staticlo_shane", "shinfoosh");
    if (mysqli_connect_errno())
        die("<p>Unable to connect to the database server.</p>"
        . "<p>Error code " . mysqli_connect_errno()
        . ": " . mysqli_connect_error()) . "</p>";
    $this->DBConnect->Select_db($this->DBName)
        Or die("<p>Unable to select the database.</p>"
        . "<p>Error code " . mysqli_errno($$this->DBConnect)
        . ": " . mysqli_error($this->DBConnect)) . "</p>";
}
public function showCart() {
    if (empty($this->Orders))
        echo "<p>Your shopping cart is empty!</p>";
    else {
        echo "<table width='100%' border='1'>";
        echo "<tr><th>Remove Item</th><th>Product</th><th>Quantity</th><th>
              Price Each</th></tr>";
        $Total = 0;
    foreach($this->Orders as $Order) {
        $SQLstring = "SELECT * FROM "
            . $this->OrderTable[key($this->Orders)] . "
            WHERE productID='" . key($this->Orders) . "'";
        $QueryResult = mysqli_query($this->DBConnect, $SQLstring)
            Or die("<p>Unable to perform the query.</p>"
            . "<p>Error code " . mysqli_errno($this->DBConnect)
            . ": " . mysqli_error($this->DBConnect)) . "</p>";
        $Row = mysqli_fetch_row($QueryResult);
        echo "<td align='center'>";
        echo "<a href='ShowCart.php?PHPSESSID=" . session_id()
              . "&operation=removeItem&productID=" . $Row[0]
              . "'>Remove</a></td>";
        echo "<td>{$Row[1]}</td>";
        echo "<td align='center''>$Order ";
	echo "<a href='ShowCart.php?PHPSESSID=" . session_id() . "&operation=addOne&productID=" . $Row[0] . "'>Add</a>";
	echo "<a href='ShowCart.php?PHPSESSID=" . session_id() . "&operation=removeOne&productID=" . $Row[0] . "'>Remove</a>";
        echo "</td>";
        printf("<td align='center'>$%.2f</td></tr>", $Row[3]);
        $Total += $Row[3] * $Order;
        next($this->Orders);

        echo "<td align='center' colspan='2'><strong>Your shopping
              cart contains " . count($this->Orders)
              . " product(s).</strong></td>";
        printf("<td align='center'><strong>Total: $%.2f</stong>
               </td>", $Total);
        echo "</table>";
    }
    echo "<tr><td align='center'><a href='ShowCart.php?PHPSESSID="
          . session_id() . "&operation=emptyCart'><strong>
          Empty Cart</strong></a></td>";
    }
}
public function removeItem() {
    $ProdID = $_GET['productID'];
    unset($this->Orders[$ProdID]);
    unset($this->OrderTable[$ProdID]);
}
function emptyCart() {
    $this->Orders = array();
    $this->OrderTale = array();
}
function _destruct() {
    $this->DBConnect->close();
}

public function addOne() {
$ProdID = $_GET['productID'];
$this->Orders[$ProdID] += 1;
}

public function removeOne() {
$ProdID = $_GET['productID'];
$this->Orders[$ProdID] -= 1;
if ($this->Orders[$ProdID] == 0)
	$this->removeItem();
}

}
?> 

 

Here is the ShowCart.php code:

<?php
session_start();
require_once("ShoppingCart.php");
if (!isset($_SESSION['curCart']))
header("location:GosselinGourmetGoods.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title></title>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<meta name="Robots" content="nofollow, noindex" />
	<link rel="stylesheet" type="text/css" media="screen" href="php_styles.css" />
</head>
<body>
<h1>Gosselin Gourmet Goods</h1>
<h2>Shop by Category</h2>
<p><a href="GosselinGourmetCoffees.php">Gourmet Coffees</a><br />
<a href="GosselinGourmetOlives.php">Specialty Olives</a><br />
<a href="GosselinGourmetSpices.php">Gourmet Spices</a></p>

<?php
$Cart = unserialize($_SESSION['curCart']);
if (isset($_GET['operation'])) {
	if ($_GET['operation'] == "addItem")
		$Cart->addItem();
	if ($_GET['operation'] == "removeItem")
		$Cart->removeItem();
	if ($_GET['operation'] == "emptyCart")
		$Cart->emptyCart();
	if ($_GET['operation'] == "addOne")
		$Cart->addOne();
	if ($_GET['operation'] == "removeOne")
		$Cart->removeOne();
}
$Cart->showCart();
$_SESSION['curCart'] = serialize($Cart);
?>
</body>
</html>

 

Here is the product page for "Specialty Olives" which is identical to the Coffees and Spices pages, save for the Table name changed to their respective products:

<?php
session_start();
require_once("ShoppingCart.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>Gosselin Gourmet Goods</title>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<meta name="Robots" content="nofollow, noindex" />
	<link rel="stylesheet" type="text/css" media="screen" href="php_styles.css" />
</head>
<body>
<h1>Gosselin Gourmet Goods</h1>
<h2>Shop by Category</h2>
<p><a href="GosselinGourmetCoffees.php">Gourmet Coffees</a><br />
<a href="GosselinGourmetOlives.php">Specialty Olives</a><br />
<a href="GosselinGourmetSpices.php">Gourmet Spices</a></p>

<h2>Speciality Olives</h2>
<?php

$Database = "gosselin_gourmet";
$Table = "olives";

$Cart=!empty($_SESSION['curCart'])?unserialize($_SESSION['curCart']):new ShoppingCart();
$Cart->construct();
$Cart->setDatabase($Database);
$Cart->setTable($Table);
$Cart->getProductList();
$_SESSION['curCart'] = serialize($Cart);
?>
<p><a href='<?php echo "ShowCart.php?PHPSESSID=" . session_id() ?>'>Show Shopping Cart</a></p>
</body>
</html>

Share this post


Link to post
Share on other sites

That code is mixing a procedural mysqli_connect() function call with OOP mysqli methods. That does not work.

 

However, the function _wakeup() is using the correct OOP method to create an instance of the mysqli class, but the code you have shown where the error is occurring at is back using procedural function calls (which again cannot be mixed with an OOP instance of the mysqli class.) Any chance the code has been modified from the original? In its' current state, it will never work.

 

To fix the code, you will need to either pick procedural or OOP for msyqli and use that throughout all the code.

Share this post


Link to post
Share on other sites

The notes below might not explain the OP's case, but I'm posting here because this thread came up prominently when I was searching for a solution to my own problem and this may help others.

 

I have a shopping cart object stored serialized in a database session. This object has a mysqli object as a property, which is left open for reuse.

I was getting the "Couldn't fetch" error every time a new Ajax call tried to access the mysqli object (with OOP) (unless this was a brand new session and the mysqli object had only just been created).

I think the problem is that the database connection is lost between Ajax calls. I have solved it for now by adding a destructor to the cart object, which does mysqli->close() (if the object exists - my cart only instantiates it if needed, not in the cart constructor).

I haven't checked, but it might also be possible to solve the problem with __sleep. Or you could just be more ruthless and ensure that you never ever leave the mysqli object open.

Share this post


Link to post
Share on other sites

@phpsort,

 

Database connections are resources and are automatically destroyed when the processing on any page request ends. You must create a new connection on each page request (or get one of the available persistent connections on each page request.)

Share this post


Link to post
Share on other sites

Thanks PFMaBiSmAd.

I realise that now, but it certainly wasn't an obvious cause when I was searching for the meaning of the Can't fetch message! The message is not exactly helpful, but PHP doesn't plan to change the system soon - see http://bugs.php.net/bug.php?id=51818

 

I've only just moved to mysqli, and what's missing from the PHP site is a thorough overview and definitions of the basic concepts, such as 'connection', 'statement', 'result'. The PHP notes are often woolly, misleading or just totally missing. If you know of a 'Mysqli for intelligent dummies' article, let me know!

Ian

Share this post


Link to post
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.