简体   繁体   中英

PHP PDO fetchAll, PDO::FETCH_CLASS and joins

I have a problem in the following code:

$query = 'SELECT user.id as id, pet.name as name FROM user 
          LEFT JOIN pet on pet.user_id = user.id
          WHERE user.id = 15';

$result = $pdo->query($query); 

This code will produce something similar to this:

***************
| id | name   |
***************
| 1  | Mikey  |
***************
| 1  | Stewie |
***************
| 1  | Jessy  |
***************

Now, I'd like to use PDO::FETCH_CLASS to get an object. However, this method, at least to me, works fine only with simple SELECT statements. When you have a join statement, then it will fetch everything in a single class. In other words:

$user = $result->fetchAll(PDO::FETCH_CLASS, 'User');
echo $user->name; // this will print the pet name (which is weird)

Therefore, I'd like to have something similar:

$pets = $user->pets; // an array holding Pet Objects 
foreach ($pets as $pet)
   echo $pet->name . "-"; 

which will produce:

Mikey - Stewie - Jessy -

How can I achieve this?

You can't rely on PDO to do the job for you. PDO has no way to know where the dataset columns come from and it obviously can't figure out where you want to dump the data.

The simplest answer is that you have to write your own code. Fetch rows as arrays and populate your classes with it as it's always been done ;-)

The technique you describe is ORM ( Object-relational mapping ). There're some third-party libraries that implement it, such as Doctrine or Propel .

I open sourced a very small function that will transform joined results into a hierarchy. This avoids using heavy ORMs if you just need this small feature. https://github.com/afilina/nestedsql

You'd give it a statement like this:

SELECT album.id AS albums__id, photo.id AS albums__photos__id
FROM album
LEFT JOIN photo ON photo.album_id = album.id;

and it will produce something this:

stdClass Object
(
    [albums] => Array
        (
            [1] => stdClass Object
                (
                    [id] => 1
                    [photos] => Array
                        (
                            [1] => stdClass Object
                                (
                                    [id] => 1
                                )
                        )
                )
        )
)

Optionally, you can replace stdClass by your own classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM