FuelPHPでhas_one関係である2つのテーブルに同時にInsertしたい
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 2,112
実現したいこと
FuelPHPで管理者が新規会員を登録する機能を作っています。
has_one関係にあるusersテーブルとprofileテーブルに同時にInsertしたい。
FuelPHP1.8
データベースにはMySQLを使用しています。
テーブル
usersテーブル
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) unsigned NOT NULL PRIMARY KEY,
`username` varchar(30) NOT NULL,
`password` varchar(255),
`email` varchar(255) NOT NULL,
`created_at` int(11) NOT NULL,
`updated_at` int(11) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
profileテーブル
CREATE TABLE IF NOT EXISTS `profile` (
`profile_users_id` int(11) unsigned NOT NULL PRIMARY KEY,
`profile_name` varchar(20) NOT NULL,
`profile_address` varchar(100),
`profile_created_at` int(11) NOT NULL,
`profile_updated_at` int(11) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
モデル
APPPATH/classes/model/user.php
class Model_User extends \Orm\Model
{
protected static $_table_name = 'users';
protected static $_primary_key = array('id');
protected static $_properties = array(
'id',
'username',
'password',
'email',
'created_at',
'updated_at',
);
protected static $_observers = array(
'Orm\Observer_CreatedAt' => array(
'events' => array('before_insert'),
'mysql_timestamp' => false,
),
'Orm\Observer_UpdatedAt' => array(
'events' => array('before_update'),
'mysql_timestamp' => false,
),
);
protected static $_has_one = array(
'profile' => array(
'key_from' => 'id',
'model_to' => 'Model_Profile',
'key_to' => 'profile_users_id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
}
APPPATH/classes/model/profile.php
class Model_Profile extends \Orm\Model
{
protected static $_table_name = 'profile';
protected static $_primary_key = array('profile_users_id');
protected static $_properties = array(
'profile_users_id',
'profile_name',
'profile_address',
'profile_created_at',
'profile_updated_at',
);
protected static $_observers = array(
'Orm\Observer_CreatedAt' => array(
'events' => array('before_insert'),
'mysql_timestamp' => false,
'property' => 'profile_created_at',
'overwrite' => true,
),
'Orm\Observer_UpdatedAt' => array(
'events' => array('before_update'),
'mysql_timestamp' => false,
'property' => 'profile_updated_at',
),
);
protected static $_belong_to = array(
'users' => array(
'key_from' => 'profile_users_id',
'model_to' => 'Model_User',
'key_to' => 'id',
'cascade_save' => false,
'cascade_delete' => false,
)
);
}
コントローラのアクション
public function action_create()
{
if (Input::method() == 'POST')
{
$user = Model_User::forge(array(
'username' => Input::post('username'),
'password' => base64_encode(hash_pbkdf2(
'sha256',
Input::post('password'),
\Config::get('auth.salt'),
\Config::get('auth.iterations', 10000),
32,
true
)),
'email' => Input::post('email'),
'created_at' => \Date::forge()->get_timestamp(),
'updated_at' => 0,
));
$user->profile = Model_Profile::forge(array(
'profile_name' => Input::post('profile_name'),
'profile_address' => Input::post('profile_address'),
'profile_updated_at' => 0,
));
if ($user and $user->save())
{
// 登録成功
Session::set_flash('success', '新しい会員『'. $user->profile->profile_name .'』を追加しました。');
Response::redirect('admin/member/index');
}
}
$this->template->title = "新規会員登録";
$this->template->content = View::forge('admin/member/create');
}
※バリデーションに関する記述は省略しています。
困っていること
これで、usersテーブルとprofileテーブルのそれぞれにInsert文が実行されると思ったのですが、
usersテーブルにしかInsertされませんでした。
ここまでは以下のドキュメントを参考にしました。
FuelPHP日本語ドキュメント > ORM > リレーション:Has One
http://fuelphp.jp/docs/1.8/packages/orm/relations/has_one.html
試しに、コントローラの以下部分、
if ($user and $user->save())
ここを次のようにしてみたら、profileテーブルにもInsertできましたが、
profile_users_idが正しく(意図した通りに)セットされませんでした。
if ($user and $user->save() and $user->profile->save())
2つのテーブルにInsertする方法をご教授いただけますと幸いです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
ダンプするとわかるかと思いますが、$user->profile
に\Model_Profile
オブジェクトが既に生成されているはずです。ですので、$user->profile->カラム名
としてそのまま続けることができます。
あとは、$user->save()
をすると、勝手に$user->id
にauto_increment
されたID
が入っています。
トランザクションと、try~catchを入れるとこんな感じだと思います。
FuelPHPで新規登録などを実装するならSimpleAuthを使用すると便利だと思います。拡張も簡単にできます。
public function action_create()
{
if (Input::method() == 'POST')
{
try {
// トランザクションスタート
\DB::start_transaction();
$user = Model_User::forge(array(
'username' => Input::post('username'),
'password' => base64_encode(hash_pbkdf2(
'sha256',
Input::post('password'),
\Config::get('auth.salt'),
\Config::get('auth.iterations', 10000),
32,
true
)),
'email' => Input::post('email'),
'created_at' => \Date::forge()->get_timestamp(),
'updated_at' => 0,
));
$user->save();
if (!empty($user->id))
{
$user->profile->profile_users_id = $user->id;
$user->profile->profile_name = Input::post('profile_name');
$user->profile->profile_address = Input::post('profile_address');
$user->profile->profile_updated_at = 0;
$user->profile->save();
// コミット
\DB::commit_transaction();
// 登録成功
Session::set_flash('success', '新しい会員『'. $user->profile->profile_name .'』を追加しました。');
Response::redirect('admin/member/index');
}
// ロールバック
\DB::rollback_transaction();
}
catch (\Exception $e) {
// エラー処理
// ロールバック
\DB::rollback_transaction();
}
}
$this->template->title = "新規会員登録";
$this->template->content = View::forge('admin/member/create');
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
Tomakさんに教えていただいた内容を元にたどりついた結果です。
$user->save()だけで意図したとおり、2つのデーブルにInsertすることができました。
public function action_create()
{
if (Input::method() == 'POST')
{
try
{
// トランザクションスタート
\DB::start_transaction();
$user = Model_User::forge(array(
'username' => (string) Input::post('username'),
'password' => base64_encode(hash_pbkdf2(
'sha256',
(string) Input::post('password'),
\Config::get('auth.salt'),
\Config::get('auth.iterations', 10000),
32,
true
)),
'email' => Input::post('email'),
'created_at' => \Date::forge()->get_timestamp(),
'updated_at' => 0,
));
$user->profile = new Model_Profile();
$user->profile->profile_name = Input::post('profile_name');
$user->profile->profile_address = Input::post('profile_address');
$user->profile->profile_updated_at = 0;
// DB保存
if ($user->save())
{
// コミット
\DB::commit_transaction();
// 登録成功
Session::set_flash('success', '新規会員『'. $user->profile->profile_name. '』を追加しました。');
Response::redirect('admin/member/index');
}
// ロールバック
\DB::rollback_transaction();
}
catch (\Exception $e)
{
// ロールバック
\DB::rollback_transaction();
Session::set_flash('error', '登録できませんでした。');
}
}
$this->template->title = '新規会員登録';
$this->template->content = View::forge('admin/member/create');
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/08/30 20:15
私の理解不足もあり、途中エラーが出たりしましたが、いただいた以下をヒントを元に乗り切ることができました。
ありがとうございました!!!
・$user->profileに\Model_Profileオブジェクトが既に生成されているはず
・$user->profile->カラム名としてそのまま続けることができる
・$user->save()をすると、勝手に$user->idにauto_incrementされたIDが入っています
あとは、おっしゃるとおりSimpleAuthを使用したいので、
AuthインスタンスとModel_Userインスタンスと、いまいち理解できていないところがありますが、
試行錯誤してみようと思います。
2017/08/30 20:53
2017/08/30 23:04
トランザクション、try〜catchなど、まだまだ理解不足が多く、とても勉強になりました。
ありがとうございました。