Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

おさらい

いままでのおさらい。

プロジェクト作成

mkdir hoge
php composer.phar create-project --prefer-dist cakephp/app hoge

Hello World

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $autoRender = false;
    public function index() {
      echo "hello world!!";
    }
  }
?>

hello/other

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $autoRender = false;
    public function index() {
      echo "hello, world!!";
    }
    public function other() {
      echo "hello, other world!!";
    }
  }
?>

フォワードとリダイレクション

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = false;
    public function index() {
      echo "hello, world!!";
    }
    public function other() {
      echo "hello, other world!!";
    }

    // アクションを指定
    public function forw() {
      $this->setAction(other);
    }
    
  // ブラウザにベージ移動を依頼する
    public function red() {
      $this->redirect("/hello/other");
    }

  }
?>

テンプレート

作る場所の例
src/Template/Hello/index.ctp

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta http-equiv="content-type" content="text/html;
  charset=UTF-8">
  <title>Hello Page</title>
</head>

<body>
    <h1>midashi</h1>
    <p> hello hello </p>
</body>
</html>

コントローラ側でautoRenderをtrueにしてテンプレートを読み込む。

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = true;
    public function index() {
      $this->viewBuilder()->autoLayout(false);
    }
  }
?>

autoLayoutをtrueにする場合、テンプレートは

   <h1>midashi</h1>
    <p> hello hello </p>

だけでよく、デフォルトのsrc/Template/Layout/default.ctp
が適用される。

レイアウト

スタイルシートを用意する。
webroot/css/cake.hello.css

body {
  background: #eee;
  color: #999;
  margin: 10px 8px
}

#header {
  font-size: 18pt;
  font-weight: bold;
  margin: 10px;
}

#content {
  background: #fff;
  color: #999;
  padding: 10px 25px 30px 25px;
  font-size: 14pt;
}

#footer {
  text-align: right;
  font-size: 12pt;
  margin: 10pt;
}

h1 {
  color: #aaa;
  font-size: 24pt;
  margin: 20pt 0pt 50pt 0pt;
}

cssを利用する側のテンプレートを書く
src/Template/Layout/hello.ctp

<!DOCTYPE html>
<html>
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <?= $this->fetch('title') ?>
    </title>
    <?= $this->Html->meta('icon') ?>

    <?= $this->Html->css('cake.hello.css') ?>

    <?= $this->fetch('meta') ?>
    <?= $this->fetch('css') ?>
    <?= $this->fetch('script') ?>
</head>

<!-- fetchでコントローラの変数を取ってきている。 -->

<body>

<div id="container">
  <div id="header">header</div>

  <div id="content">
      <?=$this->fetch('content') ?>
  </div>

  <div id="footer">footer</div>

</body>
</html>

jsも使いたい場合、ファイルをwebroot/js/cake.hello/jsに用意し、

   <?= $this->Html->script('cake.hello.js') ?>

を追加する。

最後に、コントローラでレイアウトを指定する。

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = true;
    public function index() {
      $this->ViewBuilder()->layout('Hello');
    }
  }
?>

エレメント

レイアウトにはめ込んで使える。Templete/Elementフォルダにいれておき、

 <?= $this->element('hoge') ?>

で読み込める。

値を渡す場合

 <?= $this->element('hoge', ['x'=>10,'y'=>5]) ?>

値の受け渡し

コントローラからテンプレートへ

      $this->set('poi',10);

テンプレート側は

  <p>
      <?= $poi ?>
    </p>

AppController->requestの連想配列

params 送信された値すべて
data POSTされた際の内容
query クエリー
url 送信アドレス
base ベースのディレクト
webroot webrootディレクト
here 現在のアドレス

フォームヘルパー

テンプレート側

  <p> ヘルパーを使ったフォームの送信</p>

    <p>
      <?= $result; ?>
    </p>

    <!-- FormHelperクラスを使ってformタグ生成 第1引数は値を保管するモデル名だが指定していないのでnull-->
    <?= $this->Form->create(null,
    ['type' => 'post',
    'url' => ['controller' => 'Hello', 'action' => 'index']]) ?>

    <!-- inputタグ生成 フィールド名を指定、HelloFormのところはモデル名を指定していればそれを入れる -->
    <?= $this->Form->text("HelloForm.text1") ?>

    <!-- 送信ボタンタグ -->
    <?= $this->Form->submit("送信") ?>

    <!-- タグの終了 -->
    <?= $this->Form->end(); ?>

コントローラ側

<?php
  namespace App\Controller;

  class HelloController extends AppController {

// 略

    public function index() {

// 略

      $result = "";

      if ($this->request->isPost()) {

        $result = "<pre>送信情報<br/>";

        foreach ($this->request->data['HelloForm'] as $key => $value) {
          $result .= $key . ' => ' . $value;
        }

        $result .= "</pre>";

      } else {
        $result = "送信してください";
      }
      $this->set("result", $result);
    }

// 略


  }
?>

モデル = テーブル + エンティティ

例としてBoardモデルを考える

モデル Board キャメル記法
データベーステーブル boards 小文字複数形 アンダースコア記法(クラスでないので)
エンティティ Board Board.php キャメル記法(クラスなので)
コントローラ BoardsController BoardController.php キャメル記法(クラスなので)
ビュー(テンプレート) Template/Boards index.ctp等を配置

SQLiteの用意

SQLite3で自前で作る。ダミーレコードもいれておく

$ sqlite3 mydata
sqlite> create table 'boards' ( 'id' integer primary key autoincrement, 'name' text not null, 'title' text, 'content' text);
sqlite> insert into 'boards' values (1,'name','test','test!');
sqlite> insert into 'boards' values (2,'name2','test2','test?');

.tables, select * from 'boards'等で確認

データベース設定

Config/app.php のDatasourcesをいじる

<?-
// 略
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql', // ここをSqliteに
            'persistent' => false,
            'host' => 'localhost', // 消す
            //'port' => 'non_standard_port_number',
            'username' => 'my_app', // 消す
            'password' => 'secret', // 消す
            'database' => 'my_app', // ROOT . DS . 'db' . DS . 'mydata' とする(使うファイル名を、拡張子あるならそれをつけて)。DSはパス区切りを表す。
            'encoding' => 'utf8',
            'timezone' => 'UTC',
            'flags' => [],
            'cacheMetadata' => true,
            'log' => false,

            'quoteIdentifiers' => false,

            //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],

            'url' => env('DATABASE_URL', null),
        ],

// 略

    ],
->

これでアプリ名にアクセス(例  ***/hoge)でwelcomeページをみて、下の方のdatabaseの項目が「CakePHP is able to connect to the database.」にチェックがついていることを確認する。

エンティティクラスの作成

src/Model/EntityにBoard.phpファイルを作成

<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Board extends Entity {
  // 値の一括代入用の設定 id以外のすべては一括代入可能
  protected $_accessible = [
    '*' => true,
    'id' => false
  ];
}

?>

テーブルクラスのファイルを作成

src/Model/TableにBoardsTable.phpファイルを作成

<?php 
  namespace App\Model\Table;

  use Cake\ORM\Table;

  class BoardsTable extends Table {
    
  }

 ?>

コントローラの作成

<?php
namespace App\Controller;

class BoardsController extends AppController {
  public function index() {
    $data = $this->Boards->find('all'); // $dataはQueryクラス
    $this->set('data', $data);
  }
}
?>

ビューの作成

src/Template内にBoardsフォルダを作成、index.ctpファイルを作る。

<h1> データ </h1>
<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>NAME</th>
      <th>TITLE</th>
      <th>CONTENT</th>
    </tr>
  </thead>
  <tbody>
    <?php foreach ($data as $obj): ?> <!-- $objはBoardエンティティクラス -->
      <tr>
        <td> <?= $obj->id ?> </td>
        <td> <?= h($obj->name) ?></td>
        <td> <?= h($obj->title) ?></td>
        <td> <?= h($obj->content) ?></td>
      </tr>
    <?php endforeach; ?>
  </tbody>
</table>

HTMLヘルパーでテーブルを作る

<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>NAME</th>
      <th>TITLE</th>
      <th>CONTENT</th>
    </tr>
  </thead>
  <?php
  $arr = $data->toArray();// 配列に取り出す
  for ($i = 0 ; $i < count($arr); $i++) {
    echo $this->Html->tableCells(
      $arr[$i]->toArray(),
      ['style' => 'background-color:#f0f0f0'],
      ['style' => 'font-weight:bold'],
      true);
  }
  ?>
</table>