2013年5月3日金曜日

[CakePHP]Ajax との連携

  1. script.aculo.us の src 以下にある js ファイルを app/webroot/js にコピーする
  2. prototype.js を app/webroot/js にコピーする
  3. index.ctp の <head> 部に以下を追加
    <?php echo $javascript->link('prototype'); ?>
    <?php echo $javascript->link('scriptaculous'); ?>
  4. index.ctp の <body> 部に以下を追加
        <h1>link</h1>
        <div id="user">
        </div>
        <?php echo $ajax->link('View User',
        array('controller' => 'users', 'action' => 'view', 1),
        array('update' => 'user', 'complete' => 'alert("Hello World")' )
        );
        ?>
  5. views/users/view.ctp を作成
    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
    <html> <head>
    <meta name="Content-Type" content="text/html; charset=utf-8">
    
    <title></title>
    </head>
    
    <body>
    <h1><?php echo $user['User']['username'] ?></h1>
    <p>
    <small>password: <?php echo $user['User']['password'] ?></small>
    </p>
    
    <p>
    <small>趣味: <?php echo $user['Profile']['hobby'] ?></small>
    </p>
    
    </body> </html>
  6. users_controll.php に以下を追加
    var $helpers = array('Html', 'Javascript', 'Ajax');
    
    function view($id = null)
    {
     $this->User->id = $id;
     $this->set('user', $this->User->read());
    }


Auto complete
  1. script.aculo.us の src 以下にある js ファイルを app/webroot/js にコピーする
  2. prototype.js を app/webroot/js にコピーする
  3. app/views/layouts/ 以下にファイルがないとデフォルトのレイアウトが適用される。デフォルトレイアウトは cake/libs/view/layouts/default.ctp にある。
    ここにある default.ctp を app/views/layouts/ 以下にコピーして以下の箇所を変更する
    <?php
      echo $html->meta('icon');
      echo $html->css('cake.generic');
      echo $scripts_for_layout;
    ?>
  4. prototype.jp と scriptaculous.js を読み込むようにする
    echo $javascript->link('prototype');
    echo $javascript->link('scriptaculous');
  5. charset や html の meta 情報もここで定義されているので各ページには基本的に必要ない。
    index.ctp の <body> 部に以下を追加
    <h1>link</h1>
    <div id="user">
    </div>
    <?php echo $ajax->link('View User',
    array('controller' => 'users', 'action' => 'view', 1),
    array('update' => 'user', 'complete' => 'alert("Hello World")' )
    );
    ?>
    
    <h1>autoComplete</h1>
     <?php echo $form->create('User', array('url' => '/users/index')); ?>
     <?php echo $ajax->autoComplete('User.username', '/users/autoComplete')?>
     <?php echo $form->end('View user')?>
  6. views/users/view.ctp を作成
    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
    <html> <head>
    <meta name="Content-Type" content="text/html; charset=utf-8">
    
    <title></title>
    </head>
    
    <body>
    <h1><?php echo $user['User']['username'] ?></h1>
    <p>
    <small>password: <?php echo $user['User']['password'] ?></small>
    </p>
    
    <p>
    <small>趣味: <?php echo $user['Profile']['hobby'] ?></small>
    </p>
    
    </body> </html>
  7. views/users/auto_complete.ctp を作成
    <ul>
      <?php foreach($users as $user): ?>
      <li><?php echo $user['User']['username']; ?></li>
      <?php endforeach; ?>
    </ul>
  8. users_controll.php に以下を追加
    var $helpers = array('Html', 'Javascript', 'Ajax');
    
    function view($id = null)
    {
     $this->User->id = $id;
     $this->set('user', $this->User->read());
    }
    
    function autoComplete() {
     $this->set('users', $this->User->find('all', array(
             'conditions' => array(
                'User.username LIKE' => $this->data['User']['username'].'%'
              ),
             'fields' => array('username')
              )));
     $this->layout = 'ajax';
    }
  9. app/webroot/css に my.css を準備して以下を記述する
    div.auto_complete {
     position: absolute;
     width: 250px;
     background-color: white;
     border: 1px solid #888;
     margin: 0px;
     padding: 0px;
    }
    
    li.selected {
     background-color: #ffb;
    }
  10. app/views/layouts/default.ctp に my.css を読み込ませるようにする
    echo $html->css('cake.generic');
    echo $html->css('my');


Selectで選択させて表を切り替える
プルダウンメニューを表示し、選択を切り替えるとそれに該当するユーザのテスト結果のみを表・グラフで表示するようにする。
  1. index.ctp に以下を追加する。
    <?php
     echo $form->create('user_id');
     echo $form->input('user_id', array('options' => array(1, 2, 3)));
     echo $form->end();
    ?>
    <div id="result">ここに結果が</div><br>
    <?php
     echo $ajax->observeField('user_id',
         array(
               'url' => array('action' => 'exam_table_graph'),
               'frequency' => 0.2,
               'update' => 'result'));
    ?>
  2. index.ctp から Ajax 経由で呼び出される exam_table_graph.ctp を準備する。
    <body>
    <table border="1">
      <tr>
        <th>ID</th>
        <th>user_id</th>
        <th>Date</th>
        <th>math</th>
        <th>english</th>
        <th>physics</th>
      </tr>
      <?php
     foreach ($exams as $exam) {
      echo "<tr>\n";
      echo "<td>" . $exam['Exam']['id']; "</td>\n";
      echo "<td>" . $exam['Exam']['user_id']; "</td>\n";
      echo "<td>" . $exam['Exam']['date']; "</td>\n";
      echo "<td>" . $exam['Exam']['math']; "</td>\n";
      echo "<td>" . $exam['Exam']['english']; "</td>\n";
      echo "<td>" . $exam['Exam']['physics']; "</td>\n";
      echo "</tr>\n";
     }
      ?>
    </table>
    
    <?php
      echo '<img src="' . $graph_path . '"><br>';
    ?>
    
    </body>
  3. exams_controller.php に以下を追加する。
    function exam_table_graph() {
     $user_id = $this->data['user_id'] + 1;
     $conditions = array('user_id' => $user_id);
     $order = 'date';
     $exams = $this->Exam->find('all',
           array('conditions' => $conditions,
          'order' => $order));
     $this->set('exams', $exams);
     $graph_path = './exam_graph/' . $user_id;
     $this->set('graph_path', $graph_path);
     Cache::write('exams' . $user_id, $exams);
    }
    
    function exam_graph($id=null) {
     if (!$id) {
      $id = 1;
     }
     $user_id = $id;
    
     /* Cache に保存された値を読み込む */
     $exams = Cache::read('exams' . $user_id);
     if ($exams == false) {
      $conditions = array('user_id' => $user_id);
      $order = 'date';
      $exams = $this->Exam->find('all',
            array('conditions' => $conditions,
           'order' => $order));
     }
     else {
      Cache::delete('exams' . $user_id);
     }
    
     /* pChart を使用する */
     App::import('Vendor', 'pchart/pdata');
     App::import('Vendor', 'pchart/pchart');
    
     $font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";
    
     $y1data = array();
     $a = array();
    
     foreach ($exams as $exam) {
      array_push($y1data, $exam['Exam']['math']);
      array_push($a, $exam['Exam']['date']);
     }
    
     $data = new pData;
     $data->AddPoint($y1data, "math");
     $data->AddPoint($a, "date");
     $data->AddSerie("math");
     $data->SetAbsciseLabelSerie("date");
     $data->SetSerieName("数学", "math");
    
     $chart = new pChart(400, 230);
     $chart->setFontProperties($font_path,8);
     $chart->setGraphArea(50, 30, 380, 200);
    
     /* グラフに背景色をつける */
     $chart->drawFilledRoundedRectangle(7,7,393,223,5,240,240,240);
    
     /* グラフ背景に縁をつける */
     $chart->drawRoundedRectangle(5,5,395,225,5,230,230,230);
    
     /* グラフ領域に背景色をつける */
     $chart->drawGraphArea(255,255,255,TRUE);
    
     $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,TRUE,0,2,TRUE);
    
     /* グリッド線を表示する */
     $chart->drawGrid(4,TRUE,230,230,230,50);
    
     /* chart に data を配置しグラフを描く */
     /* 棒グラフの場合は drawBarGraph */
     $chart->drawBarGraph($data->GetData(), $data->GetDataDescription(), TRUE);
    
     /* 凡例を追加する */
     $chart->setFontProperties($font_path,8);
     $chart->drawLegend(596,150,$data->GetDataDescription(),255,255,255);
    
     /* グラフタイトルを追加する */
     $chart->setFontProperties($font_path,10);
     $chart->drawTitle(50,22,"数学のテスト結果",50,50,50,585);
    
     /* 画像として出力する */
     $chart->Stroke();
    }


プルダウンメニューで表示する内容を変更する
  1. exams テーブルに以下のデータが入っているとする。 Table: exams テーブル
    iduser_iddatemathenglishphysics
    112008-10-01493656
    222008-10-01454842
    332008-10-01728091
    2132008-12-158600
    2022008-12-153000
    1912008-12-154900
    2432009-03-186300
    2322009-03-185400
    2212009-03-188900
  2. ajax ヘルパーの observeField() メソッドを使用することで user_id のプルダウンメニューを定期的に監視し、変化があった時に exam_table が呼び出される。
  3. exam_table では $this->data を使用してフォームに入力された user_id の値を取得し、該当する user_id のデータのみを返すようにできる。
  4. views/exams/index.ctp に以下を記述
    <?php
     echo $form->create('user_id');
     echo $form->input('user_id', array('options' => array(1, 2, 3)));
     echo $form->end();
    ?>
    <div id="result">ここに結果が</div>
    <?php
     echo $ajax->observeField('user_id',
         array(
               'url' => array('action' => 'exam_table'),
               'frequency' => 0.2,
               'update' => 'result'));
    ?>
  5. views/exams/exams_table.ctp を追加
    <body>
    <table border="1">
      <tr>
        <th>ID</th>
        <th>user_id</th>
        <th>Date</th>
        <th>math</th>
        <th>english</th>
        <th>physics</th>
      </tr>
      <?php
     foreach ($exams as $exam) {
      echo "<tr>\n";
      echo "<td>" . $exam['Exam']['id']; "</td>\n";
      echo "<td>" . $exam['Exam']['user_id']; "</td>\n";
      echo "<td>" . $exam['Exam']['date']; "</td>\n";
      echo "<td>" . $exam['Exam']['math']; "</td>\n";
      echo "<td>" . $exam['Exam']['english']; "</td>\n";
      echo "<td>" . $exam['Exam']['physics']; "</td>\n";
      echo "</tr>\n";
     }
      ?>
    </table>
    </body>
  6. controllers/exams_controller.php に以下を追加
    function exam_table() {
     $conditions = array('user_id' => $this->data['user_id'] + 1);
     $order = 'date';
     $exams = $this->Exam->find('all',
           array('conditions' => $conditions,
          'order' => $order));
     $this->set('exams', $exams);
    }

0 件のコメント:

コメントを投稿