0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

事前に採番したそのID使われてないかも!?(CakePHP)

Last updated at Posted at 2021-11-04

はじめに

データ新規作成時、あらかじめ ID を採番しておいて、オブジェクトを持ちまわしていました
しかし、そのオブジェクトの保存処理後、採番していた ID とは違う ID で保存されていたのです

結論

patchEntity() の返り値のエンティティの id に値を設定すれば OK

CakePHPUserRepository.php
// ユーザーを保存する
public function save(User $user): UserId
{
    $model = TableRegistry::getTableLocator()->get('Users');
    $saveData = [
        'Users' => [
            // ここで ID を設定しても保存処理に採用されない
            // 'id' => $user->getId()->getValue(),
            'username' => $user->getUsername()->getValue(),
            'password' => $user->getPassword()->getValue(),
            'role' => $user->getRole()->getValue(),
        ],
    ];

    $entity = $model->newEmptyEntity();
    $entity = $model->patchEntity($entity, $saveData);
    // patchEntity() 時に ID が消え去るため、明示的に設定
    $entity->id = $user->getId()->getValue();
    $saved = $model->saveOrFail($entity);

    return new UserId($saved->id);
}

バージョン

  • PHP
    • 8.0.10
  • CakePHP
    • 4.3.0

状況

プロダクトコード

ユーザー新規追加APIで、以下のような雰囲気のコードを書いていました

CakePHPUserRepository.php
// 独自クラス
// ユーザーID を UUID で採番する
public function assignId(): UserId
{
    return new UserId(\Cake\Utility\Text::uuid());
}

// ユーザーを保存する
public function save(User $user): UserId
{
    // (略)↑の結論と同様
}
UsersController.php
// ユーザー新規追加アクション
public function add(): void
{
    $jsonData = $this->request->getData();
    $userRepository = new CakePHPUserRepository();
    $userId = $userRepository->save(
        new User(
            $userRepository->assignId(),
            new Username($jsonData['username']),
            new Password($jsonData['password']),
            new Role($jsonData['role']),
        )
    );

    $data = ['userId' => $userId->getValue()];
    $this->set($data);
    $this->viewBuilder()->setClassName('Json')->setOption('serialize', ['userId']);
}

以下の独自クラスにゲッターメソッド(getXxx()getValue())定義

  • User.php
  • UserId.php
  • Username.php
  • Password.php
  • Role.php

テストコード

しかし、テストを実行すると、ID が一致しないのです

CakePHPUserRepositoryTest.php
public function test_ユーザー情報を保存すること(): void
{
    $expect = new UserId('01509588-3882-42dd-9ab2-485e8e579a8e');
    $user = new User(
        $expect,
        new LoginId('test'),
        new Password('p@ssw0rd1'),
        new RoleName('admin'),
    );

    $actual = (new CakePHPUserRepository())->save($user);
    $this->assertEquals($expect, $actual);
}

ということで、上記の結論となります

おわりに

テストコードを作成して実行するまで、全然気づきませんでした
この記事が他のエンジニアの助けになれば幸いです

0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?