PHP5とSmartyによる処理分岐アイデアの質問です。

http://q.hatena.ne.jp/1174771937の続きなのですが、複数テーブルから多次元配列を作成しフラグを立て、Smartyテンプレートでデータをforeachでループ出力しています。
その際、フラグのif判断で以下のように処理させて表示していました。


{foreach item=item from=$shop_cat_merge}
<strong>{$item.shop_cat_name}</strong>{$item.shop_sub_cat_name}
<div id="cat_info">
{if $item.shop_cat_flag == "1"}
<a href="{$url_shop}?type=wakeschool_modify&action=form&shopid={$shop_id}">更新</a>&nbsp;
<a href="{$url_shop}?type=wakeschool_delete&action=confirm&shopid={$shop_id}&catid={$item.shop_cat_id}&subcatid={$item.shop_sub_cat_id}">削除</a>
{else}
このカテゴリは未登録です。<a href="{$url_shop}?type=wakeschool_regist&shopid={$shop_id}&catid={$item.shop_cat_id}&subcatid={$item.shop_sub_cat_id}">登録</a>しますか?
{/if}<br />
</div>
{/foreach}


メンバーはメンバー専用画面で複数のショップを登録でき、そのショップはshop_idで管理され、ショップひとつに対し上記処理を行わせようとしています。
GET取得だと他人のデータをいじれてしまうので、POST取得に変えようとしていますがここでつまずいています・・・。
500文字に収まらないので、下のコメントに続きがあります。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2007/04/08 22:48:46
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答1件)

id:nandedarou No.1

回答回数230ベストアンサー獲得回数34

ポイント60pt

●方法1

それぞれのボタンのformタグを独立させるという方法。つまり、ボタンの数だけ、formがあるということ。


●方法2

ラジオボタンやリストボックスでユーザーに選択させる方法。


●方法3

JavaScriptを使う方法(※ユーザーがJavaScriptを有効にしてない場合や、そもそもJavaScriptが動作しないブラウザを使用している場合、機能しなくなります。)


一応、簡単に方法3を解説します。(JavaScriptを学んでない場合は意味が分からないかも知れません。)


foreachでループする際、formタグのname属性にそれぞれのフォーむ固有の名前をつけます。例えば、

<form name="Form{$item.shop_cat_id}-{$item.shop_sub_cat_id}" action="{$PHP_SELF}" method="post">


JavaScriptで、それぞれのボタンのinputタグのtype属性を"button"とし、そのインプットタグのonClickイベントで、別途JavaScriptで書いた関数(←例えば、PostValue関数)を呼び出します。呼び出す際に、2つの引数(フォームとボタンの種類)を渡します。

<input type="button" value="更新" onClick="PostValue(Form{$item.shop_cat_id}-{$item.shop_sub_cat_id},'modify')">


その関数で、クリックされたボタンの種類に応じて、受け取ったformの中のtypeとactionのvalueに値を設定し、そのフォームをsubmitします。


なお、私の経験からいうと、INPUTタグにname="action"があると、formタグのaction属性と区別がつかなくなり、JavaScriptが誤動作することがあります。JavaScriptを使うならば、nameに"action"は使わない方がいいです。

id:seadwell

なるほど・・・

PHP処理で悩んだら、HTMLの持つ機能やJavaScriptなど別な手段を考える。

なんもかんもPHPで考えていました。またひとつ学びました。


JavaScriptはあまり使ったことがありませんが、何回か実装したことがあるので少々わかります。

(3)の方法を今から試してみます。

> INPUTタグにname="action"があると、formタグのaction属性と区別がつかなくなり、JavaScriptが誤動作する・・・

他のフォームで思いっきり使ってました^^;

こういう忠告は非常にありがたいです。

早速、全てのactionという変数名を変えます。

毎度毎度ありがとうございます。

2007/04/04 00:32:49
  • id:seadwell
    {foreach item=item from=$shop_cat_merge}
    <form action="{$PHP_SELF}" method="post">
    <strong>{$item.shop_cat_name}</strong>{$item.shop_sub_cat_name}
    <div id="cat_info">
    {if $item.shop_cat_flag == "1"}
    {$form.submit3.html}&nbsp;{$form.submit2.html}
    {else}
    このカテゴリは未登録です。登録しますか?<br />
    {$form.submit1.html}
    {/if}<br />
    </div>
    <INPUT type="hidden" name="type" value="{$type}">
    <INPUT type="hidden" name="action" value="{$action}">
    <INPUT type="hidden" name="shop_id" value="{$item.storyid}">
    <INPUT type="hidden" name="shop_cat_id" value="{$item.shop_cat_id}">
    <INPUT type="hidden" name="shop_subcat_id" value="{$item.shop_sub_cat_id}">
    </form>
    {/foreach}

    上記のようなことをやらせたいのですが、送信ボタンが3つあるので$typeと$actionの値をうまく持ってくる方法がわかりません。
    ifのtrueのsubmit3とsubmit2は更新ボタンと削除ボタンです。
    例えば、$typeを$type1、$type2、$type3に分けてしまえば早いのですが、そうするとPHPのメイン処理でswitchによるtype判断で処理分岐させているほかのルーチンに影響が及んできます。

    Smartyテンプレート内で一時変数に退避させるようなことはできないのでしょうか?
    もしあったとしても、ifのtrueの場合、2つボタンがありますし・・・
    何かいいアイデアはないでしょうか?よろしくお願いします。
  • id:seadwell
    なんか、勘違いしているかもしれません・・・。
    URLに付加されたものを取得する方法がGETであって、form出力されたものを取得する方法がPOSTだと思っています。
    form出力の場合submitボタンでなければならない・・・とも思っています。
    例題がそれしか見たことがないもので・・・。
    これが勘違いですと、質問の意味がよくわからないですね。

    質問を簡単にまとめますと、URLに$shop_idなどを付加しないで、次の画面に$shop_idなどのデータを渡したいのです。
    その際、$typeや$actionの値は選択するボタンやリンクによって変化しますので、一時変数に退避するなどで結果的に$typeや$actionに収まれば問題ありません。

    独学なので学習の順番がメチャメチャで、基本的なところを理解しておらずプログラムを書いていることが多々あります。
    よろしくお願いします。
  • id:nandedarou
    >"type"もtype属性と区別できなくなる可能性があります。
    と先ほどコメントしましたが、よく考えてみると、formタグの中にtype属性はないので、問題になることは無いかも知れません。
  • id:seadwell
    やはり、JavaScriptは短時間で応用するにはハードルが高かったです。
    ラジオボタンとJavaScriptを合わせ使う方法を、いろいろ試しましたが未だ動きません。
    前、使ったのはサンプルを少しアレンジした継ぎハギで、理解して書いたわけではないのでした。

    (2)のラジオボタンを使う方法で応急的に仮のコードです。

    {foreach item=item from=$shop_cat_merge}
    <form name="Form{$item.shop_cat_id}-{$item.shop_subcat_id}"action="{$PHP_SELF}" method="post">
    <div id="main_cat"><strong>{$item.shop_cat_name}{$item.shop_subcat_name}</strong></div>
    <div id="cat_info">
    {if $item.shop_cat_flag == "1"}
    このカテゴリは登録されています。<br />
    登録情報の更新
    <input type="radio" name="type" value="{$item.shop_cat_trigger}{$item.shop_subcat_trigger}_modify" checked />&nbsp;
    削除
    <input type="radio" name="type" value="{$item.shop_cat_trigger}{$item.shop_subcat_trigger}_delete" />&nbsp;&nbsp;&nbsp;
    <input type="submit" value="送信" />
    {else}
    このカテゴリは未登録です。<br />
    <input type="submit" value="登録" />
    <input type="hidden" name="type" value="{$item.shop_cat_trigger}{$item.shop_subcat_trigger}_regist" />
    {/if}<br />
    </div>

    <input type="hidden" name="shop_id" value="{$shop_id}" />
    <input type="hidden" name="shop_cat_id" value="{$item.shop_cat_id}" />
    <input type="hidden" name="shop_subcat_id" value="{$item.shop_subcat_id}" />

    </form>
    {/foreach}

    しかし、$type(現在はあまりに箇所が多いので、そのうちに$i_triggerに変更予定)の値取得も幼稚でやりたくなかったのですが、
    DBのカテゴリTBやサブカテゴリTBにフィールド(shop_cat_trigger、shop_subcat_trigger)を追加し、処理分岐用のフラグを格納しました。
    本来必要でないフィールドを持つのはカッコ悪く、プログラムで書きたかったです。
    まだ、元$action(現$ignition)の値が取れていないので、削除画面の処理分岐が出来ず、削除が出来ずにいます^^;
    ifのtrueを書き換え、削除はさせませんww

    この画面は疲れたので後回しにし、いずれ、ちゃんとJavaScriptを試し、TBの余計なフィールドは使わずに書きたいと思います。
    考え方を学べたので大助かりです。いろいろご指導ありがとうございました。
  • id:nandedarou
    もし、分かってないと、WEBプログラムを作成することが非常に困難になりますので、念の為、超基本を書きます。

    (1)PHPやSmartyは、サーバ側で実行されます。

    (2)HTMLやJavaScriptは、クライアント(←インターネットエクスプローラ等のブラウザー)側で実行されます。

    ※よって、(1)と(2)は、実行されるタイミングが異なります。

    (3)PHPでWEBプログラムを作るということは、クライアント側で動くHTMLやJavaScriptを人間が書くのではなく、PHPに書かせるということです。

    ※上記3点、たぶん分かってますよね?
  • id:nandedarou
    今回の画面で、PHPが最低限受け取らなければいけない値は、
    (1)どのボタンが押されたか特定できる情報
    (2)現在の状態
    の2つだけです。

    (1)の情報は、今回で言えば<input type="radio" …>に書き込みます。
    (2)の情報は、<input type="hidden"…>などフォーム内の他のタグに書き込みます。

    上記、二つの情報を受け取れば、ifやswitchで分岐してサーバ側(PHP)で次に何をやるのかを判断できます。

    seadwellさんの最初に提示されたプログラムでは、どのボタンが押されたか(type)と次に何をするか(action)という二つの情報をクライアント側から受け取ろうとしているから難しくなっています。次に何をするかは、サーバ側(PHP)で判断させることもできますので、actionを無理やり渡す必要はないのではないですか?
  • id:seadwell
    コメント返信ありがとうございます。
    いろいろ気に掛けてくださってありがとうございます。

    > 上記3点、たぶん分かってますよね?
    (1)(2)(3)ともに承知しています。
    あまりにも、変なコードをコメント掲載させてしまったのと、コメントを含めた全体の書き込みの流れから『この辺は理解しているんだろうか?』とお思いになるのも当然と思います


    > GETで可能な処理をPOSTにしてるだけですよね?取得すべき情報どちらも同じはずです。「本来必要でないフィールドを持つ」必要はないと思います。」
    まったくそのとおりです。
    今回、お教えいただいた、(2)と(3)を使い((3)だけでなく(2)も併用したのは見た目にカッコいいと思ったからです。)、ラジオボタンや新規登録ボタンのonClickで渡された引数を元に、JavaScriptで$typeと元$action(現$ignition)の値を得て、JavaScriptによるsubmitを試みましたがなかなかうまくいかず、質問が締め切られるとのメールを受け、急いで状況を報告しなければと思い、また、この画面にかかりっきりなので少し疲れたということもあり、変なコメントを残してしまいました。
    参考にしたサイト:http://www.openspc2.org/reibun/javascript/など・・・
    外部ファイルで試しましたが、例えば、簡単なhttp://www.openspc2.org/reibun/javascript/form/001/index.htmlのsubmitだけを試そうと、仮にテスト環境を作りテストしましたがうまくいきませんでした。
    すごーく簡単なhttp://www.openspc2.org/reibun/javascript/form_button/001/index.htmlは正常動作したことから、パス?ディレクトリ構成?(パスというのかしら)は間違ってないと思います。


    > どのボタンが押されたか(type)と次に何をするか(action)という二つの情報をクライアント側から受け取ろうとしているから難しくなっています。次に何をするかは、サーバ側(PHP)で判断させることもできますので、actionを無理やり渡す必要はないのではないですか?
    まさに、そこが問題で根本的な仕様がおかしいのかもしれません。
    もし時間があるなら、一連の流れが解る一部ルーチンを掲載しておきます。長くなっていますがよろしかったらお目を通してください。
    http://www.boardholic.net/sample.html
    http://www.boardholic.netが作ろうとしているサイトですが、メンバー登録を行わないと、ショップ登録画面まで行くことができません。


    あまりに、同じところを質問しているので、気に掛けてくださるnandedarouさんに少し申し訳なく、強引に結果報告をしたのがかえってお手数をとらせる結果となってしまいましたm(_ _)m
  • id:nandedarou
    もうちょっと、本質的な部分がわかりました。

    seadwellさんは、$typeを画面単位で切り替えています。この考え方は、いいと思います。

    しかし、「次の画面」の単位であるところが問題です。その為、ボタンによって変わる変数が、2つになってしまっています。(次の画面の情報とどのボタンが押されたのかと言う情報の2つ)

    私だったら、「現在の画面」の単位で$typeを切り替えます。現在の画面というのは、フォームが表示されている画面(言い換えると、ボタンが表示されている画面)です。こうすれば、同じ画面上では、全て$typeの値は一緒です。

    ※もちろん、ぜんぜん違う処理に移行する場合などは例外はあります。
    ※私は実際、複数画面単位で切り替えています。

  • id:nandedarou
    現在のまま変更しない場合でも大丈夫なようにJavaScriptの例を以下に書きますので、参考にして下さい。

    (IEで動作確認しましたが、それ以外のブラウザで動作するかは未確認です。私はブラウザによりJavaScriptに癖がある為、どうしてもそれでしか実現できないこと以外は、JavaScriptでは書かない方ががいいと思っています。)

    ※回答に書いた例に間違いがありました。formタグのname属性にマイナスマークがあると動作しませんでした。もしかして、seadwellさんがうまくいかなかったのは、このせいかも知れません。大変申し訳ありませんでした。

    <html>
    <head>
    <title></title>
    <script language='JavaScript'>
    <!--//

    function PostValue( Form, button_value ){
    switch(button_value){
    case "変更":
    type = "wakeschool_modify";
    ignition = "form";
    break;
    case "削除":
    type = "wakeschool_delete";
    ignition = "confirm";
    break;
    case "登録":
    type = "wakeschool_regist";
    ignition = "";
    break;
    }

    Form.type.value = type;
    Form.ignition.value = ignition;
    Form.submit();
    }

    //-->
    </script>
    </head>
    <body>
    <form name="Form{$item.shop_cat_id}_{$item.shop_sub_cat_id}" action="{$PHP_SELF}" method="post" >
    <INPUT type="button" value="変更" onClick="PostValue(Form{$item.shop_cat_id}_{$item.shop_sub_cat_id},this.value)">
    <INPUT type="button" value="削除" onClick="PostValue(Form{$item.shop_cat_id}_{$item.shop_sub_cat_id},this.value)">
    <INPUT type="button" value="登録" onClick="PostValue(Form{$item.shop_cat_id}_{$item.shop_sub_cat_id},this.value)">
    <INPUT type="hidden" name="type" value="">
    <INPUT type="hidden" name="ignition" value="">
    <INPUT type="hidden" name="shop_id" value="{$item.storyid}">
    <INPUT type="hidden" name="shop_cat_id" value="{$item.shop_cat_id}">
    <INPUT type="hidden" name="shop_subcat_id" value="{$item.shop_sub_cat_id}">
    </form>
    </body>
    </html>

    ちょっと説明
    最初の3つのINPUTタグの最後の方にthis.valueとあります。
    ジャバスクリプトが当該タグのvalue属性値を代入します。つまり、順に、'変更','削除,'登録'という値になります。
    (最初に書いた解答では、'modify'としていた部分です。)
  • id:seadwell
    わざわざ、だらだらと長いサンプルに目を通していただき、返信ありがとうございました。
    サンプルもあとから見直せば少し説明不足も見えますが、推測していただきnandedarouさんの洞察に感謝です。


    > formタグのname属性にマイナスマークがあると動作しませんでした。・・・大変申し訳ありませんでした。
    とんでもございません。私が無知なだけです。気付けばいいだけですから・・・。


    nandedarouさんのJavaScriptは無事動作確認いたしました。
    このままでは、御礼ができませんし、
    > 私だったら、「現在の画面」の単位で$typeを切り替えます。現在の画面というのは、フォームが表示されている画面(言い換えると、ボタンが表示されている画面)です。こうすれば、同じ画面上では、全て$typeの値は一緒です。
    の部分が今一の飲み込めませんので新たに質問を設けました。

    同じところで何度も何度もお手数をおかけします。
    http://q.hatena.ne.jp/1176190436

    今回ややこしくなったのは、仕様が間違っているからだと思います。
    また、
    > 私はブラウザによりJavaScriptに癖がある為、どうしてもそれでしか実現できないこと以外は、JavaScriptでは書かない方ががいいと思っています。
    にあるように、今後、Webサイトを設計する上で非常に重要なことだと思いますので、お時間があるときにでも次の質問に目を通してみてください。

    可能なら今回の仕様変更もトライしてみたいと思っています。
  • id:nandedarou
    新しい質問のコメントに書いたとおり、私の勘違いがありました。

    やりにくさを仕様のせいにしてしまいましたが、仕様のせいではなく、ラジオボタンによる分岐を選択した為でした。(もちろん、ラジオボタンとJavaScriptを組み合わせれば、可能です。)

    現在の仕様のままでも、私の回答の(1)のやり方でやれば、まったく問題なくできます。
  • id:seadwell
    承知いたしました^^
    例を提示されると、な~んも知らん癖一番ハードルの高そうなことにすぐ挑戦したがるんですよね^^;
    $typeや$actionの2つの変数による処理分岐も、市販の参考書に例題が載っていたので、『参考書に載っているくらいなら真似しても間違いはなかろう・・・。』との安易な考えで採用しました。
    その結果があれです^^;

    今回教えていただいたとおり、(1)もしくは(2)にJavaScriptを絡めた処理で問題の画面を完成させます。
    いいかげん、この画面に関する質問は終わりにします。
    最初から最後まで、何から何まで、本当にありがとうございました。

    新しい質問は、nandedarouさんに少ないポイントですが、お礼を差し上げるためだけの質問なのでキャンセルいたします。
  • id:nandedarou
    お気持ちはしっかりと受け取りました。有難うございます。

    >とんでもございません。私が無知なだけです。気付けばいいだけですから・・・。
    やはり、上手くいかず、疲れてしまった原因はあのマイナスでしたか…。大変、申し訳有りませんでした。

    >ハードルの高そうなことにすぐ挑戦
    実験的にいろいろやっておけば、いざというときに選択肢が増えますから、それでもいいと思います。

    >JavaScriptを絡めた処理で問題の画面を完成させます。
    全てのinputタグのvalueの値をJavaScriptで設定するなんてこともできますよね。そうすれば、formは一つだけで済みます。(この場合、PostValue関数の引数としてFormを受け取る必要がなくなりますが、他の引数が増えます。)

    それでは、頑張って下さい!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません