mardi 16 juillet 2019

How to load related objects efficiently in php/mysql?

The situation

I'm using PHP & PDO with mysql and would like to query 1 table as well as rows that it points to in another table.

I have a class like:

class Pet {
    public $id;
    public $name;
    public $type;
    public $owner;
}

and a table

pet
id | name | type | owner_id
0  | jim  | cat  | 87
1  | gale | dog  | 50
2  | foxy | cat  | 60

You can see that Pet refers to an Owner. This class is like:

class Person {
    public $id;
    public $name;
    public $pets;
}

And the table

person
id | name 
87 | Joshua
50 | Bob
60 | Cynthia

Now, I want to get all the cats, with each property set, including the owner.


Solution 1

If i have a query like:

SELECT pet.*, person.* FROM pet
JOIN person
    ON person.id = pet.ownerId
WHERE pet.type LIKE 'cat'

With the associative array returned, this will create a conflict on both id and name columns.

I have two options
1.) Use the numeric indices returned to map to the Pet objects and related Person objects
2.) prefix table column names & use the associative array returned to instantiate the objects


Solution 2

Or I can do a query like:

SELECT * FROM pet WHERE pet.type LIKE 'cat'

and get a resulting associative array. I can loop over and get a list of all the owner ids and do:

SELECT * FROM person WHERE person.id IN (LIST_OF_IDS)

then instantiate the Person objects and assign them to the $owner property of my Pet objects.


complaints

Solution 1.1 (numeric indices)

This will technically work, but then I have to map numeric entries to the correct property names, which seems very prone to error, especially with any changes to DB schema.

Solution 1.2 (prefixes)

This will work pretty easily, but upon reading up, prefixing column names is discouraged. Also... I don't really want to prefix my column names.

Solution 2

This will work, but does not seem performant.

Question

Are there other options for this that I'm missing?

I tried figuring out a way to prefix the column name in the SELECT statement (which would be fine, as it wouldn't affect the actual database), but it does not seem to be possible.

Aucun commentaire:

Enregistrer un commentaire