質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

2078閲覧

JSON形式のファイルを_serializeを使って表示できない

nnafa

総合スコア12

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

0クリップ

投稿2018/11/20 10:00

編集2018/11/22 10:43

前提・実現したいこと

CakePHP3を使い、Ajax通信でデータベースからデーターを取得するソースを作成しています

発生している問題・エラーメッセージ

こちらの質問を参考に、このようなソースをコントローラにかきました(一部省略)

$this->set('res', $res); $this->set('_serialize', ['res']);

すると何も表示されず、開発者ツールではパースが失敗している?ようなエラーが出ていました

何かエラーに心当たりのある方がいらっしゃいましたら、教えていただけますと幸いです

該当のソースコード

現在コードが入ったUSBを外出先に忘れてきてしまっています。
USBを回収した後に追記いたします。

動作確認に必要そうなコントローラ、ビューファイルを追記いたしました。

不足な点があれば、修正依頼を頂けると幸いです。
下のソースコードではecho json_encode($this->paginate($query))を使い、サーバから結果を返すようになっていますが、その部分をset _serializeを用いた手法に変えた際にうまく動かなくなってしまいます。

src/Controller/ArticlesController.php(viewアクション、paginatorで使う部分を抜粋)

php

1 public $paginate = [ 2 'limit' => 5, 3 'maxLimit' => 10 4 ]; 5 6 public function initialize() 7 { 8 parent::initialize(); 9 $this->loadComponent('Security'); 10 $this->loadComponent('Paginator'); 11 } 12 13 public function view($id = null) 14 { 15 $article = $this->Articles->get($id); 16 $comment = $this->Articles->Comments->newEntity(); 17 $query = $this->Articles->Comments->find()->where(["article_id" => $id]); 18 $this->set(compact("article", "comment")); 19 $this->set("comments", $this->paginate($query)); 20 }

src/Template/Articles/view.ctp

php

1<h1><?= h($article->title) ?></h1> 2<p><?= h($article->name) ?></p> 3<p><?= h($article->body) ?></p> 4<p><small>Created: <?= $article->created->format(DATE_RFC850) ?></small></p> 5<hr> 6 7<?php 8 echo $this->Form->create($comment, ["url" => ["controller" => "Comments", "action" => "add"]]); 9 echo $this->Form->control('title'); 10 echo $this->Form->control('body', ['rows' => '3']); 11 echo $this->Form->hidden("article_id", ["default"=>h($article->id)]); 12 echo $this->Form->button(__('Save Article')); 13 echo $this->Form->end(); 14?> 15<?php if (!$comments->isEmpty()): ?> 16 17 <?php foreach ($comments as $comment): ?> 18 <?php var_dump($comment) ?> 19 <?php endforeach; ?> 20 <?php $this->Paginator->options([ 21 'url' => [ 22 'controller' => 'Comments', 23 'action' => 'get' 24 ] 25 ]); ?> 26 <ul class="pagination"> 27 <?= $this->Paginator->first('<<') ?> 28 <?= $this->Paginator->prev('<') ?> 29 <?php if (!empty($this->Paginator->numbers())): ?> 30 <?= $this->Paginator->numbers() ?> 31 <?php else: ?> 32 <li><?= $this->Paginator->current("Comments") ?></li> 33 <?php endif; ?> 34 <?= $this->Paginator->next('>') ?> 35 <?= $this->Paginator->last('>>') ?> 36 </ul> 37<?php else: ?> 38 <p>この記事にはまだコメントがありません。</p> 39<?php endif; ?> 40 41<hr> 42 43<div id="result"> 44</div> 45 46 47<script> 48 $(function () { 49 $(".pagination a").on("click", function () { 50 $.getJSON($(this).attr("href"), { article_id: <?= $article->id ?> }, function (data){ 51 console.log(data); 52 }); 53 return false; 54 }); 55 }); 56</script>

Controller/CommentsController.php(コメント取得部分等を抜粋、コメント追加アクション等一部は省略)

php

1<?php 2namespace App\Controller; 3 4class CommentsController extends AppController 5{ 6 public $paginate = [ 7 'limit' => 5, 8 'maxLimit' => 10 9 ]; 10 11 public function __construct($request, $response) 12 { 13 parent::__construct($request, $response); 14 $this->autoRender = false; 15 } 16 17 public function initialize() 18 { 19 parent::initialize(); 20 $this->loadComponent('Security'); 21 $this->loadComponent('Paginator'); 22 $this->loadComponent('RequestHandler'); 23 } 24 25 26 public function get() 27 { 28 $id = $this->request->getQuery("article_id"); 29 $query = $this->Comments->find()->where(["article_id" => $id]); 30 $this->response->charset("UTF-8"); 31 $this->response->type("json"); 32 echo json_encode($this->paginate($query)); 33 } 34}

Model/Table/ArticlesTable.php

php

1<?php 2namespace App\Model\Table; 3 4use Cake\ORM\Table; 5use Cake\Validation\Validator; 6 7class ArticlesTable extends Table 8{ 9 public function initialize(array $config) 10 { 11 $this->addBehavior("Timestamp"); 12 $this->hasMany("Comments") 13 ->setDependent(true); 14 } 15 16 public function validationDefault(Validator $validator) 17 { 18 $validator 19 ->notEmpty("title") 20 ->requirePresence("title") 21 ->notEmpty("name") 22 ->requirePresence("name") 23 ->notEmpty("body") 24 ->maxLength("body", 140, "140") 25 ->requirePresence("body"); 26 27 return $validator; 28 } 29}

src/Model/Table/CommentsTable.php

php

1<?php 2namespace App\Model\Table; 3 4use Cake\ORM\Table; 5use Cake\Validation\Validator; 6 7class CommentsTable extends Table 8{ 9 public function initialize(array $config) 10 { 11 $this->addBehavior('Timestamp'); 12 $this->belongsTo("Articles"); 13 } 14 15 public function validationDefault(Validator $validator) 16 { 17 $validator 18 ->notEmpty('title') 19 ->requirePresence('title') 20 ->notEmpty('body') 21 ->requirePresence('body'); 22 23 return $validator; 24 } 25}

Commentsテーブルの構造も記載いたします。
article_idに外部キーを用いてコメントの属する記事を参照するようにしています。

sql

1CREATE TABLE `comments` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `article_id` int(10) unsigned NOT NULL, 4 `title` varchar(255) NOT NULL, 5 `body` text, 6 `created` datetime DEFAULT NULL, 7 PRIMARY KEY (`id`), 8 KEY `article_key` (`article_id`), 9 CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`article_id`) REFERENCES `articles` (`id`) 10) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

試したこと

  • echo json_encode($res); -> 無事表示できた。開発者ツールでのエラーもなし

  • Content-Typeの指定 -> もともとしてあった

  • popobotさんにご回答頂いた内容を参考に、CommentsControllerを編集した -> Missing Templateエラーが発生した

Controller/CommentsController.php(コメント取得部分等を抜粋、コメント追加アクション等一部は省略)

php

1<?php 2namespace App\Controller; 3 4class CommentsController extends AppController 5{ 6 public $paginate = [ 7 'limit' => 5, 8 'maxLimit' => 10 9 ]; 10 11 public function __construct($request, $response) 12 { 13 parent::__construct($request, $response); 14 } 15 16 public function initialize() 17 { 18 parent::initialize(); 19 $this->loadComponent('Security'); 20 $this->loadComponent('Paginator'); 21 $this->loadComponent('RequestHandler'); 22 } 23 24 public function get() 25 { 26 $id = $this->request->getQuery("article_id"); 27 $query = $this->Comments->find()->where(["article_id" => $id]); 28 $this->response->charset("UTF-8"); 29 $this->response->type("json"); 30 $response = ($this->paginate($query)); 31 $this->set("response", $response); 32 $this->set("_serialize", ["response"]); 33 } 34}

何かエラーに心当たりのある方がいらっしゃいましたら、教えていただけますと幸いです
よろしくお願いいたします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

$this->autoRender = false; がよくない気がします。

この設定をすると、Viewの描画処理がされなくなるので、jsonをシリアライズする機能も動かなくなるのではないかと

投稿2018/11/21 21:49

編集2018/11/21 21:53
popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnafa

2018/11/22 10:44 編集

ご回答頂きありがとうございます! autoRenderが原因とのことですが、まさしくその通りでした しかしautoRenderを指定しないと、ブラウザから直接アクセスした際のみ、アクションを終了した後にビューファイルを読み込もうとしてMissing Templateエラーになってしまいます CommentsControllerにはリクエストのパラメーターからjson形式のデータを返すだけのアクションしかないため、ビューファイルは不要となっています。なので、エラーを抑制するためにビューファイルを作成することは可能な限り控えたいと考えております 上述の問題を解決する方法について、ご存知ありませんか? よろしくお願いいたします
nnafa

2018/11/22 08:56

質問の 試したこと に編集後のCommentsControllerのソースを記載いたしました。
popobot

2018/11/22 12:57 編集

jsonしか許容したくないのであれば、以下を代わりに設定したらどうでしょうか $this->request->allowMethod("json"); 他の形式でアクセスした場合、405 Method Not Allowed を返すようになるのでこの方法が適切ではないかと なお、設定する箇所は、__constructよりはinitializeの方が適切だと思います。
nnafa

2018/11/22 13:52

ご返信ありがとうございます。 autoRenderを削除しご回答頂いたソースを書くと、仰る通りの挙動になりました allowMethod()はHTTPリクエストメソッドしか設定できないものと思っていたので驚きました。コンテンツタイプもチェックできる(?)のですね。今後活用して行こうと思います ・・・ちなみに私の方でも試行錯誤をした所、405は返しませんが、`$this->RequestHandler->renderAs($this, "json");`でも一応やりたいことはできるとわかりました。 設定する箇所の件、initialize()の方が適切なのですね。 なぜなのか考えてみたのですが、initialize()を実装していればコンストラクターを上書きして親を呼び出す必要がなくなるため、コンストラクターをコールするのは無駄で、全部initialize()でできる。という考えが思い浮かびました(とんちんかんでしたらすみません)
popobot

2018/11/22 14:04 編集

うまくいってよかったです。 initialize()が適切である理由は、自分も明確には言えませんが... CakePHPが初期化のために用意しており、コンストラクタの最後に呼び出されるので、慣習的に初期化に関する処理はここにまとめるのがいいと思っています。 https://book.cakephp.org/3.0/ja/controllers.html#appcontroller
nnafa

2018/11/22 15:55

なるほど、initialize()が適切である理由について、納得できました。 この質問を通して知れたことが多く、とても勉強になりました。 このたびはお付き合い頂き、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問