データの保存

データの新規作成

データの新規作成は以下の流れで行われる。

  • newEntity()でエンティティをビルド
  • エンティティのプロパティに値をセット
  • save()でエンティティを保存
<?php
use Cake\ORM\TableRegistry;

$articlesTable = TableRegistry::getTableLocator()->get('Articles');
$article = $articlesTable->newEntity();

$article->title = '新しい記事';
$article->body = 'これは記事の本文です';

$articlesTable->save($article);
?>

データの更新

データの更新も新規作成と同様にsave()で行われる。

<?php
$article = $articlesTable->get(12); // id 12 の記事を返します

$article->title = 'CakePHP は最高のフレームワークです!';
$articlesTable->save($article)
?>

アソシエーションの保存

デフォルトではsaveでアソシエーションの一階層目を保存できる。

<?php
$author = $articlesTable->Authors->findByUserName('mark')->first(); // 関連のあるテーブルからレコードを取得

$article = $articlesTable->newEntity(); // エンティティを生成
$article->title = 'mark の記事';
$article->author = $author; // 関連付け

$articlesTable->save($article); // 保存
?>

save()でアソシエーションのレコードを保存することもできる。

<?php
$Comment = $articlesTable->Comments->newEntity(); // アソシエーションのエンティティを生成
$Comment->body = 'CakePHP の機能は傑出しています';

$article = $articlesTable->get(12);
$article->comments = [$Comment]; // 関連付け

$articlesTable->save($article); // 保存
?>

関連付けにlink()を用いても可。

<?php
$articlesTable->Tags->link($article, [$tag1, $tag2]); // 関連付け
$articlesTable->save($article);

$articlesTable->Tags->unlink($article, $tags); // 関連付け解除
?>

リクエストデータをもとにエンティティを保存

getData()で取得したリクエストデータをnewEntity()に渡し、エンティティに変換。saveで保存する。

<?php
$entity = $articles->newEntity($this->request->getData());
$articlesTable->save($entity);
?>
エンティティ構築前のリクエストデータ変更

beforeMarshalイベントの中でエンティティ構築前のリクエストデータ変更処理を行う。

<?php
// ファイルの先頭に use ステートメントを入れること。
use Cake\Event\Event;
use ArrayObject;

// テーブルまたはビヘイビアークラスの中で
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    if (isset($data['username'])) {
        $data['username'] = mb_strtolower($data['username']);
    }
}
?>

マスアサインメント攻撃の回避

マスアサインメント攻撃を回避するには、エンティティの一括代入機能を使う。編集可能なプロパティの配列を$_accessibleとして定義する。

<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity
{
    protected $_accessible = [
        'title' => true,
        'body' => true,
    ];
}
?>

または、newEntity()あるいはpatchEntity()でfieldListオプションを使用する。

<?php
$data = $this->request->getData();

// タイトルのみ変更することを許します
$entity = $this->patchEntity($entity, $data, [
    'fieldList' => ['title']
]);
$this->save($entity);
?>

厳密な保存

saveOrFail()を使うと、次の条件でCake\ORM\Exception\PersistenceFailedExceptionを投げる。

  • アプリケーションルールのチェックに失敗した場合
  • エンティティーにエラーが含まれている場合
  • 保存がコールバックによって中断された場合
<?php
try {
    $table->saveOrFail($entity);
} catch (\Cake\ORM\Exception\PersistenceFailedException $e) {
    echo $e->getEntity(); // エラーの内容を表示
}
?>