简体   繁体   中英

PDO Connection Error Within Recursive PHP Function

I've written the following function that pulls a handful of items at random from a store. The final array of items will be roughly within $50 of a value the user puts in (in this case $300).

<? 
include $_SERVER['DOCUMENT_ROOT'] . '/../../pdocon.inc.php'; 
$pdo->exec("USE database_waww");

$userValue = 300;
$resultArray = array();

function pullItem($spaceleft,&$resultArray){
    global $pdo;

    if ($spaceleft > 50) {
        $getItem=$pdo->query("SELECT id,price FROM items WHERE price < $spaceleft ORDER BY rand() LIMIT 1");
        $itemFound = $getItem->rowCount();

        if ($itemFound == 1) {
            $results = $getItem->fetchAll();
            foreach ($results as $row){
                $spaceleft = $spaceleft-$row["price"];
                $resultArray[]=$row["id"];
                pullItem($spaceleft,$resultArray);
            }
        }
    }
    else {
        $spaceleft = 0;
        pullItem($spaceleft,$resultArray);}
    }
    return $resultArray;
}

$findAllItems = pullItem($userValue,$resultArray);
print_r($findAllItems);
?>

I'm having trouble with the PDO connection in the recursive function. After running the function a handful of times, it returns the following:

PHP Warning:  PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1461 Can't create more than max_prepared_stmt_count statements (current value: 16382)

I believe this is because the pdo connections multiply during the recursion, but I'm not sure. How do I prevent this from happening?

Try using $getItem->closeCursor() before each recursive call to pullItem or else you will have a multitude of unfetched rows from the prepared results. If you still need to fetch items from $getItem , you should instead populate them into an array using fetchAll rather than burdening PDO with a multitude of unfetched results. You should be aware of memory limits at that point, however.

function pullItem($spaceleft,&$resultArray){
    global $pdo;

    if ($spaceleft > 50) {
        $getItem=$pdo->query("SELECT id,price FROM items WHERE price < $spaceleft ORDER BY rand() LIMIT 1");
        $itemFound = $getItem->rowCount();

        if ($itemFound == 1) {
            $results = $getItem->fetchAll();
            $getItem->closeCursor();
            unset($getItem);
            foreach ($results as $row) {
                $spaceleft = $spaceleft-$row["price"];
                $resultArray[]=$row["id"];
                pullItem($spaceleft,$resultArray);
        } else { // In case ($itemFound == 1) isn't satisfied
            $getItem->closeCursor();
            unset($getItem);
        }
    }
    else {
        $spaceleft = 0;
        pullItem($spaceleft,$resultArray);}
    }
    return $resultArray;
}

You should also be safely binding your user-input values to the queries to prevent SQL injection and fully utilize the PDO library

Destroy some old statement object .Try unsetting $getItem

here :

if ($spaceleft > 50) {
 unset($getItem);
 // ... Further code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM