PDO FETCH_INTO Заводская?

У меня есть фабрика ProductFactory

Я могу создать такой продукт:

$product = ProductFactory::getProduct($id);

Теперь, в зависимости от того, какой тип продукта мы получаем, эта функция может возвращать класс типа Product, потомка или Product.

Но при использовании описанного выше метода класс $product будет отвечать за подключение к базе данных и получение ее данных.


Поэтому, если бы я выбрал 20 продуктов для отображения в списке категорий, мне пришлось бы сначала получить список всех идентификаторов, а затем вызвать указанную выше функцию 20 раз. Это будет 21 обращение к базе данных.

Итак, я добавил в свою фабрику еще одну функцию:

$product = ProductFactory::createProduct($data);

Это делает то же самое, за исключением того, что вы передаете данные из базы данных, избавляя класс $product от необходимости совершать поездку. (в зависимости от того, какие данные вы передаете, фабрика вернет правильный тип класса).

Итак, теперь я хочу сделать один вызов, чтобы выбрать все данные о продуктах и ​​FETCH_INTO мою фабрику, чтобы сгенерировать объект $ product для каждой строки.

Как я могу это сделать?

Обновить

Вот то, что я пробовал, но не помогло:

$stmt->setFetchMode(PDO::FETCH_INTO,ProductFactory::createProduct);
foreach($stmt as $product)
{
    echo get_class($product) . '<br>';
}

person JD Isaacks    schedule 01.10.2010    source источник
comment
Не могли бы вы уточнить последнюю часть: чем вы хотите заниматься? В частности, на какую часть вашего вопроса не отвечает php.net/manual/en/ pdostatement.fetch.php?   -  person Michael Clerx    schedule 01.10.2010


Ответы (2)


Вы можете использовать PDO :: FETCH_CLASSTYPE для чего-то вроде

<?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)');
}

который печатает

Product
ProductXVal
Product
ProductXVal
Product
ProductXVal

но это кажется довольно ... странным, мягко говоря.
Я бы предпочел получить данные в виде массива, а затем передать их фабрике, которая создает соответствующий объект. Вы можете сделать это в классе, производном от PDO и / или PDOStatement.

person VolkerK    schedule 01.10.2010
comment
Думаю, я просто сделаю то, что вы порекомендуете в конце .. fetch the data as an array and then pass it to a factory .. Кажется, наиболее прямолинейно. - person JD Isaacks; 01.10.2010

Согласно разделу комментариев на странице PDOStatement-> fetch (), вы должны сделать это:

$stmt->setFetchMode(PDO::FETCH_INTO, new myClass());
$stmt->execute();
while ($object = $stmt->fetch())
{
  $result[] = clone $object;
}

Так что различия есть

  1. Вы передаете fetch_in методу, а не существующему объекту
  2. Вы не выполняете инструкцию (по крайней мере, в вашем примере)
  3. Вы не включили вызов fetch () в свой цикл
  4. Вы не клонируете объект

Теперь я не знаю, будет ли он работать с фабричным методом вместо существующего объекта, но вызов execute () и fetch () - это меньшее, что вы можете сделать :)

person Michael Clerx    schedule 01.10.2010
comment
Выполняет ли вызов foreach () над оператором? Я никогда не замечал, что PDOStatement реализует Traversable ... - person Michael Clerx; 01.10.2010
comment
Нет и да, execute () выполняет оператор и реализует Traversable ;-) - person VolkerK; 01.10.2010