0

私は解決しようとして何時間も費やしてきたが、運がなかったしつこい問題を抱えています。データベースからアイテムを削除するために使用するフォームがあります。ここにフォームがあります: 編集:コードをもう少し合理的なものに更新しましたが、まだ問題があります。

    <div id="tabs-3">
            <p>Select Replenish for Books that will be for sale again.<br/>Select Remove for Books that will NOT be for sale again.</p>
            <br/>
            <table>
            <tr>
                <td><input type="radio" name="returnType" value="replenish" checked>Replenish<br></td>
                <td><input type="radio" name="returnType" value="remove">Remove<br></td>
            </tr>
            <tr>
                <td>&nbsp</th>
                <td>&nbsp</th>
            </tr>
            <tr>
                <th>SKU</th>
                <th>Order ID</th>
                <th>Quantity</th>
                <th>Location</th>
            </tr>
            <?php $numberofrow = 10;?>
<!--create the for loop-->
<?php for($counter = 1;$counter<=$numberofrow;$counter++){ ?>
<!--create 1 row for repeating-->
            <tr>
                <td><input type="text" id="sku<?php echo   $counter;?>"/></td>
                <td><input type="text" id="order<?php echo $counter;?>"/></td>
                <td><input type="text" id="reEnterQty<?php echo $counter;?>"/></td>
                <td>
                    <select id="reEnterLocation<?php echo $counter;?>" name="reEnterLocation" class="Location">
                        <option value="">--Select Location--</option>
                        <?php
                        $query = "SELECT location_id, location FROM location ORDER BY location";
                        $result = $conn->query($query);
                        while ($row = $result->fetch_assoc()) {
                            echo '<option value="' . $row['location_id'] . '" >' . $row['location'] . '</option>';
                        }
                        ?>
                    </select>
                </td>
            </tr>
            <?php }?>
            </table>
            <br/>


            <br/>
            <input type="button" id="reEnterSKU" value="Process Returns" /> <br/>

            <div id="returnsNotice"></div>
        </div>

これを処理する js は次のとおりです。

        $("#reEnterSKU").on('click', function() {

    if($("input[name=returnType]:checked").val() == "remove"){ //executes when Remove radio button is checked
        var arr = {};
        var counter = 0;

        for(var x=1;x<11;x++)
        {
            if($("#sku"+x).val() != "" && $("#order"+x).val() != ""){
            arr[x] ={sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: $("#reEnterQty"+x).val()};   
            }
        }   
                $.ajax({
                    type: "POST",
                    async:false,
                    url: "invReturnsRemove.php",
                    dataType: "json",
                    data: {data: JSON.stringify(arr)},//({sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: quantity}),
                    success: function(data){

                    }
                });



        $("#returnsNotice").html("<h3>" + x + " return(s) removed.</h3>");

invReturnsRemove.php は次のとおりです。

    <?php
require_once ('../db.php');
$conn = db_connect();
$n=0;

$data =json_decode($_POST['data'], true); 

foreach($data as $value){

$conn->query("UPDATE order_sold SET quantity = (quantity - {$data[$n]['quantity']}) WHERE sku = {$data[$n]['sku']} AND order_id = {$data[$n]['order']}");
$n++;}


$conn->close();
?>

問題は、実行しようとすると、削除するレコードが 1 つだけであっても、何百回も実行されることです。私が間違っている可能性があることと、それを修正する方法はありますか?

4

2 に答える 2

3

あなたが行ったコメントは、問題の少なくとも一部がクライアント側にあることを示唆しています。

'click'イベントリスナーを複数回追加した可能性があります。イベントリスナーを追加するコードがループ内にある場合は、ほぼ確実に複数回追加しています。たとえば、ページに複数のフォームがあり、次の方法でリスナーをアタッチしている場合、送信ボタンが押されるたびに複数回トリガーされます。

// THIS IS BAD
$('form').each(function() {
    $("#reEnterSKU").on('click', function(e) {
         // details of listener for form1
    });
    $("#reEnterSKU2").on('click', function(e) {
         // details of listener for form2
    });
    $("#reEnterSKU3").on('click', function(e) {
         // details of listener for form3
    });
});

の に直接関連付けられたイベント リスナを使用しているbuttonためform、おそらくreturn false;イベント リスナ関数から呼び出すか(パラメータをクリック リスナ関数e.preventDefault();に追加する必要があります)、ボタンが を送信しないようにする必要があります。(おそらく、すでにそのようなことをしているが、コードを含めていないのですか?)ページをリダイレクトするつもりはないと思います。そうしないと、要素のコンテンツを更新しません。eform<div id="returnsNotice"></div>

問題を引き起こす可能性のあるもう 1 つのことは、クリック リスナーを検索してボタンに追加するために使用しているセレクターが十分に具体的でない場合です。この場合、一度に複数のボタンにイベント リスナーを追加している可能性があるため、1 つのボタンに複数のイベント リスナーが存在する可能性があります。

enterまた、フォームを操作する場合、ユーザーがキーを押したときなど、さまざまな送信シナリオで状況が複雑になる可能性があるため、送信をトリガーする目的で、ボタンなどの特定のフォーム要素にイベント リスナーをアタッチすることは一般的に避けるのが最善だと思います。テキスト入力フィールドにフォーカスがあります。別の方法として、要素にアタッチされているjQuery.submit()メソッドを使用できます。このメソッドはform、フォームが送信される状況によってトリガーされます。これにより、関数 (送信リスナー) を実行し、自動送信をより確実に停止することができます。requiredこれにより、属性をフォーム要素に適用するときに組み込まれているブラウザーのフォーム検証機能を活用することもできます(詳細互換性)。

$("#your-form-id").submit(function() {

    if($("input[name=returnType]:checked").val() === "remove") { //executes when Remove radio button is checked
        var arr = [];
        var counter = 0;

        for(var x = 1; x < 11; x++)
        {
            if( $("#sku"+x).val() !== "" && $("#order"+x).val() !== ""){
                arr[x] = {
                    sku: $("#sku"+x).val(), 
                    order: $("#order"+x).val(), 
                    quantity: $("#reEnterQty"+x).val()
                };   
            }
        }
        console.log('FORM SUBMIT');

        $.ajax({
            type: "POST",
            async:false,
            url: "invReturnsRemove.php",
            dataType: "json",
            data: {data: JSON.stringify(arr)},//({sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: quantity}),
            success: function(data){
                console.log('SUCCESS'); // how many times do you see this per button click?
            }
        });

        $("#returnsNotice").html("<h3>" + x + " return(s) removed.</h3>");

        // ... anything that remains in your function
        return false;

問題を解決する方法に関して、私が最初に行うことは、フォーム送信ステートメントをコメントアウトして、方程式からそれを取り除くことです. 次に、その場所にconsole.log()ステートメントを追加して、a) 複数回呼び出されるかどうか、b) 複数回呼び出される場合に 1 回だけ実行する方法を見つけようとします。クリック イベント リスナーを追加するときconsole.log()に実行されるステートメントを追加して、クリック イベント リスナーを 1 つだけ追加するようにすることもできます。これらの変更を以下に示します。

console.log('ADDING FORM SUBMISSION click listener -- you should only see this once.');

$("#reEnterSKU").on('click', function(e) {

    e.preventDefault();

    if($("input[name=returnType]:checked").val() === "remove") { //executes when Remove radio button is checked
        var arr = [];
        var counter = 0;

        for(var x = 1; x < 11; x++)
        {
            if( $("#sku"+x).val() !== "" && $("#order"+x).val() !== ""){
                arr[x] = {
                    sku: $("#sku"+x).val(), 
                    order: $("#order"+x).val(), 
                    quantity: $("#reEnterQty"+x).val()
                };   
            }
        }
        console.log('FORM SUBMIT');
        /* 
        $.ajax({
            type: "POST",
            async:false,
            url: "invReturnsRemove.php",
            dataType: "json",
            data: {data: JSON.stringify(arr)},//({sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: quantity}),
            success: function(data){
                console.log('SUCCESS');
            }
        }).fail(function(data) {
            console.log('FAIL');
        });
        */
        $("#returnsNotice").html("<h3>" + x + " return(s) removed.</h3>");

他に気づいたことは、arr変数が実際にはObjectではなく であるということArrayです。それがPHPに影響を与えるかどうかはわかりません。そして、あなたがxの値から開始していることに気付きました1arrこれは、が として作成された場合、最初の要素Arrayがあることも意味します。undefined

また、何counterですか?それに基づいてループしている場合は、注目すべきものになる可能性があります。

トラブルシューティングの中間ステップとして、次のバージョンの JavaScript コードは、ブロックされなかった最新の送信から 1.2 秒以内に行われた送信呼び出しをキャンセルします。これは解決策としてはお勧めしませんが (非常に悲惨です)、問題が存在する場合のトラブルシューティングに役立つ可能性があります。

(function(undefined) { 
    if (window.blockSubmission === undefined) {
        window.blockSubmission = false;
    }
})();

$("#reEnterSKU").on('click', function() {

    // this will make sure your listener only gets called at most once every 1.2 seconds
    if (window.blockSubmission) {
        return false;
    } else {
        window.blockSubmission = true;
        setTimeout(function() { 
            window.blockSubmission = false;
        }, 1200);
    }

    if($("input[name=returnType]:checked").val() == "remove") { //executes when Remove radio button is checked
        var arr = [];
        var counter = 0;

        for(var x = 1; x < 11; x++)
        {
            if( $("#sku"+x).val() != "" && $("#order"+x).val() != ""){
                arr[x] = {
                    sku: $("#sku"+x).val(), 
                    order: $("#order"+x).val(), 
                    quantity: $("#reEnterQty"+x).val()
                };   
            }
        }
        console.log('FORM SUBMIT');

        $.ajax({
            type: "POST",
            async:false,
            url: "invReturnsRemove.php",
            dataType: "json",
            data: {data: JSON.stringify(arr)},//({sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: quantity}),
            success: function(data){
                console.log('SUCCESS'); // how many times do you see this per button click?
            }
        });

        $("#returnsNotice").html("<h3>" + x + " return(s) removed.</h3>");

それでもうまくいかない場合は、質問で少し詳しく説明することをお勧めします。追加のコードを含めると役立ちます。少なくともform要素全体を表示する、PHP / HTML のより長い抜粋かもしれません。また、JavaScript のより包括的な抜粋を含めることも役立つ場合があります。たとえば、投稿で提供された抜粋では、フォーム送信ボタンのクリック イベント リスナーが閉じられることはありません。そのため、実際に何が起こっているのかを確認するのは困難です。

多くの JS を使用する場合は、一読の価値があるかもしれません。少し古くなっていますが、ブラウザ デバッグ ツールの素晴らしい紹介です。

http://jtaby.com/2012/04/23/modern-web-development-part-1.html

于 2012-12-09T06:12:59.573 に答える
2

完全なコンテキストを表示せずに、クリックが重複によってトリガーされていると推測しています。この小さなハックはそれを回避するかもしれません:

var e = false;
$("#reEnterSKU").on('click', function() {
    if (e) return;

    if ($("input[name=returnType]:checked").val() == "remove") { //executes when Remove radio button is checked
        e = true;
        var arr = {};
        var counter = 0;

        for(var x=1;x<11;x++)
        {
            if ($("#sku"+x).val() != "" && $("#order"+x).val() != "") {
                arr[x] ={sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: $("#reEnterQty"+x).val()};   
            }
        }  

        $.ajax({
            type: "POST",
            async:false,
            url: "invReturnsRemove.php",
            dataType: "json",
            data: {data: JSON.stringify(arr)},//({sku: $("#sku"+x).val(), order: $("#order"+x).val(), quantity: quantity}),
            success: function(data) {}
        });

        $("#returnsNotice").html("<h3>" + x + " return(s) removed.</h3>");
        e = false;
    }
});
于 2012-12-07T18:15:16.280 に答える