Angular.js×cakePHP3.xで非同期通信の実装 その1
カテゴリ:新技術開拓記
こんにちは。inglowの開発担当です。
今回は最近よく耳にするjavascriptのライブラリ「Angular.js」とcakePHP3.xを利用した場合の非同期通信の処理を生成してみます。
今回使った技術は下記です。
- PHP(cakePHP3.8)
- javascript(angular.js)
目次
Angular.js×cakePHP3.x
webアプリケーションを作成する際にほぼ利用するものといえば、非同期通信です。
Angular.jsとcakePHP3.xでの非同期通信を調べてみたのですが、jQueryでのajaxとの通信の記事についてはたくさん出てくるのですが、Angular.jsでは意外と出てこず、今回実際に制作してみてまとめることにしました。実際に制作するにあたって出てきた問題は、下記でした。
- formタグに指定した、「ng-submit」の処理が動かない
- フォームの内容を送信するときに、cakePHP3.8のCSRFトークンチェックでエラーになる
今回の記事では、まず、「formタグに指定した、「ng-submit」の処理が動かない」を解決していきます。
Angular.jsでのsubmit時の処理
Angular.jsでsubmitする際に処理を入れる場合、属性のところに「ng-submit=”関数名()”」を記載し、「action」でURLを指定しないことで、submitされずに処理が動くという仕組みになっていますが、cakePHP3のFormヘルパーでフォームを生成すると、フォームタグの中に現在表示しているURLが入るようになってしまします。
試しに、オプションで「action => null」や「url => null」等を試してみましたが、結局URLがはいるようになってしまいます…。(actionに至っては、「urlのキーで指定してね」とメッセージが表示されます…。)
1 |
<?= $this->Form->create($entityObject, ['action' => false, 'ng-attr-action' => '{{actnm}}', 'name' => 'recip_edit', 'ng-submit' => 'sbmt()', 'ng-attr-id' => '{{form_name}}',]); ?> |
actionにURLが生成されるのを解決する
今回は、これを解決するために、「action」にnullを指定したらactionにURLを指定しないフォームを生成するヘルパーを作成することにしました。
作成するといっても、元のFormHelperを継承し(継承については、「オブジェクト指向 継承」などで検索するといろいろ解説が出てくるかと思います…)、フォームタグを生成するcreate関数を上書きして作成するような簡単なものです。
独自処理のヘルパーを作る
まずは、元のvendor/cakephp/cakephp/src/View/Helper/FormHelper.phpをコピーして、src/View/Helperの中にコピーします。
FormHelper.phpのファイル名は別のものに変更します。今回は、Angular.jsのために作成するので、「NgFormHelper.php」としました。
次にファイルを編集していきます。
まずは、クラス名と、継承元を変更します。クラス名は、ファイル名に合わせて、「NgFormHelper」、継承元(extends)には、FormHelperと記述します。
1 2 3 4 5 6 |
//クラスの始まり部分を修正します。 class NgFormHelper extends FormHelper{ //この中にいろいろ処理が書いてあります } |
次に関数の処理を変えていきます。
create()関数を探しだして(403行目あたりにあるかと思います。)、他の関数は消しておきます。
関数の処理の内容は、実際に見ていただければわかるかと思いますが、最後returnしているところで、「attrs」を指定している箇所で、「$actionAttr」という変数が結合されています。
1 2 3 4 |
return $this->formatTemplate('formStart', [ 'attrs' => $templater->formatAttributes($htmlAttributes) . $actionAttr, 'templateVars' => isset($options['templateVars']) ? $options['templateVars'] : [], ]) . $append; |
今回はこれを、actionがfalseだった場合は結合しないように処理を変更しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public function create($context = null, array $options = []) { $append = ''; $add_action = true; //フラグを追加 ・ ・ ・ //actionの指定があった時のエラーを出さないようにし、変わりにactionをつけないようにする if (isset($options['action'])) { //エラーは出さずに、actionをつけないようにする $add_action = false; //trigger_error('Using key `action` is deprecated, use `url` directly instead.', E_USER_DEPRECATED); } ・ ・ ・ //最終的に「attrs」に渡す値を事前に生成する $actionAttr = $templater->formatAttributes(['action' => $action, 'escape' => false]); $formated_attributes = $templater->formatAttributes($htmlAttributes); if($add_action){ //フラグでactionをつけるか判定する $formated_attributes .= $actionAttr; } //フォームタグを返す return $this->formatTemplate('formStart', [ 'attrs' => $formated_attributes, 'templateVars' => isset($options['templateVars']) ? $options['templateVars'] : [], ]) . $append; } |
処理が変更できたら、Templete側で呼び出してみます。呼び出す際には$this->「指定したクラス名」->create()で呼び出します。今回の場合は、$this->NgForm->create()です。無事に、actionにURLが指定されていないformが生成されたかと思います。
1 |
<?= $this->NgForm->create($recip, ['action' => false, 'ng-attr-action' => '{{actnm}}', 'name' => 'recip_edit', 'ng-submit' => 'sbmt()', 'ng-attr-id' => '{{form_name}}',]); ?> |
さいごに
今回は、angular.jsでsubmit時の処理が動かせるようにしました。次は、jqueryでのajaxの実装時にもたくさん困らされた、CSRFチェックの対応方法についてまとめていこうと思います。