5

Stackoverflow の長年の読者。初めてのポスターなので、お手柔らかにお願いします:)

さまざまなタイプ (チェックボックス/テキスト/10 進数/日付など) の約 50 のフィールドで構成されるページにフォームがあります。値は、およそ次のように、1 つのクエリを通じて約 8 つのテーブルから取り込まれます。

SELECT * FROM p
LEFT JOIN pd on p.id=pd.id
LEFT JOIN pc on p.id=pc.id
LEFT JOIN pie on p.id=pie.id
etc.
WHERE p.id = xxx

フォームで単純な POST を使用し、一連の検証クエリと更新クエリを作成し (既存のすべての値をフォームにあるもので上書きする)、それで完了すると考えて一日を始めましたが、自分の判断に疑問を抱いています。ここ。

具体的には、既存の値が変更されていない場合にそれをオーバーライドするのは間違っていると感じます。データベースの更新が途中で失敗した場合にどうなるか少し心配です (トランザクションで処理することを考えています)。私は小さなフォームでこれに慣れていますが、スタッフが 1 つまたは 2 つのフィールドを変更しただけの場合、これは無駄に多くのことを書いているように感じます. 次に考えたのは、フィールドごとのレベルに基づいて AJAX にすることでした。フィールドを変更すると、変更が送信されて保存されます。できればjsを避けたいと思っていても、もっと理にかなっているように感じます。もちろん、3番目のオプションは、複数の送信ボタンを備えた複数のフォームに変換することです。たとえば、タブごとに1つ(フォームはすでにタブに分割されています)、欠点は、より多くの送信が必要なため、ページをより頻繁にリロードすることです(ここではもちろん、AJAX も使用できます)。

私はそれにこれほど多くのことを考えるべきですか? ここには財務データが少し含まれているので、私の主な関心事は信頼性とパフォーマンスですが、他の人が従うベスト プラクティスがあるかどうかも知りたいです。

--- 以下の選択した回答を実装した後に更新 ---

SO の長年の読者である私は、質問者が後でフォローアップするスレッドにいつも感謝しているので、自分でそうしようと思いました。正しいプロトコルまたはフォーマットがわからない。

上記のように、私は基本的にjavascriptを使用して送信時のフォームを元の値と比較し、変更をmysqlに投稿するbarnyrのソリューションに行き着きました(jquery postを使用)。同様のシナリオを検討している場合は、次の点を考慮してください。

  1. すぐに、jquery のシリアル化は、チェックボックス/ラジオの値が選択されていない場合、それらを送信しません。彼らの論理はわかりますが、私にはこれは意味がありません。これを解決するために、 http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/のプラグインを使用しました。

  2. ページで値を編集して保存し、再度編集して元の値に戻すと、ページの読み込み時に設定された初期値と比較して、何も変更されていないというメッセージが表示されます。論理的ですが、すべてが完了してテストが完了するまで、これを考慮していませんでした。単純な「フォーム送信時にすべてをオーバーライドする」よりも、このソリューションに伴う複雑さを維持することを保証するこれを回避する方法は実際には見当たらないため、ユーザーを気にするパブリックアプリケーションを構築している場合は、この方法を使用することをお勧めします。

  3. 正規化に関しては、コンテンツが特定のフィールドに追加されない限り、ユーザー ID を含むメインのテーブルにリンクされたテーブルに行が追加されないようにすることができるため、このソリューションは美しいです。ただし、ポイント 2 が私にとって大きな問題である場合、1 つの大きなフォームに表示されるこれらすべての値を 1 つの大きなテーブルに格納するだけで、コードの複雑さが大幅に軽減されます。私は正規化に関してほとんど初心者です(ピッチフォークで簡単に行ってください)。もちろん、これは主に、すべてのデータが1つの形式で表示される結果です。複数のフォームを使用している場合、これは当てはまりません。

  4. システムの一部には、フォームの他の部分に合計された多くの数値が含まれます。これらすべてを AJAX 経由で行うことは、ユーザーが保存を押したときに正確に何が変化するかを非常に注意深く明確にする必要があることを意味します。たとえば、プログラムの価格を変更でき、合計価格も更新されるはずですが、AJAX 経由で送信していて適切なリロードがないため、これらすべてをシステムにコーディングし直す必要があります。

この場合、ポイント 2、3、および 4 を回避できますが、開始時に今知っていることを知っていれば、すべてのデータを含む 1 つの大きなテーブルを使用し、フォーム送信時に行全体を単純に編集していたでしょう。繰り返しになりますが、私は学ぶことがずっと少なかったので、後悔はありません:)これが後の段階でこのスレッドを見つけた人の助けになることを願っています.

4

4 に答える 4

1

UPDATE - 最初のアプローチでは、他の入力タイプをうまく処理できませんでした。一般的な入力タイプを処理し、初期値に DOM プロパティを使用するようにコードを変更しました。これにより、ページの読み込み時にコードを実行する必要がなくなります。

リンクは次のとおりです: http://jsfiddle.net/rLwca/5/更新された関数は次のとおりです。

    //Initial setup no longer needed. the DOM has the default states anyway...

//heres where we filter the elements for ones which have changed
$("#My50PageForm").submit(function(){        
    var elems = $("#My50PageForm :input").filter(function(value){
        var elem=$(this),
            type=this.tagName +"_"+(elem.attr("type")||""); // uniquely name the element tag and type

        switch (type){
            case "INPUT_radio": case "INPUT_checkbox":                    
                return elem.prop("checked")!=elem.prop("defaultChecked");
            case "INPUT_text": case "INPUT_textarea": case "INPUT_":                 
                return elem.val()!=elem.prop("defaultValue");
            case "SELECT_":
                var options=$(this).find('option'),
                    defaultValue=options.first().val(); //use the first element's value as default in case no defaults are set
                options.each(function (i,o) {
                    defaultValue=this.defaultSelected?this.value:defaultValue;
                });
                return $(this).val()!=defaultValue;

            default:
                console.log("type "+type+" not handled");
                return false;
        }
     });

    if(elems.length){
        console.log(elems.serialize());
        return false;
        $.post("http://jsfiddle.net/example.cfm",
               elems.serialize());
    }else{
       alert("nothing changed");   
    }         

    return false;
});

以下の元のコード:

変更内容を送信する最小限の例へのリンクを次に示します。

http://jsfiddle.net/UhGQX/

$(document).ready(function(){
//Copy all form valued into a data attribute called 'original' when the page loads
$("#My50PageForm :input").each(function(elem){
    $(this).data("original",$(this).val());
});

//here's where you check what has changed
$("#My50PageForm").submit(function(){        

    var elems = $("#My50PageForm :input").filter(function(value){
        var elem=$(this),
        original=elem.data("original");
        console.log(original);
        //check that original isn't 'undefined' and that it's been changed
        return original && elem.val()!==original
    });
    if(elems.length){
        //post the data back to your server for processing
        $.post("http://jsfiddle.net/example.cfm",
               elems.serialize());
    }else{
     alert("nothing changed");   
    }         

    return false;
});
});

キービットは次のとおりです。

  • ページが読み込まれたら、jQuery を使用して各フォーム フィールドの初期値のコピーを作成します。
  • 送信が開始されたときに、各フィールドの現在の値を、ページが読み込まれたときに保存された値と比較します。
  • 変更がある場合は、データをサーバーに戻します。

他のアプローチとして、フォーム全体を投稿できるようにすることもできます。

  • セッション中のサーバーにデータを保存する
  • ページの入力に使用した選択を再実行し、それをフォームによって投稿されたものと比較します
于 2013-04-26T15:20:01.493 に答える
1

クライアントの onChange または onBlur イベントに基づくデータベースへの書き込みは避けます。コーディングは簡単ですが、ユーザーがそのフィールドの適切な値を実際に決定したという前提に基づいています。それは危険な仮定です。校正する人もいます。途中でフォームを放棄する人もいます。また、フォーム フィールドが選択の場合、onChange イベントが発生する前に発生することがあります。

また、barnyr が提案するように、セッション スコープにデータを保存することも避けます。ユーザーが新しいブラウザー タブを開いてセッション変数を不注意に変更してしまったことに、私たちは悩まされてきました。

私がよくとるアプローチは、フォーム フィールドのクエリ オブジェクトを作成し、QofQ を使用して何かを更新する必要があるかどうかを判断することです。簡単な例を次に示します。

<cfscript>
RecordsToUpdate = QueryNew("a");
FormValues = QueryNew("id,name","integer,varchar");
Delim = Chr(30);
</cfscript>

<cfloop list="#form.fieldnames#" index="ThisElement">
<cfset ThisValue = form[ThisElement]>
<cfif left(ThisElement, 12) is "NewCategory_">
 not relevent here
<cfelse>
<cfscript>
ThisId = RemoveChars(ThisElement,1,17);
AddNewRow(FormValues,"id#Delim#name", "#ThisID##Delim##ThisValue#", Delim);
// AddNewRow is a udf
</cfscript>
</cfif>
</cfloop>

<cfquery name="RecordsToUpdate" dbtype="query">
select FormValues.*
from FormValues, GetCategories
where id = CategoryId
and name <> CategoryName
</cfquery>

<cfloop query="RecordsToUpdate">
update query
</cfloop>

ところで、Chr(30) の使用は、ここの Stack Overflow で Adam Cameron から学んだことです。

于 2013-04-26T18:37:15.480 に答える