【初心者】CakePHP3入れ子データベースへの一括保存方法

こんにちはRujuuです。

今回は、CakePHP3で入れ子データベースへの、データの一括保存方法を紹介します。

入れ子データベースの作成方法がわからない方は以下の記事を参考にしてみてください!

今回の記事で使用しているデータベースもこの記事の物を流用しています。

入れ子データベースの作成 【初心者】CakePHP3の入れ子データベースの作成

環境

  • XAMPP 7.4.29
  • Windows 11
  • PHP 7.4.29
  • Apache 2.4.53
  • 10.4.24-MariaDB
  • CakePHP 3.10.4

MariaDBはMySQLから派生したDBなので、代わりにMySQLを使用してもOKです。

データベース構成

データベース構成は最初に張った参考記事と同様で、以下のように人のテーブルと趣味のテーブルで構成されています。

usersテーブル(人)

idnameage
1山田22
2佐藤21

hobbysテーブル(趣味)

idhobbyuser_id
1読書1
2ゲーム2
3散歩2

Controller編集

まずは使いまわしがしやすいように、新しく関数を作成します。

関数名は、saveRelationalDbとでもしておきましょう。

UsersController.phpのclass定義の下、15行目あたりにtable読み込み用の初期関数を含め、下記のコードを追加します。

UserController.php
public function initialize(){
    $this->users_table = TableRegistry::get('users');
}
public function saveRelationalDb($data){
    $entities = $this->users_table->newEntities($data, ['associated' => ['Hobbys']]);
    foreach($entities as $entity){
        $this->users_table->save($entity, ['associated' => ['Hobbys']]);
    }
}

1~3行目の関数はControllerが呼び出されたときに最初に実行される関数で、CakePHPで定義されているものです。その中でusersテーブルを呼んでいます。このようにしておくと、あとからは「$this->users_table」でテーブルを呼びだすことができます。

4~9行目の関数は、$dataが渡されるとusersテーブルへ$dataを保存する関数となっています。

各行を簡単に説明すると、5行目で$dataをデータベースに保存する形に修正して、6~8行目で中身を一個ずつ取り出しデータベースに保存しています。

この時重要なのが5行目と7行目の第二引数です。この第二引数へ「[‘associated’ => [‘Hobbys’]]」を渡すと、連携されているHobbysテーブルにもデータを渡してくれます。もし複数のテーブルをつなげていた場合は、[‘associated’ => [‘Hobbys’, ‘Foo’, ‘Bar’,…]]のように配列の中に追加していきます。

また、本来作成したテーブル名は小文字で「hobbys」ですが、associatedに渡したのは先頭が大文字の「Hobbys」です。これは、「relation_sample/src/Model/table/UserModel.php」に記載されている$this->hasManyの第一引数を見ればなにを渡せばよいかわかります。本記事の場合は下記のようになっているため、Hobbysを渡しています。

UserModel.php
$this->hasMany('Hobbys', [
            'foreignKey' => 'user_id',
            'dependent' => true,
        ]);

そしておそらく今のコードのままだと、「TableRegistry」が無いよとエラーが出ていると思うので、UsersControllerの5行目あたり、「namespace App\Controller;」の下の方に下記のコードを追加します。

UsersController.php
use Cake\ORM\TableRegistry;

これでデータベースに保存する仕組みは構築できました!

データ登録

実際に登録できるか、テスト用のデータで試してみましょう。

今回はUsersController.phpのindex関数内に下記の内容を追記します。

UsersController.php
// テストデータ
$data = [
    [
        'name' => '山田',
        'age' => 22,
        'hobbys' => [
            [
                'hobby' => '読書',
            ],
        ]
    ],
    [
        'name' => '佐藤',
        'age' => 21,
        'hobbys' => [
            [
                'hobby' => 'ゲーム',
            ],
            [
                'hobby' => '散歩',
            ],
        ]
    ],
];
$this->saveRelationalDb($data);

追記できたらusersのページにアクセスしてみましょう。

自分と同じフォルダ構成であれば、「http://localhost:180/test/relation_sample/users」にアクセスしてください。

するとcakePHPの画面上は特に変わっていませんが、phpMyAdminでデータベースを確認するとusersとhobbysテーブルにデータが登録されているはずです。

(必要な人のみ)重複データを登録しないようにする

最後に重複データを保存しないようにしてみましょう。

今回はusersのnameが重複した場合は登録しないようにしてみます。

UsersTable.phpの「validationDefault」関数の下に下記のコードを追記します。

UsersTable.php
public function buildRules(RulesChecker $rules){
    $rules->add($rules->isUnique(['name']));
    return $rules;
}

これでnameが同じ場合はデータベースに保存されなくなります。

name以外も重複を許したくない場合は、isUniqueの配列の中に列名を加えていってください。

おわりに

ここまで読んでくださり、ありがとうございました。

上手く、入れ子データベースにデータを一括で登録できたでしょうか?

今回の記事のソースコードも下記に貼っておきます。

今後もCakePHPに関することや、その他プログラミングに関することを紹介していくので、気に入りましたらこのブログのことを覚えていてくださると幸いです。

質問等ありましたら、優しくコメントやDMしてくださるとうれしいです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA