PHP/MySql - 使用嵌套对象查询对象的最佳方法
Posted
技术标签:
【中文标题】PHP/MySql - 使用嵌套对象查询对象的最佳方法【英文标题】:PHP/MySql - Optimal way to querying an object with nested objects 【发布时间】:2015-04-23 02:35:16 【问题描述】:每次制作新的 OOP 应用程序时,我都会为这个问题而苦恼。假设这将成为一个不断增长的中大型站点,那么实现选择嵌套在另一个对象中的对象的正确方法是什么(在这种情况下,实现对匹配信息查询的最佳方法是什么)。
假设我有这个:
Class SportsTeam
protected $teamId;
protected $teamName;
protected $teamLocation;
Class Matchup
protected $matchupId;
protected $date;
protected $time;
protected $homeTeamId;
protected $awayTeamId;
protected $homeTeam; //SportsTeam object
protected $awayTeam; //SportsTeam object
Class SportsTeamDao
public function getSportsTeam($teamId) //Get SportTeam info
Class MatchupDao
public function getMatchup($matchupId) //Get Matchup info
选项 1:选择比赛对象本身,并在比赛对象内调用 homeTeam 对象的 get 方法和 awayTeam 对象中的调用,以根据需要获取整个 SportsTeam 对象,这样如果我向 SportsTeam 添加属性稍后的对象(例如 teamLogo)它们可以访问到我使用 matchup 对象的位置。
Class Matchup
protected $matchupId;
protected $date;
protected $time;
protected $homeTeamId;
protected $awayTeamId;
protected $homeTeam; //SportsTeam object
protected $awayTeam; //SportsTeam object
//Getters and setters for matchupId, date, time, homeTeamId, awayTeamId
public function getHomeTeam()
$this->homeTeam = SportsTeamDao::getSportsTeam($this->homeTeamId);
return $homeTeam;
public function getAwayTeam()
$this->awayTeam = SportsTeamDao::getSportsTeam($this->awayTeamId);
return $awayTeam;
Class SportsTeamDao
public function getSportsTeam($teamId) //Get SportTeam info
Class MatchupDao
public function getMatchup($matchupId)
$query = "SELECT matchupId, date, time, hometeamid, awayteamid WHERE matchupId = $matchupId LIMIT 1"; //I'd parameterize it of course
选项 2:选择连接中匹配可能需要的所有详细信息,因此我只访问数据库一次。缺点是如果我稍后将属性添加到 SportsTeam,我必须记住将其添加到我的选择语句中,用于 SportsTeam 和 Matchup 以及需要使用这些新属性的任何其他地方。
Class SportsTeam
protected $teamId;
protected $teamName;
protected $teamLocation;
Class Matchup
protected $matchupId;
protected $date;
protected $time;
protected $homeTeamId;
protected $awayTeamId;
protected $homeTeam; //SportsTeam object
protected $awayTeam; //SportsTeam object
Class SportsTeamDao
public function getSportsTeam($teamId) //Get SportTeam info
Class MatchupDao
public function getMatchup($matchupId)
$query = "SELECT M.matchupid, M.date, M.time, M.homeTeamId, M.awayTeamId, HT.teamName AS homeN, HT.teamLocation AS homeL, AT.teamName AS awayN, AT.teamLocation AS awayL FROM matchups M LEFT JOIN sportsteam HT ON M.hometeamid = HT.teamid LEFT JOIN sportsteam AT ON M.awayteamid = AT.teamid WHERE matchupid = $matchupid LIMIT 1";
//Set matchup properties and hometeam object properties and awayteam object properties
我的困境是选项 1 更密集(想想如果我想显示一个球队中的足球运动员列表,它是 1 次调用球队 + 1 次调用来获取球队中所有球员的 ID + 53 次调用一个对于每个玩家对象)但更易于管理,选项 2 是更少的数据库连接(1 次调用团队,1 次调用所有玩家)但更繁琐的维护。那么实现这个的正确方法是什么,或者有第三种更好的方法吗?
【问题讨论】:
如果你使用prepared statement并重用SELECT
语句,我认为选项1是可以接受的。
感谢您的回复。这是后续行动,如果我在 getSportsTeam() 函数中使用准备好的语句,但该函数连续多次调用,那是否仍然利用准备好的语句?不是每次调用函数都要重新准备吗?
您需要缓存准备好的语句变量,并重用该变量。我通常通过构建一个处理缓存的自定义 DB 类来做到这一点。
有趣的想法,能给我举个例子吗?就像这是一个父类,每个准备好的语句都有一个变量或更复杂的东西?
【参考方案1】:
评论太长了,来个答案吧。
选项 1 “结构上”更好。您主要关心的是繁重的数据库连接,如果您使用 prepared statement 并重用 SELECT
语句,可以在一定程度上对其进行优化。
这是我通常做的以确保语句重用(只是一个演示;实际代码中可能有更多逻辑):
class DB
protected $statements=[];
public function prepare($query)
if(empty($this->statements[$query]))
$this->statements[$query]=$mysqli->prepare($query);
return $this->statements[$query];
因此,每当您准备查询时,数据库实例都会检查该查询之前是否已准备好,如果已准备好,则返回该语句而不是再次重新准备。
下一步是让您的类依赖于您的 DB 类。您可以使用 Singleton(全局命名空间下的静态数据库“变量”)来做到这一点:
class Singleton
protected static $db;
public static function getDB()
if(empty(self::$db))
self::$db=new DB(/*...*/);
return self::$db;
或类似的东西:
class Car
public function __construct(DB $db);
您可以根据自己的需要选择合适的方式。
【讨论】:
使用单例使一个类依赖另一个类是否正确?您可以通过在第一类的构造函数中传递 DB 对象来进行显式依赖。 @denied 我从来没有说过要对单例使用依赖。您是否误读了“或”阶段? 糟糕,我非常想开始一场圣战,以至于我什至没有读到你的答案:) 抱歉)以上是关于PHP/MySql - 使用嵌套对象查询对象的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
Swift NSFetchedResultsController 嵌套对象的最佳实践