Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PDO::FETCH_CLASS without passing class name as a parameter

Tags:

php

mysql

pdo

i came across a piece of code where PDO::FETCH_CLASS is being called without passing the name of the class as a parameter, like this:

  function getUsers() {
    $DBH = $this->getDbh();
    $query = "SELECT * FROM users";

    try {
      $STH = $DBH->query($query);
      $users = $STH->fetchAll(PDO::FETCH_CLASS);
    } catch(PDOException $e) {

    }

    return $users;
  }

now, in the official documentation it says:

If fetch_style includes PDO::FETCH_CLASSTYPE (e.g. PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE) then the name of the class is determined from a value of the first column.

so im not sure i understood exactly what they mean nor how it works. let's say i have users table with one record

  • id:1
  • name:Josh
  • so on..

so how can PDO::FETCH_CLASS know what's the class name? can i add column to my record with the class name in a way FETCH_CLASS will get the class name from the database? example of record structure will be highly appreciated ...thx

*I am testing this class but not the author so changing the class is irrelevant

like image 430
Donoven Rally Avatar asked Mar 25 '26 06:03

Donoven Rally


2 Answers

For fetchAll method, if classname is not supplied and PDO::FETCH_CLASSTYPE flag is not raised, a stdClass object is returned (just like with PDO::FETCH_OBJ). This is what happens (lxr):

1436    switch(how & ~PDO_FETCH_FLAGS) {
1437    case PDO_FETCH_CLASS:
1438        switch(ZEND_NUM_ARGS()) {
1439        case 0:
1440        case 1:
1441            stmt->fetch.cls.ce = zend_standard_class_def;
1442            break

Then, in do_fetch, as there's no class name supplied, this value remains as is. That makes sense, as stdClass is sometimes considered an anonymous class of a sort. )


That explains the code you have to deal with; @eggyal's answer explains how one can use PDO::FETCH_CLASS || PDO::FETCH_CLASSTYPE combo. It's actually a pretty powerful technique, allowing you to skip the boilerplate switch in factory methods.

like image 94
raina77ow Avatar answered Mar 26 '26 19:03

raina77ow


  1. im not sure i understood exactly what they mean nor how it works

    What they mean is that instead of

    $STH = $DBH->query("SELECT * FROM users");
    $users = $STH->fetchAll(PDO::FETCH_CLASS, 'UserClass');
    

    you can do the following:

    $STH = $DBH->query("SELECT 'UserClass', users.* FROM users");
    $users = $STH->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
    

    However, this is not especially useful: why hardcode the class name into the SQL only to have MySQL return it with every record and PDO parse each of those fields (i.e. for each record) when instantiating the resultant objects? Better just to specify the class name as the second argument to fetchAll(), as shown in the first example above.

  2. should i add column to my record with the class name?

    Well, indeed, one could do that too—and that is a far more useful use of this functionality: it enables the class of each resultant object to depend upon the record itself, which may be useful in some cases (i.e. where not all records in a resultset are of the same "type"—for example: perhaps some records should instantiate Employee objects, whilst others should instantiate Customer objects).

like image 35
eggyal Avatar answered Mar 26 '26 18:03

eggyal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!