[英]Best Practice approach to relating MySQL join queries to OOP and Objects
我正在开发一个PHP Web应用程序,用户可以在其中创建到目的地的旅行,并邀请其他用户参与这些旅行。
我有用于Destinations
, Trips
和Users
MySql表,还有一个名为Invites
的表,用于解决Users
和Trips
之间的多对多关系。
对于这些表中的每一个,我都在应用程序中创建了一个类(因此Destinations
是一个类, Trips
是一个类,等等)。 我为这些类的每一个编写了一个静态函数,该函数允许实例化对象并从MySQL查询分配属性(因此,从SELECT *
查询返回的每一行都会实例化对象并分配属性)。
我正在尝试创建一个页面,我的用户可以在该页面上查看他们计划的所有行程的详细信息。 此页面将显示目的地(来自Destinations
),旅程详细信息(例如Trips
日期)和他们邀请的用户的详细信息(例如Users
名),并将所有这些数据放在html表中,其中每个旅程都是行。
要做到这一点,到目前为止,我一直在实例Trips
这涉及到用户的user_id
, Destinations
和Invites
其涉及到的Trips
,和Users
这涉及到这些Invites
。 然后,我使用了嵌套的foreach循环来根据需要显示这些循环,如下所示:
foreach($trips as $trip) {
foreach($invites as $invite) {
foreach($invited_users as $invited_user) {
if($invite->trip_id == $trip->id && $invite->guest_id == $invited_user->id) {
echo $invited_user->name;
} } } }
我看到的是可怕的,没有办法做到这一点。
通过阅读,我认为我想使用MySQL来联接这4个表,然后仅选择与我的相关行程有关的数据。 我不确定的是:
a)如何从该MySQL结果实例化对象并正确分配其属性?
b)即使这样做,如何避免昂贵的foreach
循环在正确的行程旁边显示正确的数据?
是否存在“最佳实践”方式以面向对象的方式显示来自多个相关数据库表的数据?
首先,“良好实践”是人们用来给偏见以可敬的色彩的短语之一。 最好问一下如何通过设计实现特定的目标。
话虽如此:您偶然发现了将RDBMS映射到面向对象系统时常见的问题。 Google的“延迟加载”进行了大量讨论。 问题归结为您一次加载多少个“关系”的问题。 在您的示例中,旅行与目的地和用户相关联; 加载“行程”时,是否还应该加载目的地和用户? 如果这样做,那么是否还应该为用户加载其他信息(例如,他们正在进行的其他旅行?)。 如果这样做,是否为用户进行的所有行程加载行程数据? 依此类推-如果不小心,最终将加载整个数据库。
不加载所有相关实体的缺点是,如果一次加载每个对象的数据,性能可能会变得很差。
有关我认为最佳实践的详细说明,请购买并阅读Evans的“域驱动设计”。
作为一种捷径,请考虑创建一个“存储库”层,该层知道如何将数据库记录映射到对象,并创建用于搜索所需内容的自定义方法。 例如,您可以调用:
$repository::getTripsForUser($userID);
该方法将执行将4个表连接在一起的SQL查询,并将结果转换为对象树。
您可能想利用他人在解决此问题上所做的工作; 有许多解决此问题的“对象关系映射”框架。 我认为对于ORM解决方案是否可以使生活更轻松尚无定论-但这值得一看。
我认为您正在使事情变得复杂,您不需要一次加载所有数据。
为什么需要遍历所有行程,而又需要显示一位用户的行程?
OOP的一种天真但简单的方法: User
类,具有检索用户相关旅程的方法。
它可以返回Trip
数组,其自身具有受邀用户的引用:
class User {
private $id;
public function __construct($id) {
$this->id = $id;
}
public function getTrips() {
$trips = array();
// Run your query using $this->id to build the WHERE clause
return $trips;
}
}
class Trip {
// Array of User objects invited to the trip
private $invited = array();
// Other methods here to add/retrieve invited users
}
$user = new User(1);
foreach ($user->getTrips() as $trip) {
// Do something with $trip
}
理想情况下, User
实例将存储在会话中
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.