環境
PHP 7.2.21
CakePHP 2.10.18
やりたいこと
フォームのtextboxにIDを入力するとAjaxで非同期通信し、その値を元に検索して得たデータを表示したい
やったこと
ControllerにてAjax用の関数を追加しセキュリティを変更
Viewでは表示エリアとAjaxのJavascriptを追加
Controller/HogeController.php
/**
* beforeFilter method
*
* @return void
*/
public function beforeFilter(): void {
parent::beforeFilter();
// Ajax通信の為セキュリティを解除
$this->Security->unlockedActions = ['fetchDBData'];
}
/**
* 入力されたIDを元にAjaxで名前を取得するpublic関数
*/
public function fetchDBData() {
// 表示はせずにデータをやりとりする関数なのでView不要の記述
$this->autoRender = false;
if ($this->RequestHandler->isAjax()) {
if ($this->request->data) {
$inputId = Hash::get($this->request->data, 'input_id');
}
$inputName = $this->Fuga->getFugaName($inputId);
if (strlen($inputName) === 0) {
return '※存在しません';
} else {
return $inputName;
}
}
}
View/Hoge/index.ctp
<!-- フォーム -->
<?php echo $this->Form->create('Hoge'); ?>
<?= $this->Form->input('modified_by', ['type' => 'hidden']) ?>
<table class="formTable defaultTable">
<colgroup>
<col class="em8" />
</colgroup>
<tr>
<th>対象ID</th>
<td>
<!-- ID入力 -->
<?php
echo $this->Form->input('input_id', [
'type' => 'text',
'div' => false,
'label' => false,
'required' => false,
]);
?>
<!-- 入力IDに応じて名前表示 -->
<span id="input_name"></span>
</td>
</tr>
</table>
<div class="submitArea">
<ul class="submitButtons">
<li>
<label class="submitBase primary" for="submit">
<?php
echo $this->Form->submit('保存', ['id' => 'submit']);
?>
保存
</label>
</li>
<li>
<?php echo $this->Html->link('戻る', $this->Session->read('Hoge.lastIndexUrl'), ['class' => 'submitBase inverse']); ?>
</li>
</ul>
</div>
<?php echo $this->Form->end(); ?>
<!-- Javascript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
// ID内容変更時
$('#HogeInputId').change(function() {
getNameWithAjax();
});
// 名前を非同期に取得して表示
function getNameWithAjax() {
const inputId = $('#HogeInputId').val();
$.ajax({
url: '/Hoge/fetchDBData',
type:'POST',
data: {
'input_id': inputId,
},
})
.then(
data => $('#input_name').text(data),
error => alert('名前の読み込みエラー')
);
}
</script>
結果
できました!!
success:とかerror:とかはもう非推奨なので使ってはいけませぬ
エラー集
HTTP 400
chrome console
jquery.js:9659 POST https://{YOUR_DOMAIN}/Hoge/fetchDBDat 400 (Bad Request)
errorlog
2019-12-16 16:13:39 Error: [AuthSecurityException] The request has been black-holed
Request URL: /Hoge/fetchDBData
Stack Trace:
# 0 /vagrant/Vendor/cakephp/cakephp/lib/Cake/Controller/Component/SecurityComponent.php(490): SecurityComponent->_validToken(Object(HogeController))
修正箇所
HogeController.php
// beforeFilterにセキュリティを解除が抜けている
$this->Security->unlockedActions = ['fetchDBData'];
HTTP 404
chrome console
jquery.js:9659 POST https://{YOUR_DOMAIN}/Hoge/fetchDBData 404 (Not Found)
errorlog
2019-12-16 15:44:03 Error: [PrivateActionException] Private Action HogeController::fetchDBData() is not directly accessible.
Exception Attributes: array (
'controller' => 'HogeController',
'action' => 'fetchDBData',
)
Request URL: /Hoge/fetchDBData
Stack Trace:
# 0 /vagrant/Vendor/cakephp/cakephp/lib/Cake/Routing/Dispatcher.php(193): Controller->invokeAction(Object(CakeRequest))
修正箇所
HogeController.php
private function fetchDBData() {
// 処理
}
// ↓ アクセス修飾子をprivate→publicに変更
public function fetchDBData() {
// 処理
}
HTTP 500
chrome console
POST https://{YOUR_DOMAIN}/Hoge/fetchDBData 500 (Internal Server Error)
errorlog
2019-12-16 15:00:02 Error: [MissingViewException] View file "/vagrant/oauth/app/.../.../View/Hoge/fetch_d_b_data" is missing.
Exception Attributes: array (
'file' => '/vagrant/oauth/app/.../.../View/Hoge/fetch_d_b_data.ctp',
)
Request URL: /Hoge/fetchDBData
Stack Trace:
# 0 /vagrant/Vendor/cakephp/cakephp/lib/Cake/View/View.php(470): AppView->_getViewFileName('Hoge...')
修正箇所
HogeController.php
public function fetchDBData() {
// View不要の記述が抜けている
$this->autoRender = false;
}
}