ホームページ > バックエンド開発 > PHPチュートリアル > iframe は、PHP を通じてデータベースにクエリを実行し、JS を使用してページのコンテンツを更新するプログラムであるロング ポーリングを実装しています。問題は、すべての MYSQL INSERT メッセージをページに表示できるわけではないことです。何が問題なのかを分析してください。

iframe は、PHP を通じてデータベースにクエリを実行し、JS を使用してページのコンテンツを更新するプログラムであるロング ポーリングを実装しています。問題は、すべての MYSQL INSERT メッセージをページに表示できるわけではないことです。何が問題なのかを分析してください。

WBOY
リリース: 2016-06-23 14:38:47
オリジナル
1369 人が閲覧しました

この投稿は stneo1990 によって最終編集されました: 2013-08-08 11:45:06

まず第一に、これは顧客サービスの相談を模倣したリアルタイム コミュニケーション システムです。主な目的は、顧客サービスから送信されるメッセージをシミュレートすることです。フロントエンド ユーザー (MYSQL データベースへの手動 INSERT 実装を通じて) は、サーバーによってリアルタイムでフロントエンド カスタマー サービス ページにプッシュされます。 一般的な構造は次のとおりです:
1. フロントエンドには iframe があります。 kefu.html ページ。この iframe はバックエンドの query.php クエリ プログラムをリクエストします (iframe はページ上で非表示になります)
2. query.php は while(true) 無限ループを渡し、set_time_limit(0) を設定します。ユーザーが送信した未読メッセージをクエリするループ内で SQL クエリを実行し、<script></script>JS コードを出力し、親ページの 領域を操作します。クエリされたメッセージの結果をページに出力します
3. データを手動で INSERT することでユーザーのメッセージ送信をシミュレートします。デフォルトのメッセージは未読ステータスですが、query.php が読み取られると既読ステータスに変わります

現在の問題は次のとおりです。ページを開くと (またはページを閉じてプログラムを再度開くと)、通常、最初に挿入されたデータはページに表示できませんが、これらのメッセージのステータスは query.php によって読み取れるように変更されています (つまり、 query.php はこのレコードをクエリし、JS コードをフロントエンドに送信しました)、多くのメッセージを挿入し続けると、フロントエンドはレコードの表示を開始し、以前の INSERT レコードは既読としてマークされていましたが、それらは既読としてマークされませんでした。フロントエンドの kefu.html ページに表示される

挿入するのに多くのレコードが必要になるか、通常に戻るのに時間がかかります

全体 後続のプログラムは正常に実行されるため、プログラムには問題ありません。 1 つずつ表示されます。前景に挿入すると 1 つ表示されます (ただし、途中で 1 つが失われることもあります)

問題の根本は次の 2 つの点にあると思います。
1. PHP スクリプトには次のようなものがあります。終了していない
2. JS にキャッシュがあり、データは受信されているが更新されていない可能性があります

ただし、上記の 2 点については、問題はそれほど単純ではないのではないかと思います。特定のメカニズムへの違反または不注意が原因。

具体的なコードは次のとおりです。問題がどこにあるかを見つけるのに役立ちます。ありがとうございます。

テスト方法:
データベースにデータを手動で INSERT し、フロントエンド kefu.html ページが時間内にメッセージを受信して​​更新できるかどうかを観察します

データベース テーブルを作成します:
CREATE TABLE msg(
id int(11) NOT NULL auto_increment、
pos varchar(20) NOT NULL デフォルト ''、
rec varchar(20) NOT NULL デフォルト ''、
content varchar(200) NOT NULL デフォルト ''、
isread` int(1) NOT NULL デフォルト'0',
PRIMARY KEY(id)
);
データを挿入する例:
insert into msg(rec,pos,content,isread) names('admin','zhangsan','hello',0);

ディスカッションへの返信(解決策)

フロントエンド kefu.html コード:

<?php  setcookie('username','admin');?><!doctype html><html>  <head>    <title>在线客服系统</title>    <meta charset="utf-8" />    <script>      //测试浏览器是Chrome 27.0.1453.93      var xhr = new XMLHttpRequest();      //由query.php程序调用的JS函数,用来输出内容到前台页面      function comet(msg,rand){        var content = '';        //获取用户发送给前台的消息,并拼接好        content = '<span onclick="reply(this);" style="cursor:pointer;">' + msg.pos + ' </span>' + '对你说:<br/>  ' + msg.content + '<br/>';        var msgzone = document.getElementById('msgzone');        //把拼接的消息赋值给消息显示区域        msgzone.innerHTML += content;      }      //点击某个用户名,然后回复的span会显示该用户名      function reply(reobj){        document.getElementById('rec').innerHTML = reobj.innerHTML      }      //前台客服回复时,调用的函数      function huifu(){        var rep = '';        //接收前台发送的用户名字        var rec = document.getElementById('rec').innerHTML;        //前台发送的消息内容        var content = document.getElementsByTagName('textarea')[0].value;        if(rec == '' || content == ''){          alert('请选择回复人并填写回复内容');//简单判断回复对象和内容不能为空          return;        }        //sendmsg.php是专门配套前台发送消息用的,就是把消息INSERT进数据库        xhr.open('POST','sendmsg.php',true);        xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');        xhr.onreadystatechange = function(){          if(this.readyState == 4 && this.status == 200){            if(this.responseText == 'ok'){              //当确定前台发送的消息INSERT进数据库后,把这条消息显示到消息区域内              rep += '你对 ' + rec + '说:<br/>  ' + content + '<br/>';              var msgzone = document.getElementById('msgzone');              msgzone.innerHTML += rep;              document.getElementsByTagName('textarea')[0].value = '';            }          }        }        xhr.send('rec='+rec+'&content='+content);      }    </script>    <style>      #msgzone{        border:1px solid #ececec;        width:500px;        height:500px;        overflow:scroll;      }    </style>  </head>  <body>    <h1>在线客服系统--客服端</h1>    <!-- 消息显示区域 -->    <div id="msgzone"></div>    <!-- 用户名区域 -->    回复:<span id="rec"></span><br/>    <!-- 回复内容区域 -->    <textarea>    </textarea><input type="button" value="回复" onclick="huifu();" />    <!-- 隐藏的iframe,其中加载了query.php来不断查询数据库是否有要推送的消息 -->    <iframe src="query.php" width="0" height="0" iframeBorder="0"></iframe>  </body></html>
ログイン後にコピー

バックエンド クエリ query.php コード:

<?phpset_time_limit(0);ob_start();echo str_repeat(' ',4000),'<br/>';ob_flush();flush();$i = 0;require 'conn.php';//连接数据库文件//不断循环查询消息while(true){	//查询接收者为admin,并且是未读的消息	$sql = 'select * from msg where rec = "admin" and isread = 0 limit 1';	$result = $conn -> query($sql);	//提取查询结果	$rs = $result -> fetch_assoc();	if(!empty($rs)){		//将这条消息更新为已读状态		$sql = 'update msg set isread = 1 where id = "'.$rs['id'].'" limit 1';		$conn -> query($sql);		//转换为JSON格式准备发送给JS		$rs = json_encode($rs);		//通过paren调用父窗体的comet()函数,并将转换的JSON数据传送过去,comet()函数可以在kefu.html代码中找到		echo '<script>';		echo 'parent.window.comet(',$rs,',',mt_rand(1,1000000),')';		echo '</script>';	}	ob_flush();	flush();	//防止查询次数过多,设置的每1秒查询一次	sleep(1);}
ログイン後にコピー

データベース接続 conn.php コード:

<?php	$conn = new mysqli('localhost','root','jackson613','test');	$conn -> query('set names utf8');
ログイン後にコピー

AJAX ポーリング方式を使用することをお勧めします。この種のバックグラウンド クエリ スクリプトはスクリプトの実行を積極的に終了しないため、特定の問題が発生する可能性があります。

🎜 私がテストしたのは、1つだけ表示でき、残りは表示できないということです 🎜
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート