2013-11-04 617 views
2

他在那里!Yiiframework消息弹出

如果有一个问题与我正在处理的应用程序中的两个不同问题有关。

问题1: - 有一个消息系统。用户可以发送其他消息。我想在用户收到新消息并且不在收件箱页面上时实时弹出。

问题2: - 我想创建一个基本的成就系统,其中一个成就可以是(例如):“接收消息”。

现在我认为这两种功能都可以通过相同的方式实现。你们中的任何人都有这种实时通信的经验吗?我真的不知道从哪里开始。我真的很喜欢它,如果它不重。

非常感谢。

+3

调查web​​sockets/AJAX轮询/长轮询。 – Matt

回答

1

以下是你可能会使用长轮询(使用jQuery和Yii的)一个样板:

服务器端:

class MessagesController extends CController { 

    public function actionPoll($sincePk, $userPk) { 
     while (true) { 
      $messages = Message::model()->findAll([ 
       'condition' => '`t`.`userId` = :userPk AND `t`.`id` > :sincePk', 
       'order'  => '`t`.`id` ASC', 
       'params' => [ ':userPk' => (int)$userPk, ':sincePk' => (int)$sincePk ], 
      ]); 

      if ($messages) { 
       header('Content-Type: application/json; charset=utf-8'); 

       echo json_encode(array_map(function($message){ 
        return array(
         'pk' => $message->primaryKey, 
         'from' => $message->from, 
         'text' => $message->text, 
         /* and whatever more information you want to send */ 
        ); 
       }, $messages)); 
      } 

      sleep(1); 
     } 
    } 

} 

客户端:

<?php 
$userPk = 1; 
$lastMessage = Messages::model()->findByAttributes([ 'userId' => $userId ], [ 'order' => 'id ASC' ]); 
$lastPk = $lastMessage ? $lastMessage->primaryKey : 0; 
?> 

var poll = function(sincePk) { 
    $.get('/messages/poll?sincePk='+sincePk+'&userPk=<?=$userPk?>').then(function(data) { 
     // the request ended, parse messages and poll again 
     for (var i = 0;i < data.length;i++) 
      alert(data[i].from+': '+data[i].text); 

     poll(data ? data[i].pk : sincePk); 
    }, function(){ 
     // a HTTP error occurred (probable a timeout), just repoll 
     poll(sincePk); 
    }); 
} 

poll(<?=$lastPk?>); 

记得要实现一些这种认证可以避免用户阅读其他消息。