如何有效地在php / mysql中加载相关对象?

时间:2019-07-16 21:27:52

标签: php mysql performance join design-patterns

情况

我正在将PHP和PDO与mysql一起使用,并想查询1个表以及它指向另一个表的行。

我有一个类似的课程:

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

和一张桌子

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

您可以看到Pet是指所有者。此类就像:

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

和桌子

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

现在,我想让所有拥有所有属性的猫,包括主人。


解决方案1 ​​

如果我有这样的查询:

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

返回关联数组后,这将在idname列上产生冲突。

我有两个选择
1.)使用返回的数字索引映射到Pet对象和相关的Person对象
2.)给表列名添加前缀并使用返回的关联数组实例化对象


解决方案2

或者我可以执行以下查询:

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

并得到一个结果关联数组。我可以循环获取所有所有者ID的列表,然后执行以下操作:

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

然后实例化Person对象,并将它们分配给我的$owner对象的Pet属性。


投诉

解决方案1.1(数字索引)

从技术上讲这是可行的,但随后我必须将数字条目映射到正确的属性名称,这似乎很容易出错,尤其是对数据库模式进行任何更改时。

解决方案1.2(前缀)

这将很容易地工作,但是在阅读时,不建议在列名前添加前缀。另外...我真的不想在列名前加上前缀。

解决方案2

这将起作用,但似乎不起作用。

问题

我还缺少其他选择吗?

我试图找出一种在SELECT语句中为列名加上前缀的方法(这很好,因为它不会影响实际的数据库),但是似乎不可能。

3 个答案:

答案 0 :(得分:2)

您可以为一个或两个表中的列加上别名,这样它们就不会模棱两可,例如:

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

(您无需从人员表中选择ID,因为它已被包含为ownerId。)

答案 1 :(得分:1)

据我所知,您无法在MySQL中一次更改或添加所有列名(person.* as person.*)或其他答案中提到的单个列。既然您也提到了使用PDO,请考虑其他方法,下面是其中两种。

1.3:使用PDO语句getColumnMeta()

这将询问数据库有关数字列的其他元数据:

$qry = "SELECT pet.*, person.* FROM pet JOIN person ON person.id = pet.owner_id WHERE pet.type LIKE 'cat'";
$stmt = $dbh->prepare($qry);
$stmt->execute();       
while($row = $stmt->fetch(PDO::FETCH_NUM)) {
    foreach($row as $key => $value) {
        $meta = $stmt->getColumnMeta($key);
        echo $meta['table'] . '.' . $meta['name'] . ': ' . $value . PHP_EOL;
    }
}

/* Output: 
pet.id: 2
pet.name: foxy
pet.type: cat
pet.owner_id: 60
person.id: 60
person.name: Bob
..
*/

1.4:使用fdo_style PDO::FETCH_NAMED

使用PDO语句获取

这将使具有相同名称的字段成为数组。仍然要注意顺序:SELECT pet.*, person.*SELECT person.*, pet.*

$qry = "SELECT pet.*, person.* FROM pet JOIN person ON person.id = pet.owner_id WHERE pet.type LIKE 'cat'";
$stmt = $dbh->prepare($qry);
$stmt->execute();       
while($row = $stmt->fetch(PDO::FETCH_NAMED)) {
    echo $row['name'][1] . ' owns a ' . $row['type'] . ' named ' . $row['name'][0] . PHP_EOL;
}

/* Output:
Bob owns a cat named foxy
Joshua owns a cat named jim
*/

答案 2 :(得分:0)

我认为最佳实践是不要在不同的表中使用相同的列名,这是应建议的。列名称应描述其实体。在这种情况下,Pet.id应该是Pet.pet_id,依此类推。

希望这会有所帮助。

谢谢