質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.81%

cakephpのsaveAllについて質問です。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,768
退会済みユーザー

退会済みユーザー

やろうとしていること

モデルの関係性(アソシエーション)

// Name model

hasMany = array(
        'Nickname' => array(
            'className' => 'Nickname',
            'foreignKey' => 'name_id',
            'dependent' => true,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        ),
    );

元のデータ

array
  'Name' => 
    array
      'name' => string 'shit'
      'number' => string 'N001'
      'id' => string '1'
  'Nickname' => 
    array
      0 => 
        array
          'name' => string 'pussy'
      1 => 
        array (size=1)
          'name' => string 'pussy2'
      2 => 
        array (size=1)
          'name' => string 'pussy3'

編集して保存したいデータ

array
  'Name' => 
    array
      'name' => string 'shit'
      'number' => string 'N001'
      'id' => string '1'
  'Nickname' => 
    array
      0 => 
        array
          'name' => string 'asshole'
      1 => 
        array
          'name' => string 'assholeshit'

コントローラ

if($this->request->data && (!empty($id))){
            try {
                $this->Name->create();
                $this->request->data['Name']['id'] = $id;
                $this->Name->begin();


                if(isset($this->data['Name']['id']) && !empty($this->data['Name']['id'])) {
                    $conditions = array('name_id' => $id);
                $this->Name->Nickname->deleteAll($conditions, false);
                }
         //追記
         //保存する前にNicknameにあるname_idで一回削除した上で保存すると保存されますが、作成日時と更新日時が 新規と同じようになってしまいます。
                if(!$this->Name->saveAll($this->request->data,array('deep' => true))){
                    $this->Flash->error('変更できません。入力内容を確認してください。');
                }
                $this->Name->commit();
                $this->Flash->success('変更しました。');
                $this->redirect(['action' => 'index']);
            }catch(Exception $e) {
                $this->Name->rollback();
            }
        }

テーブルCREATE

CREATE TABLE IF NOT EXISTS `abata`.`names` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,
  `created` DATETIME NOT NULL,
  `creator` INT(11) NOT NULL,
  `modified` DATETIME NOT NULL,
  `modifier` INT(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `name_UNIQUE` (`name` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

CREATE TABLE IF NOT EXISTS `abata`.`nicknames` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `nickname` VARCHAR(255) NOT NULL,
  `name_id` INT(11) NULL,
  `created` DATETIME NOT NULL,
  `creator` INT(11) NOT NULL,
  `modified` DATETIME NOT NULL,
  `modifier` INT(11) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

なぜか、saveAllするとnameは編集した通り保存されますが、
Nicknameの方は保存されず、追加する場合だけ保存されます。
階層の深さのせいと思い オプションにarray('deep' => true)を追加してみましたが、
ダメでした。
やはり、NicknameのIDも指定しなければならないのでしょうか?
しかし、NicknameのIDを取ろうとしても、どうやってとればいいでしょうか?

何方かお分かりであれば、教えていただけると幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KatsumiTanaka

    2016/04/20 16:23

    検証をしてみたいのですが、Name、およびNicknameテーブルのCreate文を開示していただくことは、可能でしょうか?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2016/04/20 16:38

    Create文を開示しました。
    宜しくお願い致します。

    キャンセル

回答 2

checkベストアンサー

0

とりあえず、以下のコードで、nickname側のテーブルも更新できることを確認しました

$data = array(
    'names' => array(
        'name' => 'shit',
        'id' => '1'
    ),
    'Nickname' => array(
        array(
            'id' => '2',
            'nickname' => 'asshole'
        )
    )
) ;


try {
    $this->names->create();
    $this->names->begin();
    if(!$this->names->saveAll($data,array('deep' => true))){
        $this->Flash->error('変更できません。入力内容を確認してください。');
    }
    $this->names->commit();
    $this->Flash->success('変更しました。');
    $this->redirect(['action' => 'index']);
}catch(Exception $e) {
    $this->names->rollback();
}

ポイントは、更新データのNickname配列における連想配列の0が不要というところかと思います

array
  'Name' => 
    array
      'name' => string 'shit'
      'number' => string 'N001'
      'id' => string '1'
  'Nickname' => 
    array
      0 => // これが不要
        array
          'name' => string 'asshole'


追加;

$data = array(
    'names' => array(
        'name' => 'shit',
        'id' => '1'
    ),
    'Nickname' => array(
            array(
                'id' => '1',
                'nickname' => 'asshole1'
            ),
            array(
                'id' => '2',
                'nickname' => 'asshole2'
            )
    )
) ;

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/21 14:24

    やはり、Nickenameテーブル側の レコードを指定しなければなりませんか。

    キャンセル

  • 2016/04/21 14:29

    そうですね
    bakeで生成したコードを確認すればわかると思いますが、基本的にレコードの更新は主キーで特定されたレコードを対象とするので、CakePHPの機能(アソシエーション)を使うのであれば、レコードの指定は必要だと思います

    キャンセル

  • 2016/04/21 14:50

    ありがとうございました。大変助かりました。

    キャンセル

0

確かfind()で引っ張ってきた場合と同じフォーマットでないとだめだと思います。
NicknameはhasManyなので渡すときのフォーマットは以下のようになるかと思います。

array
  'Name' => 
    array
      'name' => string 'shit'
      'number' => string 'N001'
      'id' => string '1'
      'Nickname' => 
        array
          0 => 
            array
              'name' => string 'asshole'


というようにNameの配列の中に入れてあげないといけなかったと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/21 10:43

    Nameの配列の中に Name.Nickname.0.name という配列で入れて見ましたが、ダメでした。
    しかし、元のデータがName.Nickname.0.nameではなくNickname.0.nameですのでダメかと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る