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

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

ただいまの
回答率

88.34%

form入力でcreateとeditを行う際に同じbladeテンプレートを使い回したい。

解決済

回答 5

投稿 編集

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

退会済みユーザー

Laravelでデータの入力を行うformと編集するformを作っていますが、同じテーブルを扱うので自ずとformのinputの内容が同じになります。なのでformのbladeテンプレート作って入力でも編集でも使える様にしたいです。

しかし、それぞれのパターンで微妙に違いがあるのでそこをどう一つのbladeテンプレート補えばいいのか模索しております。createの際は初期にinputには何もvalueはありませんが、editの際は初期に編集するデータがinputのvalueに入ってます。また、createとeditでformの接続先である、actionの値が違います。そこの違いを考慮して例として以下の様なformのbladeテンプレートを作りました。

<form action="{{$action}}" method="post">
    @csrf
    <input type="text" name="name"
           value="@if(old('name') != null)
           {{old('name')}}
           @elseif(isset($content))
           {{$content['name']}}
           @endif">
    <input type="submit" value="submit">
</form>

上記の$actionはcontorollerから渡された値です。これはこれで十分だとおもいます。

問題はinputのvalueです。create、edit共通でにvalidationで引っかかって修正することがあるのでまずold関数で古い入力した値がないか確認します。あれば、それを表示します。なかった際は編集時で編集前のデータがあるかもしれないのでisset関数でcontorollerから送られたコンテンツのデータがないか確認し、あればセットします。それもなければcreate時と判断して何もセットしません。そんな感じで上記のif文を書きましたが正直長すぎます。input数が増えるたびにあんなif文を書くのはしんどいです。

そこで質問なのですが、この様なパターンってよくあると思うので、なにか方法みたいのが確立されていると思うのですが、調べても出てきません。createとeditで同じformのbladeテンプレートを使い回すスマートな方法があれば教えてください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

+4

ベストかどうかは分かりませんが、私がよく書く方法です。

<input type="text" name="name" value="{{ $errors->has('*') ? old('name'):($content['name'] ?? '')}}">

三項演算子と、「??」を使って簡単に。

ポイントとしては、
validationエラーで戻ってきた場合に、必ずoldを参照する形にしていることです。

これは、「登録済みの項目」を「編集で空にしようとした場合」の話になりますが、
いずれかの項目でバリデーションエラーが発生した場合、old('name')を基準に判断すると、空にした項目に編集前のデータが勝手に補完されてしまうことになるので、それを回避するためです。(なので、補完されていいのであれば、old基準でも問題ないかなと思います)

「??」(Null Coalesce Operatorとかいうものらしい・・)は、{{ $a ?? '' }}と書いた場合に、{{isset($a) ? $a : ''}}と書いたのと同じ結果になります。

最後に、これだけではcreate(新規作成)時に、$contentそのものの定義がないUndefinedのerrorが出てしまうので、create(新規作成)時は、viewに['content'=>false]を渡すようにします。

ご参考までに。。。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

checkベストアンサー

+2

質問を読む限り、

old('name', $content['name']);

で十分な気がする

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/18 18:13

    十分ですね。oldにデォフォルト値をつけられたとはありがとうございます。

    キャンセル

+1

切り分け処理が施された各inputの部分を、Laravel Bladeのコンポーネント機能を使うと、部品としてまとめることが可能です。
Vue.jsを参考に実装されたtSlot機能により、HTMLの断片を呼び出し側から渡せるので、インクルードよりも柔軟性が高いです。
Laravel 5.8 Bladeテンプレート

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/15 16:25

    ありがとうございます。参考にいたします。

    キャンセル

0

@php
    function getValue($name,$data) {
        $value = '';
        $old = old($name);
        if($old != null) {
            $value = $old;
        } elseif(isset($data)) {
            $value = $data[$name];
        }
        return $value;
    }
@endphp

<input type="text" name="name" value="{{getValue('name',$content)}}">


とりあえず上記のメソッドを作ってみました。一応問題なく動いています。一旦はこれでいいかなって感じですが、もし他に何かあればご意見が欲しいです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

-3

Laravelに限ったことではないかと。 
「絶対的に確立されている手順」というのはありません。

あくまで下記を満たせば良いわけで、手段は1つではありません。

  • 同じ入力コントロールである
  • 新規の場合はデフォルト未入力、更新の場合は指定されたデータ
  • 新規の時はinsert、更新の場合はupdateを行う

以上から、
「新規か、更新か」が判別できる情報が何かしら渡されていればいいわけですから。
それさえ出来ていればactionをわける必要はありません。

アクセスのURLを下記のようにすれば
/item/add/add
/item/edit/1
ルーティングすら1つにすることも可能でしょうし。(addの最後のaddは任意パラメータならなくてもいいかもしれない)

それさえ渡せばactinも共通にしてaddならinsert,editなら渡されたパラメータ(IDなど)をWhereに渡してupdateが可能でしょう。

バリデーションを行う場合は必要なパラメータを失わないように工夫する必要がありますし、確認画面を挟む際もそれは同じですね。
「既存情報より入力情報を優先とする作り」にする必要はあります(逆にすると入力した情報で更新されないので)

機能によっては「新規では入力するけど更新では更新不可な項目」もあると思うので、入力コントロールをdisableではなくラベルするなど工夫が必要ですね。

仕様の”決め”と考え方だと思います。
今回質問に提示された内容だけだと単純すぎるので具体的な話にはなりにくいと思います)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/16 21:44

    ご回答ありがとうございます。

    確かにいろんなパターンがあるし上記の質問だと仕様の決めが不十分で答えにくいかもしれませんね。そしていろんなパターンがあるので絶対的とは言わなくても、メジャーな方法とかもないかもですね。一応質問を修正します。

    キャンセル

  • 2019/07/18 15:42

    自己回答確認しましたがbladeに直接関数を書いてしまうとそこしか利用できないので
    やはり「別のルーティングから同じビューを呼び出す」方が良いかと思います。

    キャンセル

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

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

関連した質問

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