LoginSignup
3
3

More than 3 years have passed since last update.

🍰【CakePHP2】フォームの入力値をリアルタイムにAjaxで非同期通信して検索結果を表示させる

Last updated at Posted at 2019-12-17

環境

PHP 7.2.21
CakePHP 2.10.18

やりたいこと

フォームのtextboxにIDを入力するとAjaxで非同期通信し、その値を元に検索して得たデータを表示したい

ID入力
before.png

IDに紐づく値を隣に表示
after.png

やったこと

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;
    }
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3