0

I am trying to create a PHP array of random "fruits" from a database.

The database class that I am using:

class Db
{

private static $_instance = null;
private $_pdo;

private function __construct()
{
    try {

        $this->_pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME .'', DB_USER, DB_PASS);
    } catch (PDOException $e) {
        die($e->getMessage());
    }
}

public static function getInstance()
{
    if (!isset(self::$_instance)) {
        self::$_instance = new Db();
    }

    return self::$_instance;
}

public function prepare($sql)
{
    return $this->_pdo->prepare($sql);
}

}

The class that is using the database to fetch "fruits" to create an array of a given size of random entries by using 3 seperate queries to calculate and retrieve "x" number of random items form the database.

class FruitBasket
{

private $_fruitArray = array(),
        $_inputCode,
        $_db;

public function __construct($input = null)
{
    $this->_inputCode = $input;
    $this->_db = Db::getInstance();
    var_dump($this->_db);
}

public function pickFruit($count)
{
    $doubleCount = $count * 2;//double the count used in calculation with the random number
    $fruitIDs = ''; //the choosen fruits (id's)
    $i = 0;

    //#1 get total count of fruits table
    $sql = "SELECT COUNT(*) FROM `fruits`";

    if ($query = $this->_db->prepare($sql)) {

        if ($query->execute()) {

            $allFruits = $query->fetch(PDO::FETCH_NUM);

        } else {

            print_r("ERROR QUERY DID NOT EXECUTE #1");
        }

    } else {

        print_r("ERROR CHECK SQL SYNTAX #1");
    }

    //#2 calculate random number to pull from all of id's
    $sql = "SELECT id FROM `fruits` WHERE RAND()* ? <  ? ORDER BY RAND() LIMIT 0, ? ";

    if ($query = $this->_db->prepare($sql)) {

        $query->bindParam(1, $allFruits[0], PDO::PARAM_INT);
        $query->bindParam(2, $doubleCount, PDO::PARAM_INT);
        $query->bindParam(3, $count, PDO::PARAM_INT);

        if ($query->execute()) {

            while ($row = $query->fetch(PDO::FETCH_ASSOC)) {

                if ($i == 0) {

                    $fruitIDs .= "'" .  $row['id'] . "'";

                } else {

                    $fruitIDs .= ", '" . $row['id'] . "'";
                }

                $i++;
            }

        } else {

            print_r("ERROR QUERY DID NOT EXECUTE #2");
        }

    } else {

        print_r("ERROR CHECK SQL SYNTAX #2");
    }

    //#3 get the fruits
    $sql="SELECT NAME FROM `fruits` WHERE `id` IN( ? )";

    if ($query = $this->_db->prepare($sql)) {

        $query->bindParam(1, $fruitIDs, PDO::PARAM_STR);

        if ($query->execute()) {

            while ($row = $query->fetch(PDO::FETCH_ASSOC)) {

                $this->_fruitArray[] = $row['name'];
            }

        } else {

            print_r("ERROR QUERY DID NOT EXECUTE #3");
        }

    } else {

        print_r("ERROR CHECK SQL SYNTAX #3");
    }

    return $this->_fruitArray;
}
}

The table that I am attempting has a bunch of "fruits" in it, an example of how the table is structured:

==================================
| ID | NAME                      |
==================================
| 01 | Apple                     |
==================================

I am attempting to test this all out by using the following:

echo "<pre>";

echo "TESTING FRUIT ARRAY:</br></br>";

$basket = new FruitBasket();

echo"</br></br> PRINT_R: </br></br>";

print_r($basket->pickFruit(10));

echo "</br></br> VARDUMP: </br></br>";

var_dump($basket->pickFruit(10));

The sql query prepares and executes properly, I can do a vardump of the prepares and the binds and they return TRUE. Nothing is returned on the last query however.

In the first query that executes Doing a print statement of $allFruits shows the correct total count from the table.

The second query seems to be working properly,the string $fruitIDs, gets random id's from the table, I can echo this out and confirm that indeed the correct number of ID's are returned.

The problem occurs (I think) with the third query:

Nothing is returned form this query. The prepare statement returns true on a var dump as does the execute, however there is no results!

If I manually take the ID's that are output from query#2 and run it myself in mysql, the correct "fruit" names are returned.

Am I binding the variables incorrectly? I read the pages from the PHP manual but clearly I am doing something wrong.

Please help! :)

Shanedroid
  • 36
  • 1
  • 4
  • 2
    http://stackoverflow.com/questions/15990857/reference-frequently-asked-questions-about-pdo#15991146 – Your Common Sense Apr 01 '14 at 21:19
  • You may want to remove a lot of your code that your sure could not be causing the problem (like most of your list of fruits). You got a lot to read here. . . – rhill45 Apr 01 '14 at 21:23
  • Great point buzrw, I have omitted some of what I posted previously, just didn't want to be one of the questions with insufficient information posted. – Shanedroid Apr 02 '14 at 00:16
  • THanks Your Common Sense! I would not have even thought to check that! It appears as thought his may solve my problem? https://stackoverflow.com/questions/15990857/reference-frequently-asked-questions-about-pdo#15991146 I will attempt this as a fix at once :D – Shanedroid Apr 02 '14 at 00:28

1 Answers1

0

Thanks to the links and input provided by Your common sense, using the following:

Reference - frequently asked questions about PDO

and

Can I bind an array to an IN() condition?

I was able to resolve this by changing my query as follows:

//#2 calculate random number to pull from all of id's
        $sql = "SELECT id FROM `fruits` WHERE RAND()* ? <  ? ORDER BY RAND() LIMIT 0, ? ";

        if ($query = $this->_db->prepare($sql)) {

            $query->bindParam(1, $allFruits[0], PDO::PARAM_INT);
            $query->bindParam(2, $doubleCount, PDO::PARAM_INT);
            $query->bindParam(3, $count, PDO::PARAM_INT);

            if ($query->execute()) {

                while ($row = $query->fetch(PDO::FETCH_ASSOC)) {

                        $fruitIDs[] = $row['id'];
                }

            } else {

                print_r("ERROR QUERY DID NOT EXECUTE #2");                }

        } else {

            print_r("ERROR CHECK SQL SYNTAX #2");
        }

        //#3 get the fruits
        $inQuery = implode(',', array_fill(0, count($fruitIDs), '?'));

        $sql="SELECT NAME FROM `fruits` WHERE `id` IN($inQuery)";

        if ($query = $this->_db->prepare($sql)) {

            if ($query->execute($fruitIDs)) {

                while ($row = $query->fetch(PDO::FETCH_NUM)) {

                     $this->_fruitArray[] = $row[0];
                }

            } else {

                print_r("ERROR QUERY DID NOT EXECUTE #3");
            }

        } else {

            print_r("ERROR CHECK SQL SYNTAX #3");
        }

        return $this->_fruitArray;
    }

I do not fully understand the security benefits or ramifications of binding the parameters or simply including them in the actual execute() but for now the query is performing as intended, so thank you for the input!

Shanedroid
  • 36
  • 1
  • 4