2

I have a PHP class called Product:

class Product {

   $id;
   $name;

}

And another class that get data from database:

$stm = $this->dsn->prepare($sql);

$stm->execute();

$rst = $stm->fetchAll(PDO::FETCH_ASSOC);

How can I convert this PDO resultset ($rst) to an array of objects Product?

Dharman
  • 30,962
  • 25
  • 85
  • 135
supdown
  • 33
  • 1
  • 3
  • I recommend you to use a good ORM for that reason. Also it makes your development faster. See http://propelorm.org/ for example – Ahmad Sep 16 '15 at 17:20

5 Answers5

5

Use the PDO::FETCH_CLASS argument.

class Product {
    public $id;
    public $name;
}

$stm = $this->dsn->prepare($sql);
$stm->execute();

$result = $stm->fetchAll( PDO::FETCH_CLASS, "Product" );

http://php.net/manual/en/pdostatement.fetchall.php

Danijel
  • 12,408
  • 5
  • 38
  • 54
  • By using `Product::class` instead of `"Product"`, one could avoid hard-coding the class name as a string. – Uwe Keim Jul 26 '22 at 06:04
1

Just change the way you're calling fetchAll()

$rst = $stm->fetchAll(PDO::FETCH_CLASS, 'Product');
Dharman
  • 30,962
  • 25
  • 85
  • 135
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

My approach in this case would be to use a helper function within the Product class that builds a new instance of the object and returns it provided the inputs from the PDO.

Such as

public static function buildFromPDO($data) {
    $product = new Product();
    $product->id = $data["id"];
    $product->name = $data["name"];

    return $product;
}

Then inside of your PDO call, loop through the return and array_push onto an array containing all your products built via this function.

$products = array();
foreach ($rst as $r) {
    array_push($products, Product::buildFromPDO($r));
}

You also might want to consider using an ORM if it seems like you'll be doing a ton of this kind of stuff.

Scott G.
  • 323
  • 1
  • 10
  • I like your array push idea, but why on earth would you create a static function to do a constructor's job.. that's literally what a constructor is *for* – I wrestled a bear once. Sep 16 '15 at 17:27
  • hence the name.. *construct*or – I wrestled a bear once. Sep 16 '15 at 17:28
  • in this case your probably right since his class is only a few lines, but sometimes you just need multiple constructors, and this is a correct approach in that case since PHP doesn't natively support constructor overloading. http://stackoverflow.com/questions/1699796/best-way-to-do-multiple-constructors-in-php – Scott G. Sep 16 '15 at 18:48
  • 1
    It's not supported because it's not necessary. Your way isn't incorrect, it's just not ver intuitive. Look at this sudo code: https://3v4l.org/ThasR – I wrestled a bear once. Sep 16 '15 at 20:29
  • in this case, the pdo fetch class is the best solution since it should just work, if it doesn't either one of our solutions are perfectly valid code and their isn't much of a point to continue trying to discuss it. i know some people would argue about using a multi-typed constructor like in the example, and others would say that those are just setters and they should be public, where you just might disagree for the sake of wanting your code to be a certain way. i personally like the idea of putting a pseudo factory inside of the class, or separating it all together. – Scott G. Sep 17 '15 at 11:08
0

You have to write a method to do it.

class Product {
   $id;
   $name;
   public function loadData($data){
      $this->id = $data['id'];
      $this->name = $data['name'];
   }
}

$Product = new Product();
$Product->loadData($database_results);

Or, if you're going to be doing this for every object, use a constructor..

class Product {
   $id;
   $name;
   public function __construct($id, $pdo){
      $pdo->prepare("select * from table where id = :id");
      // do your query, then...
      $this->id = $data['id'];
      $this->name = $data['name'];
   }
}

$Product = new Product($id, $pdo);
I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116
0

You can use constructor arguments (http://php.net/manual/en/pdostatement.fetchall.php)

$result = $stm->fetchAll( PDO::FETCH_CLASS, "Product", array('id','name'));

Note: properties must be public

SebCar
  • 328
  • 3
  • 12