読者です 読者をやめる 読者になる 読者になる

Motomichi Works Blog

その日学習したことについて書いている日記です。誰かの役に立ったらそれはそれで嬉しいです。

さくらvpsとcakephp2.6.7で開発日記 その0019 AngularJS1.xを使用してAjaxでテーブルデータを取得する

制作 cakephp angularjs

参考にさせて頂いたページ

$httpサービスについて

$http | AngularJS 1.2 日本語リファレンス | js STUDIO

コントローラーの書き方について

jQueryとAngularJSにおけるAjaxの微妙な違い | ゆっくりと…

AngularJSでリクエストを送信すると$this->request->is('ajax')がfalseになってしまう事について

AngularJSのリクエストをPHPで処理するときのメモ - Qiita

runメソッドについて

AngularJS使い方ガイド Ajax編 | Webエンジニアブログ

その他

AngularJSのTutorialのstep-5よりAjaxの書き方・テストの仕方 - Qiita

ベースになるソースコード

以前書いた記事で、「jQueryを使用して・・・」を書いたのでこれをベースにAngularJSでもやってみる。

AngularJS1.4.7でsample.jsを書いてみる

$http | AngularJS 1.2 日本語リファレンス | js STUDIO」のページの「概要 > 一般的な使用」を参考にjsを記述してみた。

具体的には以下の通り。

// myAppモジュールを作成
var app = angular.module('myApp', []);
// myAppモジュールにSubmitCtrlコントローラーを登録
app.controller('SampleCtrl', ['$scope', '$http', function($scope, $http) {
  $scope.onclick = function(){
    $http({method: 'GET', url: 'https://practice.mw.top/Ajax/find_contacts/'})
      .success(function(data, status, headers, config) {
        // レスポンスが有効の場合に、非同期で呼び出されるコールバックです。
        console.log(data);
      })
      .error(function(data, status, headers, config) {
        // エラーが発生、またはサーバからエラーステータスが返された場合に、
        // 非同期で呼び出されます。
        console.log('error');
      });
  }
}]);

以下のようなショートカットメソッドもある。

  • $http.get
  • $http.head
  • $http.post
  • $http.put
  • $http.delete
  • $http.jsonp

app/View/Contacts/index.ctp

jQueryでやったときのソースに以下のように追記した。

<button ng-controller="SampleCtrl" ng-click="onclick();">angular</button>

app/Controller/AjaxController.phpについて

$this->request->is('ajax')がfalseになってしまう事について

なぜfalseになるのかなんだけど、

AngularJSのリクエストをPHPで処理するときのメモ - Qiita」のページの記事本文にある

XMLHttpRequestで判定しているのでAngularのリクエストではtrueになってくれません。

とか

コメントにある

X-Requested-With が削除された経緯らしきもの

とかによるものらしい。

リクエストとレスポンスオブジェクト — CakePHP Cookbook 2.x ドキュメント」にも

is('ajax') 現在のリクエストが X-Requested-With = XMLHttpRequestに由来するものかどうかを調べます。

と書いてある。

代わりにどうやって判定するか

同じく「AngularJSのリクエストをPHPで処理するときのメモ - Qiita」のページにあるisAngular関数を定義して判定すると良いみたい。

その関数の内容としては、

ブラウザのアドレス入力によるリクエストなのか、AngularJSのHTTPリクエストなのか判定したい場合、$_SERVER['HTTP_ACCEPT']に「application/json」が含まれるかで判断すると良いです。

と書いてあります。

$_SERVER['HTTP_ACCEPT']には何が入っているのか

jQueryでリクエストを送ると"application/json, text/javascript, */*; q=0.01"が入っていた。

Angularでリクエストを送ると"application/json, text/plain, */*"が入っていた。

今回のAjaxController.phpの記述内容

<?php
App::uses('AppController', 'Controller');
class AjaxController extends AppController {

  //使用するModel
  public $uses = array('Contact');

  public function beforeFilter(){
    parent::beforeFilter();
    //ログインしていないときでも許可されているアクション (allow()はすべてのアクションを許可)
    $this->Auth->allow(array(
      'find_contacts',
    ));
  }

  public function find_contacts() {
    //Ajaxでリクエストを送る為のアクションなので、Viewの描画を無効化
    $this->autoRender = false;
    //関数を定義
    function isAngular(){
      if (false !== strpos($_SERVER['HTTP_ACCEPT'], 'application/json')) {
        return true;
      }
      return false;
    }
    //Ajax以外の通信の場合
    if(!isAngular()) {
      //400 Bad Request エラー
      throw new BadRequestException();
    }
    //contactsテーブルのデータを取得
    $result = $this->Contact->find('all');
    //値が入っているかを確認(trueまたはfalseが$statusに入る)
    $status = !empty($result);
    //データが無い場合は$errorにエラー内容を格納
    if(!$status) {
      $error = array(
        'message' => 'データがありません',
        'code' => 404
      );
    }
    //$status,$result,$errorを結合して、JSON形式のデータを返す(js側で変数dataとして使用される)
    return json_encode(compact('status', 'result', 'error'));
  }

}

URLバーに直に入力してページにアクセスしたとき$_SERVER['HTTP_ACCEPT']には何が入っているのか

ContactsController.phpのindexアクションで試してみたら、"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"が入っていた。

$_SERVER['HTTP_ACCEPT']とは

PHP: $_SERVER - Manual」に

現在のリクエストの Accept: ヘッダがもしあれば その内容。

と書いてありました。

actionに引数を渡す

CakePHPなので、非同期通信の場合も以下のような感じで、アクション名に続いてスラッシュ区切りで渡せる。

https://hoge.com/コントローラー/アクション/hoge/foo/

非同期通信を使う際のセキュリティについて

$http | AngularJS 1.2 日本語リファレンス | js STUDIO

今回はここまで。