PHP/MySql - 查询具有嵌套对象的对象的最佳方式

标签 php mysql oop query-optimization

每次我制作一个新的 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)可以在我使用匹配对象的地方访问它们。

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 个所有玩家调用)但维护起来更繁琐。那么实现这个的正确方法是什么,或者还有第三种更好的方法吗?

最佳答案

这对于评论来说太长了,所以这里有一个答案。

选项 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];
    }
}

因此,每当您准备查询时,数据库实例都会检查该查询之前是否已经准备过,如果是,则返回该语句而不是再次重新准备。

下一步是让您的类依赖于您的数据库类。您可以通过使用 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);
}

您可以选择适合您需要的正确方式。

关于PHP/MySql - 查询具有嵌套对象的对象的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29812598/

相关文章:

mysql - 使用entitframework将excel数据上传到mysql数据库

mysql - 将 2 个月份和年份的列与不同的条件相结合

php - 如何将 SQL 查询放入 for() 循环中

php - 如何检查 while 循环中的最后一个条目并在 php 中的表中的最后一行之后插入行

php - Android与mysql数据库的连接

MySQL - 组和总计,但返回每个组中的所有行

php - 如何从 SQLite 数据库中获取随机记录?

java - 面向对象的设计——当一个类中有很多数据字段时,封装有多重要?

oop - 如何理解松耦合应用程序的整体情况?

java - OOP设计,在主类之外调用某些方法