我正在开发一个flash游戏网站。我有两个模型:游戏和用户,还有一个中间表,我在其中保存用户的动作,例如:"用户1喜欢游戏3"。
- 我喜欢的功能在哪里最好
- 在游戏模型中获取当前用户id是一种好的做法吗?还是应该将其作为参数传递
出于性能原因,我也增加了游戏表中的点赞字段。为了简单起见,我省略了检查用户是否已经喜欢这个游戏
这是我的选择:
第一个版本:
$user->like(12345);
class User
{
public function like($game_id)
{
$like = new User_Game();
$like->user_id = $this->id;
$like->game_id = $game_id;
$like->save();
$obj = new Game($game_id);
$obj->likes++;
$obj->save();
}
}
第二个版本:
$game->like(); // by current user
class Game
{
public function like()
{
$like = new User_Game();
$like->user_id = $_SESSION[‘user_id’];
$like->game_id = $this->id;
$like->save();
$this->likes++;
$this->save();
}
}
老实说,我不确定这是否是解决此类问题的最佳场所。也许代码评审更适合。抛开一切不谈,IMO,你建议的两种方法都不是"最佳方法"。但和往常一样,这可能是个人的事情
在我看来,实现OOP的最佳方法是尽快将所有数据推送到对象中,并实现一个服务层来处理需要多个查询或多个对象的操作。
如果我可以假设您使用的是MVC模式,那么您的控制器将接收数据。在那里,实例化一个Game
对象,并将id设置为123456
。您可以将该实例传递给一个名为fillGameModel(Game $gameInstance)
的服务方法。此方法连接到DB,设置Game
对象的所有其他属性并返回。User
对象也是如此。然后,这两个对象都可以传递给另一个服务方法:likeGame(Game $game, User $user)
。这种方法可以处理其余的问题。
就我个人而言,我甚至会更进一步,使用映射器来访问数据库,但我现在不打算讨论这个问题。下面是一个使用服务的示例,以及一种更面向对象的方法:
//controller:
$user = new User();
$user->setId($_SESSION['user_id']);
$game = new Game();
$game->setId(123456);//wherever you get this from
$service = new MainService();
$service->userLikes($game,$user);
//service:
public function userLikes(Game $game, User $user)
{
$user = $this->_completeUser($user);
$game = $this->_completeGame($game);
//insert or update whatever data you need...
}
protected function _completeUser(User $user)
{
$db = $this->_getConnection();//asuming PDO, to keep things simple
$query = 'SELECT * FROM my_db.users WHERE id = ?';
$stmt = $db->prepare($query);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
foreach ($row as $field => $value)
{//this implies getters and setters in your model
$user->{'set'.ucfirst(strtolower($field))}($value);
}
return $user;
}
protected function _completeGame(Game $game)
{
$db = $this->_getConnection();
$query = 'SELECT * FROM my_db.games WHERE id = ?';
$stmt = $db->prepare($query);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
foreach ($row as $field => $value)
{//field id becomes "setId" method, field name "setName" etc...
$game->{'set'.ucfirst(strtolower($field))}($value);
}
return $game;
}
//just for show: a pseudo-overloader method, if your models all share the same
//abstract class.
protected function _completeAny(Model_Abstract $model)
{
$modelName = get_class($model);
if (method_exists($this,'_complete'.$modelName))
{
return $this->{'_complete'.$modelName}($model);
}
throw new Exception('No completion method for '.$modelName.' found');
}
同样,可以用抽象模型类中的方法来替换通过结果集的循环,该方法将数组作为参数,并将字段名转换为相应的setter。我想说,有足够的抽象空间;-)