“喜欢”功能的最佳实践

时间:2012-09-18 06:55:58

标签: php oop model social-media-like

我正在开发一个Flash游戏网站。我有两个模型:游戏用户以及一个中间表,我在其中保留用户的操作,例如:“用户1喜欢游戏3”。

  1. 我最喜欢的地方在哪里?
  2. 游戏模型中获取当前用户ID是一种好习惯吗?或者我应该将其作为参数传递?
  3. 出于性能原因,我也在游戏桌中增加了喜欢的字段。 我省略了检查用户是否已经喜欢这个游戏只是为了保持简单 以下是我的选择:

    第一版:

    $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();    
      }    
    }    
    

1 个答案:

答案 0 :(得分:1)

说实话,我不确定这是否是这个问题的最佳位置。也许codereview更适合。除此之外,IMO,你建议的两个都不是“最好的方法”。但一如既往,这可能是个人的事情。
在我看来,最好的方法是尽快将所有数据推送到对象中,并实现一个服务层来处理需要多个查询或多个对象的操作。

如果我假设你正在使用MVC-ish模式,你的控制器会收到数据。在那里,您实例化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。我会说,有足够的抽象空间; - )