・データベーステーブルが規約に準拠している場合、すぐにORMの利用を開始できる。

 use Cake\ORM\TableRegistry;

 // articlesテーブルからデータ取得

 $articles = TableRegistry::get('Articles');

 $query = $articles->find();

 foreach ($query as $row) {

  // 各$rowはArticleエンティティクラスのインスタンス

  echo $row->title;

 }


・テーブルクラスの作成

 src/Model/Table に置く。

 テーブルクラス名は、テーブル名にTableを加える。

 namespace App\Model\Table;

 use Cake\ORM\Table;

 class ArticlesTable extends Table {

 }


 ・主キーの指定

  id 以外の主キーの場合、initialize()で設定する。

  $this->setPrimaryKey('my_id');


 ・エンティティクラスの指定

  命名規則に従わないエンティティクラスを使用する場合、initialize()で設定する。

  $this->setEntityClass('App\Model\Entity\PO');


 ・ビヘイビアの追加

  ビヘイビアは、テーブルクラスの共通ロジック。

  initialize()で設定する。

  $this->addBehavior('Timestamp');


 ・データ検証

  // コントローラ側

  $article = $this->Articles->newEntity($this->request->getData());

  if ($article->errors()) {

   // 検証失敗

  }


 ・バリデーションの作成

  バリデーションは、ユーザ入力を検証する。

  // デフォルトで呼ばれるバリデーション

  public function validationDefault(Validator $validator) {

    $validator->requirePresence('title', 'create')

        ->notEmpty('title');

    $validator->allowEmpty('link')

        ->add('link', 'valid-url', ['rule' => 'url']);

    return $validator;

  }

  // バリデーションのカスタマイズ

  public function validationUpdate($validator) {

  ...

  }

  // コントローラ側

  $article = $this->Articles->newEntity($this->request->getData(), ['validate' => 'update']);


  ・requirePresence()

   バリデーション対象の配列にフィールドが実在すること。

   第2パラメータ

     create : create実行時のみ適用

     update : update実行時のみ適用

   $validator->requirePresence('author_id', 'create');

   $validator->requirePresence(['author_id', 'title'], 'create');

   $validator->requirePresence([

          'author_id' => [

              'mode' => 'create',

              'message' => 'An author is required.',

          ],

          'published' => [

              'mode' => 'update',

              'message' => 'The published state is required.',

          ]

   ]);


  ・allowEmpty()

   フィールドが空欄でもよいこと。

   第2パラメータ

     create : create実行時のみ適用

     update : update実行時のみ適用

   $validator->->allowEmpty('header_image', 'update');


  ・notEmpty()

   フィールドが空欄でないこと。

   第2パラメータ

     create : create実行時のみ適用

     update : update実行時のみ適用

   $validator->notEmpty('body', 'Body cannot be empty', 'create')


  ・add() 組み込みのバリデーションルール

   alphaNumeric:半角のアルファベットまたは数字であるか。

          'rule' => 'alphaNumeric',

   between: データ長が指定範囲内であるか。

        'rule' => array('between', 5, 15),

   blank: 空かスペースのみであるか。

       スペースには、半角スペース・タブ・キャリッジリターン・改行文字を含む。

       'rule' => 'blank',

   boolean: true/false または 0/1 または '0'/'1'であるか。

        'rule' => array('boolean'),

   cc: クレジットカード番号として適切か。

     'rule' => array('cc', array('visa', 'maestro'), false, null),

   comparison: 数字が指定範囲内であるか。

         is greater, is less, greater or equal, less or equal, equal to, not equal

         'rule' => array('comparison', '>=', 18),

         'rule' => array('comparison', 'greater or equal', 18),

   date: 日付形式であるか。

      'rule' => array('date', array('ymd')),

   decimal: データが小数であるか。小数点以下の桁数を指定。

        'rule' => array('decimal', 2)

   email: email形式であるか。trueを指定すると、メールサーバのホストが存在するか確認する。

       'rule' => array('email', true),

   equalTo: 指定値と等しいか。

        'rule' => array('equalTo', 'cake'),

   extension: ファイル名の拡張子が指定値と等しいか。

        'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg'),

   ip: IPv4形式であるか。

     'rule' => 'ip',

   isUnique: 重複しない値であるか。

        'rule' => 'isUnique',

   minLength: データ長が指定値以上であるか。

        'rule' => array('minLength', '8'),

   maxLength: データ長が指定値以下であるか。

        'rule' => array('maxLength', '15'),

   money: 金額として有効であるか。通貨記号の位置を'left'/'right'で指定。

       'rule' => array('money', 'left'),

   Multiple: 複数選択で指定した値が含まれるか。指定数の最小値と最大値を指定。

       'rule' => array('multiple', array('in' => array('foo', 'bar'), 'min' => 1, 'max' => 3)),

   inList: 指定リストに含まれるか。

       'rule' => array('inList', array('Foo', 'Bar')),

   numeric: 数字または数値形式であるか。

       'rule' => 'numeric',

   notEmpty: 空でないか。

        'rule' => 'notEmpty',

   phone: アメリカの電話番号形式であるか。日本の場合は、電話番号形式の正規表現を第2パラメータに指定。

       'rule' => array('phone', null, 'us'),

   postal: 郵便番号形式であるか。日本の場合は、郵便番号形式の正規表現を第2パラメータに指定。

       'rule' => array('postal', null, 'us')

   range: 指定範囲内の値であるか。

       'rule' => array('range', 0, 10),

   ssn: 社会保障番号であるか。

      'rule' => array('ssn', null, 'us')

   url: URL形式であるか。

     'rule' => 'url'


・ルールの作成

 ルールは、コード中で変更されたデータを検証する。

 ルールは save()及びdelete()メソッド実行時にチェックされる。

 テーブルクラスのbuildRules()メソッドに定義する。

 public function buildRules(RulesChecker $rules) {

  // add, update時のルール

  $rules->add(function ($entity, $options) {

  ...

  }, 'ruleName');

  // add時のルール

  $rules->addCreate(function ($entity, $options) {

  ...

  }, 'ruleName');

  // update時のルール

  $rules->addUpdate(function ($entity, $options) {

  ...

  }, 'ruleName');

  // delete時のルール

  $rules->addDelete(function ($entity, $options) {

  ...

  }, 'ruleName');

  return $rules;

 }


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

 src/Model/Entity に置く。

 エンティティクラス名は、テーブル名。

 namespace App\Model\Entity;

 use Cakd\ORM\Entity;

 class Article extends Entity {

 }


 ・エンティティのデータへのアクセス

  $this->Articles->title;


 ・get

  get()をカスタマイズする際に使用する。

  protected function _getTitle($title) {

   return ucwords($title);

  }

  // コントローラ側

  echo $this->Articles->title;


 ・set

  set()をカスタマイズする際に使用する。

  protected function _setTitle($title) {

   return Text::slug($title);

  }

  // コントローラ側

  $this->Articles->title = 'foo';


 ・仮想プロパティの生成

  存在しないフィールドを作成し、アクセスを提供する。

  protected function _getFullName() {

   return $this->_properties['first_name'] . ' ' . $this->_properties['last_name'];

  }

  // コントローラ側

  echo $this->Users->full_name;


 ・エンティティの変更チェック

  ・フィールドの変更チェック

   $this->Articles->dirty('title');


  ・変更を設定する

   $this->Articles->comments[] = $newComment;

   $this->Articles->dirty('comments', true);


  ・変更前の値を取得する

   $org = $this->Articles->getOriginal('title');


  ・変更されたフィールド一覧を取得する

   $dirtyFields = $this->Articles->getDirty();


 ・一括代入

  リクエストからユーザデータをエンティティへ一括代入できるかを指定する。

  protected $_accessible = [

             'title' => true,

             'body' => true,

             '*' => false,]; // 指定されていないフィールド

  コントローラ側でアクセス可・不可を設定する。

  $this->Articles->accessible('user_id', true);


 ・エンティティがDB上に存在するデータかチェックする

  if (!$this->Articles->isNew()) {

   echo 'already registered.';

  }


 ・エンティティから配列への変換

  $array = $this->Users->toArray();


 ・エンティティからJSONへの変換

  $json = json_encode($this->Users);


・接続設定

 config/app.php に 'default' の接続設定をする。


・データベースアクセスAPIで出来ること

 ・データベース接続

  use Cake\Datasource\ConnectionManager;

  $dsn = 'mysql://root:password@localhost/my_database';

  ConnectionManager::config('default', ['url' => $dsn]);

  $con = ConnectionManager::get('default');

 

 ・select

  $results = $con->execute('select * from articles where id = :id', ['id' => 1])

         ->fetchAll('assoc');

 ・insert

  $con->insert('articles',['title' => 'A New Article',

            'created' => new DateTime('now')],

            ['created' => 'datetime']);


 ・update

  // id=10を更新

  $con->update('articles',['title' => 'New Title'],

            ['id' => 10]);


 ・delete

  $con->delete('articles', ['id' => 10]);


 ・query

  パラメータは使用できない。

  $con->query('update articles set published = 1 where id = 2');


 ・execute

  パラメータ、型指定を使用できる。

  $con->execute('update articles set published_date = ? where id = ?', [new DateTime('now'), 2], ['date', 'integer']);


 ・トランザクション

  $con->begin();

  $con->execute('update articles set published = ? where id = ?', [true, 2]);

  $con->execute('update articles set published = ? where id = ?', [false, 4]);

  $con->commit();

  // bigen,commit,rollbackを自動でハンドリングする

  $con->transactional(function ($con) {

     $con->execute('update articles set published = ? where id = ?', [true, 2]);

     $con->execute('update articles set published = ? where id = ?', [false, 4]);

   });


 ・結果行の取得

  $stmt->execute('select ...');

  // 1行読み込む

  $row = $stmt->fetch('assoc');

  // 全行読み込む

  $rows = $stmt->fetchAll('assoc');

  foreach ($rows as $row) {

  }


 ・行数の取得

  $stmt->execute('select ...');

  $rowCount = count($stmt);

  $rowCount = $stmt->rowCount();


・クエリオブジェクト

 ・クエリオブジェクトの作成

  $articles = TableRegistry::get('Articles');

  $query = $articles->find();

  // コントローラの場合

  $query = $this->Articles->find();


 ・メソッドをチェーンする

  $query = $this->Articles->find()

        ->select(['id', 'name'])

        ->where(['id !=' => 1])

        ->order(['created' => 'DESC']);


 ・主キーで単一のエンティティを取得する

  $article = this->Articles->get($id);


 ・カラムから値リストを取得する

  $allTitles = $this->Articles->extract('title');

  foreach ($allTitles as $title) {

   echo $title;

  }


 ・クエリはCollectionオブジェクト

  Collectionオブジェクトで使用できるメソッドは、クエリオブジェクトでも使用できる。

  $keyValueList = $this->Articles->find()->combine('id', 'title');


 ・SQL関数

  $query=$this->Articles->find();

  $query->select(['count' => $query->func()->count('*']);

  sum()

  avg()

  min()

  max()

  count()

  concat() : 2つの値を結合する。

  coalesce()

  dateDiff() : 2つの日にち/時間の差を取得する。

  now()

  extract() : SQL式から特定の日付部分(年など)をかえす。

  dateAdd()

  dayOfWeek()


 ・Group と Having

  $query = $this->Articles->find();

  $query->select(['count' => $query->func()->count('view_count'),

         'published_date' => 'DATE(created)'])

     ->group('published_date')

     ->having(['count >' => 3]);


 ・Case

  select

   count(case when published = 'Y' then 1 end) as number_published

  from articles

  $query = $this->Articles->find();

  $publishedCase = $query->newExpr()

             ->addCase($query->newExpr()->add(['published' => 'Y']),

1, 'integer');

  $query->select(['number_published' => $query->func()->count($publishedCase)]);


 ・エンティティの代わりに配列を取得

  $query = $this->Articles->find();

  $query->hydrate(false); // エンティティの代わりに配列を返す

  $result = $query->toList() // クエリを実行し配列を返す


 ・高度な条件

  $query = $this->Articles->find()

             ->where(['author_id' => 3,

                 'OR' => [['view_count' => 2],['view_count' => 3]]]);

  $query = $this->Articles->find()

             ->where(['author_id' => 2])

             ->orWhere(['author_id' => 3])

             ->andWhere(['published' => true,

                   'view_count >' => 10])

             ->orWhere(['promoted' => true]);


 ・In

  // カラムのデータ型を明示する

  $query = $this->Articles->find()

             ->where(['id' => $ids], ['id' => 'integer[]']);

  // もしくはINを含める

  $query = $this->Articles->find()

             ->where(['id IN' => $ids]);


 ・結果を取得する

  // イテレートする

  foreach($query as $row) {

  }

  // 結果を取得する

  $results = $query->all();

  // コレクションのメソッドを使う

  $ids = $query->map(function ($row) {

   return $row->id;

  });

  // 最初の行だけ取得する

  $row = $query->first();


 ・関連付くデータをロードする

  article毎に、authorとcommentをロードする。

  $query = $this->Articles->find()

             ->contain(['Authors', 'Comments]);

 

 ・inner join with

  $query = $this->Articles->find();

  $query->innerJoinWith('Tags', function ($q) {

               return $q->where(['Tags.name' => 'CakePHP']);

  });


 ・データをinsertする

  $query = $this->Articles->query;

  $query->insert(['title', 'body'])

     ->values(['title' => 'First post',

         'body' => 'Some body text'])

     ->values(['title' => 'Second post',

         'body' => 'Another body text'])

    ->execute();

  // または

  $article = $this->Articles->newEntity();

  $article->title = 'this is a new article.';

  $article->body = 'this is a body.';

  if ($this->Articles->save($article)) {

   // 登録されたデータのid

   $id = $article->id;

  }


 ・データをupdateする

  $query = $this->Articles->query();

  $query->update()

     ->set(['published' => true])

     ->where(['id' => $id])

     ->execute();

  // または

  $article = $this->Articles->get(12);

  $article->title = 'changed title';

  $this->Articles->save($article);


 ・データをdeleteする

  $query = $this->Articles->query();

  $query->delete()

     ->where(['id' => $id])

     ->execute();


 ・関連テーブルのデータ追加・更新

  $tag1 = $this->Articles->Tags->findByName('cakephp')->first();

  $tag2 = $this->Articles->Tags->newEntity();

  $tag2->name = 'fantastic';

  $article = $this->Articles->get(12);

  $article->tags = [$tag1, $tag2];

  // 外部キーは自動でセットされる。

  $this->Articles->save($article);


 ・中間テーブルへのデータ保存

  // 最初にレコードを紐づける。

  $tag1 = $this->Articles->Tags->findByName('cakephp')->first();

  $tag1->_joinData = $this->Articles->ArticlesTags->newEntity();

  $tag1->_joinData->tagComment = 'this is a tag comment.';

  $this->Articles->Tags->link($article, [$tag1]);

  // 既存のアソシエーションを更新する。

  $article = $this->Articles->get(1, ['contain' => ['Tags']]);

  $article->tags[0]->_joinData->tagComment = 'this is a new comment';

  // 必須

  $article->dirty('tags', true);

  $this->Articles->save($article, ['associated' => ['Tags']]);


 ・SQLインジェクション対策

  バインディングを使用する。

  $query->where(['MATCH (comment) AGAINST (:userData)',

         'created < NOW() - :moreUserData'])

     ->bind(':userData', $userData, 'string')

     ->bind(':moreUserData', $moreUserData, 'datetime');


 ・UNION

  $query1 = $this->Articles->find()

             ->where(['need_review' => true]);

  $query2 = $this->Articles->find()

             ->where(['published' => false]);

  $query2->union($query1);


 ・ステートメントのロック

  $query->epilog('FOR UPDATE');


via System Development Tips
Your own website,
Ameba Ownd