I have a factory called ProductFactory
I can create a product like so:
$product = ProductFactory::getProduct($id);
Now depending on what type of product we are getting, this function may return a class of type Product
or a des开发者_JS百科cendant or Product
.
But using the method above, the $product
class would be responsible for connecting to the database and retrieving its data.
So if I were to select 20 products to be displayed on a category list, I would have to first get a list of all the ID's then call the above function 20 times. This would be 21 calls to the database.
So I added another function to my factory like so:
$product = ProductFactory::createProduct($data);
This does the same thing, except you pass in the data from the database, saving the $product
class from having to make the trip. (depending on what data you pass, the factory will return the right type of class).
So now I want to make one call to select all products data and FETCH_INTO
my factory to generate a $product object for each row.
How can I do that?
update
Here is what I tried that did not work:
$stmt->setFetchMode(PDO::FETCH_INTO,ProductFactory::createProduct);
foreach($stmt as $product)
{
echo get_class($product) . '<br>';
}
You could use PDO::FETCH_CLASSTYPE for something like
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
initDemo($pdo);
$result = $pdo->query("SELECT IF(x,'Product','ProductXVal'), id, x FROM soTest");
while ( $obj=$result->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE) ) {
echo get_class($obj), "\n";
}
class Product {
public function id() { return $this->id; }
}
class ProductXVal extends Product {
public function x() { return $this->x; }
}
function initDemo($pdo) {
$pdo->exec('CREATE TEMPORARY TABLE soTest (id int auto_increment, x int, primary key(id))');
$pdo->exec('INSERT INTO soTest (x) VALUES (1),(NULL),(2),(NULL),(3),(NULL)');
}
which prints
Product
ProductXVal
Product
ProductXVal
Product
ProductXVal
but that seems rather ...odd to say the least.
I'd rather fetch the data as an array and then pass it to a factory that creates the appropriate object. You could do so in a class derived from PDO and/or PDOStatement.
According to the comments section on the PDOStatement->fetch() page, you should do this:
$stmt->setFetchMode(PDO::FETCH_INTO, new myClass());
$stmt->execute();
while ($object = $stmt->fetch())
{
$result[] = clone $object;
}
So differences there are
- You're passing fetch_into a method rather than an existing object
- You're not executing the statement (in your example, at least)
- You didn't include a call to fetch() in your loop
- You're not cloning the object
Now I don't know if it'll work with a factory method instead of an existing object, but calling execute() and fetch() is the least you can do :)
精彩评论