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

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

ただいまの
回答率

89.64%

[CakePHP 2.X]「既存レコードの更新」と「新規レコードの登録」を一つの画面で行いたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,835

hiro_87g

score 22

「既存レコードの更新」と「新規レコードの登録」を一つの画面で行いたいのですが、うまくできずに困っております。つまずいているポイントが2箇所ありまして、下記のソース内に

★悩みポイント1★

★悩みポイント2★

というカタチで記載させていただいてます。

もし解決方法をご存知の方がいましたらご教授いただけますと幸いです。

よろしくお願いします。


■cakeのバージョン:2.7

■データベース(テーブル名:hoges)

id    |    text

~~~~~~~~~~~~~~~~~~~~~

1    |    りんご

2    |    バナナ

3    |    スイカ

■Model/Hoge.php

<?php
class Hoge extends AppModel {
}
?>

■View/Hoges/index.ctp

<?php echo $this->Form->create('Hoge'); ?>
<ul>
    <!-- すでに登録してあるレコード情報を表示・更新するエリア -->
    <?php foreach ($hoges as $hoge) :?>
        <li>
            <?php echo $this->Form->input('Hoge.' . $hoge['Hoge']['id'] . '.text', array(
                'type' => 'text',
                'default' => $hoge['Hoge']['text']
                ));
            ?>
        </li>
    <?php endforeach; ?>
    <!-- /すでに登録してあるレコード情報を表示・更新するエリア -->

    <!-- 新しく情報を登録するエリア -->
    <!-- ★悩みポイント1★ -->
    <!-- ここに情報が入力された場合、新規レコードとして登録したいのですが出来ずに困っています…。 -->
        <li>
            <?php echo $this->Form->input('text');?>
        </li>
    <!-- /新しく情報を登録するエリア -->
</ul>
<?php echo $this->Form->end('保存'); ?>

■Controller/HogesController.php

<?php

class HogesController extends AppController {
    public function index($id=NULL) {
        $this->hoges = $this->Hoge->find('all');
        $this->set('hoges',$this->hoges);


        if ($this->request->is('post')) {

            //★悩みポイント2★
            //下記のように
            //$text = $this->request->data['Hoge'][1]['text'];
            //とすると一番上に入力した値で更新されるのですが、これをそれぞれの入力欄に対して行いたいです。
            //data['Hoge'][配列の番号]['text'] ←配列の番号 を自動で取得できたら解決すると思うのですがやり方がわからず困っています…。
            $text = $this->request->data['Hoge'][1]['text'];

            if ($this->Hoge->updateAll(
                array('Hoge.text' => "'".$text."'")
                ))
            {
                $this->Session->setFlash('保存しました。');
                $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash('保存できませんでした。');
            }
        }
    }
}
?>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

こんな感じでいかがでしょうか。

■View/Hoges/index.ctp

<?php echo $this->Form->create('Hoge'); ?>
<ul>
    <!-- すでに登録してあるレコード情報を表示・更新するエリア -->
    <?php foreach ($hoges as $hoge) :?>
        <li>
            <?php echo $this->Form->input('Hoge.' . $hoge['Hoge']['id'] . '.text', array(
                'type' => 'text',
                'default' => $hoge['Hoge']['text']
                ));
            ?>
        </li>
    <?php endforeach; ?>
    <!-- /すでに登録してあるレコード情報を表示・更新するエリア -->

    <!-- 新しく情報を登録するエリア -->
    <!-- ★悩みポイント1★ -->
    <!-- ここに情報が入力された場合、新規レコードとして登録したいのですが出来ずに困っています…。 -->
        <li>
            <?php echo $this->Form->input('Hoge.0.text');?>
        </li>
    <!-- /新しく情報を登録するエリア -->
</ul>
<?php echo $this->Form->end('保存'); ?>

■Controller/HogesController.php

<?php

class HogesController extends AppController {
    public function index($id=NULL) {
        $this->hoges = $this->Hoge->find('all');
        $this->set('hoges',$this->hoges);

        if ($this->request->is('post')) {

            //★悩みポイント2★
            //下記のように
            //$text = $this->request->data['Hoge'][1]['text'];
            //とすると一番上に入力した値で更新されるのですが、これをそれぞれの入力欄に対して行いたいです。
            //data['Hoge'][配列の番号]['text'] ←配列の番号 を自動で取得できたら解決すると思うのですがやり方がわからず困っています…。

            if (isset($this->request->data['Hoge'])) {
                foreach ($this->request->data['Hoge'] as $id =>$text) {
                    $hoge = array(
                        'text' => $text
                    );
                    if ($id == '0') {
                        $this->Hoge->create();
                    } else {
                        $hoge['id'] => $id;
                    }
                    $result = $this->Hoge->save($hoge, false);
                    if (!is_array($result)) {
                        $this->Session->setFlash('保存できませんでした。');
                        return;
                    }
                }            
                $this->Session->setFlash('保存しました。');
                $this->redirect(array('action' => 'index'));
            }
        }
    }
}
?>

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/12/14 00:54 編集

    ありがとうございます!
    土曜日丸まる費やしても、解決できなかったので非常に助かりました(ToT)

    回答いただいたものそのままだと私の環境ではエラーが出てしまったので、
    下記の通り2箇所変更させていただいたところ、ほぼ期待通りの動きになりました。
    ----
    'text' => $text

    'text' => $text['text']
    ----
    $hoge['id'] => $id;

    $hoge['id'] = $id;
    ----

    ほぼ、というのは、「すでに登録してあるレコード情報」だけを更新したい場合でも、
    「新規レコードに空の値が入っている」と認識されて、textが空のレコードが新たに追加されてしまうためです。

    新規レコードが空の場合は、登録させないようにしたいのですが可能でしょうか?

    Modelの$validate で 'allowEmpty' => false でいけるかな?と思ったのですが、
    送信が行われる前にバリデートが行われてしまうのでこれでは解決できませんでした。
    (※空の場合は、新規レコードを登録しない、という動作にしたいのです)

    Controllerでテキストが入っていた場合のみcreate()させようと思い、
    下記のようにしてみたところ、空の値は登録されなくなりましたが、既存更新をした場合にレコードの一番最後の値が、強制的に空になってしまうという謎挙動になってしまいました…。

    ----
    if ($id == '0') {
      $this->Hoge->create();
    }



    if ($id == '0') {
      if($text['text'] != '') {
        $this->Hoge->create();
      }
    }
    ----

    もし良いお知恵がありましたらアドバイスいただけますと助かります。

    キャンセル

  • 2015/12/14 01:07

    自己レスですみません。
    下記のように、それぞれの中でsetしてあげたらうまくいきました!

    -----
    if ($id == '0') {
      if($text['text'] != "") {
        $this->Hoge->create();
        $result = $this->Hoge->save($hoge, false);
      }  
    } else {  
      $hoge['id'] = $id;//修正したところ2
      $result = $this->Hoge->save($hoge, false);
    }
    -----

    この度は迅速かつ丁寧に回答いただき、本当にありがとうございました!

    キャンセル

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

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