前提・実現したいこと
非同期通信にて取得した値をDBに登録し、送信後の値をリアルタイムに表示させたい。
発生している問題・エラーメッセージ
非同期通信にてモーダルを閉じる処理、次の動画を呼び出す処理及びDBにデータを保存するまでは実行できましたが、送信後の値(afterP)が送信前(beforeP)の値となってしまう。
手動でブラウザのリロードを行うと送信後の値(afterP)を取得できるが、元の動画に戻ってしまう。
dataType:"json"にすると送信時にアラートが表示
Error : SyntaxError: Unexpected end of JSON inputが出てしまい次に進みません。
index.ctpのJSON.encodeと JSON.parseを外すと上記エラーは出ませんが、videosの値をjsファイルに渡す方法がわからず外せていません。
該当のソースコード
Point.php
class Point extends AppModel {
public function sumByUserId($userId) {
$data = $this->find('all',
array(
'conditions'=> array('user_id' => $userId),
'fields' => array('sum(point) as sumPoints'),
)
);
return $data['0']['0']['sumPoints'];
}
}
PointsController
他のコード省略
public function beforeFilter() {
parent::beforeFilter();
$userId = $this->Auth->user('id');
$beforeP = $this->Point->sumByUserId($userId);
$this->set(compact('beforeP'));
}
public function index() {
$this->set('videos', $this->Video->find('all'));
}
public function addPoint() {
if (!$this->request->is('ajax')) {
throw new BadRequestException();
}
$userId = $this->Auth->user('id');
$data = array(
'Point' => array(
'user_id' => $this->Auth->user('id'),
'point' => $this->request->data['point'],
)
);
$this->Point->create();
$this->Point->save($data);
$afterP = $this->Point->sumByUserId($userId);
$this->viewClass = 'json';
$this->set(compact('afterP'));
$this->set('_serialize', array('afterP'));
//$this->set('_serialize',(res));のまま使ってしまい気付ずこの時間になってしまいました。
}
point.js
他のコード省略
$(".send").on("click",function(){
$.ajax({
type: "POST",
url: "/aaa/bbb/addPoint",
dataType: "json", //やっとjsonで動きました!有難うございます。
data: {
"point": point
},
success: function(res) {
//モーダルを閉じる処理;
//次の動画を呼び出す処理;
$('#sumPoints').text(res.afterP);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('Error : ' + errorThrown);
}
});
return false;
}
});
index.ctp
他のコード省略
<p>送信前:<?php echo $beforeP; ?> pt</p>
<p>送信後:<span id="sumPoint"></span> pt</p>
<?php
function json_safe_encode($data){
return json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
}
$videos = json_safe_encode($videos);
//$afterP = json_safe_encode($afterP);(削除)
?>
<script></script>
補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報
XAMPP 5.6.14-0
cakephp-2.7.8
jquery 1.11.0
10.0.17-MariaDB
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
exitはPHPスクリプト自体を終了させる言語構造で、それ以降の処理は行われません。
削除するか、処理を抜ける目的ならreturn
に置き換えてみてください。
また、PointsController::indexがポイント操作も請け負うのは不自然で
その部分は別アクションや別コントローラに切り分けたほうが良いかもしれません。
そのほうが問題箇所の特定もしやすくなるはずです。
PHP: exit - Manual
http://php.net/manual/ja/function.exit.php
追記 2016-06-03 18:15
ポイントの合計を求める処理は複数個所で使われそうなので、Pointモデルのメソッドに
してもいかもしれません。
class Point extends AppModel {
//略
public function sumByUserId($userId) {
$data = $this->find('all',
array(
'conditions'=> array('user_id' => $userId),
'fields' => array('sum(point) as sumPoints'),
)
);
return $data['0']['0']['sumPoints'];
}
}
//コントローラ側で使う時はこんな感じ
$userId = $this->Auth->user('id');
$afterP = $this->Point->sumByUserId($userId);
ポイント加算アクションの例です。indexアクション内のajax対処部分を
抜き出しただけなので、問題の解決につながるかはまだ分かりません。
public function add() {
if (! $this->request->is('ajax')) {
//ajax以外なら例外を投げる
}
$userId = $this->Auth->user('id');
$data = array(
'Point' => array(
'user_id' => $userId,
'point' => $this->request->data['point'],
)
);
$this->Point->create();
$this->Point->save($data);
$afterP = $this->Point->sumByUserId($userId);
$this->viewClass = 'json';
$this->set(compact('afterP'));
$this->set('_serialize','res');
}
ポイントの加算に対応するアクションがindexからaddに変わったので
ajaxのリクエスト先も変更します。
$.ajax({
type: "POST",
url: ""
urlを /CakePHPディレクトリのパス/points/addに変更
環境によってはちょっと違うかもしれません。ブラウザでF12を押してコンソールを出し、
いろいろ試しながら確認してみてください。
addアクションからレスポンスが返ってくるようになれば、
indexアクション内のajaxに関わるコードは削除してしまっても構いません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/06/02 23:33
ポイント操作の切り分け方ですが
beforeFilter( ){
・現在のポイント合計を呼び出す処理
・現在のポイント合計を変数にする処理
}
index( ){
・登録されている動画を呼び出す処理
・ajaxでdataを受け取る処理
・そのdataをDBに保存する処理
}
other action( ){
・DBからポイント合計を呼び出す処理
・ポイント合計を変数にする処理
}
切り分けの考え方はよろしいでしょうか?
その際、index( )でajaxお処理をした後に、自動でother action( )の処理をさせるのは
redirectを使って連携させるのでしょうか?
トンチンカンな質問かも知れませんが、お時間のある時で構わないのでアドバイスをお願いいたします。
2016/06/03 18:02 編集
> redirectを使って連携させるのでしょうか?
今はindexアクションが状況に応じてHTMLを返したり、ポイント数をjsonで
返したりしています。多分この、状況によって役割が変わるという部分が
分かりにくさにつながっているのだと思います。
ajax > index > other という流れをイメージされていると思うのですが、
ajax > other のみで完結させたほうが良いでしょう。
・indexアクションはindexの描画だけを担当する、Ajaxの事は考えない
・「ポイントを追加して返す」アクションはそれだけをする、HTMLの事は考えない
と分ければ処理内容は追いやすくなるはずです。
続きます。 < コメント欄だとコードが見づらいので回答を編集しました。
2016/06/03 23:09
とても分かりやすく、綺麗なコードと丁寧なご説明のおかげで、やっとやっと出来ました!
感謝し尽くしても足りないくらい本当にありがとうございました。
嬉しくてたまりません。質問のコードは動かせたコードに修正いたしました。
本当にありがとうございました。
2016/06/04 18:22
問題のほうが解決したようで良かったです。作品完成までがんばってください。
2016/06/04 18:51