Array of confusion


#1

Hi,
I am submitting an ajax request to a php script. The values submitted in the string are:

product_category=Kitchen+Equipment&brand_name=Brabantia&brand_name=Kenwood

I put them int an array like this

$post = file_get_contents( 'php://input' );
  
$filterOptions = explode( '&', $post);
 
$filters = array();

foreach( $filterOptions as $k => $v ) 
{
$data = explode("=", $v);
   
      array_push( $filters, $data );

}

That gives an an array like this:

dumping filters—

array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(16) "product_category"
    [1]=>
    string(17) "Kitchen+Equipment"
  }
  [1]=>
  array(2) {
    [0]=>
    string(10) "brand_name"
    [1]=>
    string(9) "Brabantia"
  }
  [2]=>
  array(2) {
    [0]=>
    string(10) "brand_name"
    [1]=>
    string(7) "Kenwood"
  }
}

Trouble is:

I need to access the values (Kenwood, Brabantia and others) using the category (brand_name) to put them in a list for use in my Db query where clause but $filters[‘brand_name’]; doesn’t get me them. I also need to get a range of items using the param $filters[‘product_category’]; with in this scenario, the category being ‘Kitchen Equipment’.

my Db query where clause is like this: (though it can be changed)

if ( in_array( "brand_name", $filters ) ) 
{
$where .= ' rpc.brand in ' . "('" . implode( "','" , $brands ) . "')";
}

Should I restructure the array and if so, in what way

or

am I calling the data from the array incorrectly?

Bazz


#2

It’s certainly unconventional to post data from javascript that way. Could you show the corresponding javascript code please?


#3

HI, thanks for responding.

Here’s the page code sending the ajax request.
(You’ll notice a standard html form, which I used to see the output of the processing script because I can’t seem to access the goings-on of that code using just the ajax code).

I need to see how the data is being submitted from the filters div.


    <h1>Filters table</h1>
 
   


<div id="filter" style='width:300px;float:left'>

  <h2>Filter options</h2>
  <div class='menu_divs'>
    <input type="checkbox" name="product_category" id="product_category" value="Kitchen Equipment"/>
    <label for="Kitchen Equipment">Kitchen Equipment</label>
  </div>
  <div class='menu_divs'>
    <input type="checkbox" name="product_category" id="product_category" value="Shoes"/>
    <label for="Shoes">Shoes</label>
  </div>


  <div class='menu_divs'>
    <input type="checkbox" name="brand_name" id="brand_name" value="Kenwood" />
    <label for="Kenwood">Kenwood</label>
  </div>
  <div class='menu_divs'>
    <input type="checkbox" name="brand_name" id="brand_name" value="Oxo">
    <label for="Oxo">Oxo</label>
  </div>
 <div class='menu_divs'>
    <input type="checkbox" name="brand_name" id="brand_name" value="Brabantia">
    <label for="Brabantia">Brabantia</label>
  </div>
 <div class='menu_divs'>
    <input type="checkbox" name="brand_name" id="brand_name" value="Gaby">
    <label for="Gaby">Gaby</label>
  </div>
 <div class='menu_divs'>
    <input type="checkbox" name="brand_name" id="brand_name">
    <label for="Felicity Fox">Felicity Fox</label>
  </div>
  <div class='menu_divs'>
    <input type="checkbox" id="1.7">
    <label for="1.7">1.7</label>
  </div>
  <div class='menu_divs'>
    <input type="checkbox" id="stainless steel">
    <label for="stainless steel">Stainless Steel</label>
  </div>
</div>

 <div>


 <form method='POST' action = '/php-queries/product-catalogue-query.php' >
    <input type='checkbox' id="brand_name" name="brand_name" value="@filterOpts" />
    <input type="checkbox" id="product_category" name="product_category" value='Kitchen Equipment'>
    <label for="Kitchen Equipment">Kitchen Equipment</label>
    <input type="checkbox" id="brand_name" name="brand_name" value='Brabantia'>
    <label for="Brabantia">Brabantia</label>
    <input type="checkbox" id="brand_name" name="brand_name" value='Kenwood'>
    <label for="Kenwood">Kenwood</label>
<input type='submit' value='submit'>
</form> 
</div> 

 <table id="product_catalogue">
      <thead>
        <tr>
          <th width="15">ID</th>
          <th>Brand</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>


  <div id="debug"></div>
    <script src="http://code.jquery.com/jquery-latest.js"></script> 
    <script>

    debug = true;
    function handleDebug(debugInfo)
    {
    \$("#debug").html("<pre>" + debugInfo + "</pre>");
    }


    function makeTable(data)
    {
    var tbl_body = "";



        \$.each(data, function(k, v) 
        {
        var tbl_row = "",
        currRecord = this;


            if(k==="debug")
            {

                if(debug === true)
                {
                handleDebug(v);
                }
            return;
            }


            \$.each(this, function(k , v) 
            {
                
                if( k==='brand' )
                {
                v = "<a href='content.php?id=" + currRecord['id'] +"'>" + v + "</a>";
                }
                else if ( k==='size' )
                {
                v = "<span class='price'>" + v + "</span>";
                }
                else
                {
                v= "<span class='something_else'>" + v + "</span>";
                }

            tbl_row += "<td>"+v+"</td>";
            })

            tbl_body += "<tr>"+tbl_row+"</tr>";
        })

    return tbl_body;
    }
 



    function getCatalogueFilterOptions()
    {
    var opts = [];
   

        \$checkboxes.each(function()
        {
            if(this.checked)
            {
            opts = {
             id:value
            };
            //opts.push(this.id:value);
            }
        });
 
    return opts;
    }
 


    function updateCatalogue(opts)
    {
    var obj = \$.extend({}, opts); /* convert your array to an object */

        \$.ajax(
        {
        type: "POST",
        url: "/php-queries/product-catalogue-query.php",
        dataType : 'json',
        cache: false,
        //data: {filterOpts: opts},
        data: \$('#filter').serializeArray() + '&' + \$.param(obj), /* merge your form with the new obj (your array) */
          success: function(records)
          {
          //alert('SUCCESS!');
          \$('#product_catalogue tbody').html(makeTable(records));
          }
        });
    }
    

  
    function subsidyIsValid()
    {
    var amount1 = \$("#amount1").val(),
    amount2 = \$("#amount2").val(),
    regex = /^\\d+\$/,
    inputValid = false;

        if(regex.test(amount1) && regex.test(amount2))
        {
        var newTotal = Number(amount1) + Number(amount2)
        
        \$("#total").text(newTotal);
        inputValid = true;
        }

    return inputValid
    }





    function updatePrices()
    {
    var subsidyTotal = Number(\$("#total").text());

        \$(".price").each(function()
        {
        var origVal = Number(\$(this).text())
        \$(this).text(origVal - subsidyTotal)
        })
    }



//# this seems to be where the data is pushed to the catalogue output
//# we need to get the data for pushing to the nav menu 

    var \$checkboxes = \$("input:checkbox");
    \$checkboxes.on("change", function()
    {
    var opts = getCatalogueFilterOptions();
    updateCatalogue(opts);
    });
    

// end //




  
    \$("#apply").on("click", function()
    {
    
         if(subsidyIsValid())
         {
         \$(this).prop("disabled", true);
         \$(this).next().prop("disabled", false);
         updatePrices();
         }
         else 
         {
         alert("Subsidy invalid!")
         }
    });




    \$("#remove").on("click", function()
    {
    \$("#amount1").val("");
    \$("#amount2").val("");
    \$("#total").text("0");
    \$(this).prop("disabled", true);
    \$(this).prev().prop("disabled", false);
    \$checkboxes.trigger("change");
    });



    \$checkboxes.trigger("change");
    updatePrices();
    </script> 
);

#4

I would ditch the datatype JSON, put all fields inside the form, and then use $(form).serialize();, where form is a correct selector for the form.

Also, IDs in HTML must be unique, you can’t have multiple elements with the same ID.


#5

Thanks.
If I get rid of json, what should the data type be?
And I don’t understand what you meant with the comment ‘where form is a correct selector for the form’.

In case it may affect your answers; I will be making this form submit with each selection made and not by using a submit button. I need the params submitted to be categorised eg product_category=Kitchen Equipment&brand=Kenwood so I can more easily apply the correct where clauses. i.e, if no make is checked, it should show all makes and if no (clothing), size is checked, all sizes should show. Likewise with all params.

Thanks again.

Bazz


#6

Nothing, just let it use the default (which is regular form post).

If your form has an id myform use $('#myform'), or if it has class filterform, use $('.filterform'), etc. I dislike giving absolute answers that contain jQuery selectors because people may think I’m using some magic value. So I leave it out and let you figure it out yourself.


#7

Also, do you allow checking multiple brands at the same time? If so, you can’t give all checkboxes the same name, as PHP will only see the last one. What you should do instead is give them the name brand_name[], which makes PHP parse the data as an array which can have multiple brands.


#8

Thank you rpkamp.

I eventually got the form working as I need. I uniquified the id for each form field using the structure “$category_$value” and then I split the strings and process it all in my php script. It enables the selection of multiple brands/sizes/colours etc

Thanks again for your assistance.
Bazz


#9

Could you post the final code please?


#10

the Js…

<div id="debug"></div>
    <script src="https://code.jquery.com/jquery-latest.js"></script> 
    <script>

    //debug = true;
    //function handleDebug(debugInfo)
    //{
    //\$("#debug").html("<pre>" + debugInfo + "</pre>");
    //}


    function makeTable(data)
    {
    var tbl_body = "";



        \$.each(data, function(k, v) 
        {
        var row = "",
        currRecord = this;


            if(k==="debug")
            {
           
                if(debug === true)
                {
                handleDebug(v);
                }
            return;
            }


            \$.each(this, function(k , v) 
            {
                
                
                if( k==='brand_name' )
                {

                /* trim the product name to be just 'length' characters */
                var string = currRecord['product_name'];
                var length = 25;
                var trimmedString = (string.substring(0, length));



                v =  "<table><tr><td class='product_image'>"
                     + "<a href='/cgi-bin/catalogue_detail/" 
                     + currRecord['stock_data_id'] 
                     + "/"
                     + currRecord['product_name'] 
                     + "'>"
                     + "<img class='galleryThumbnail' src='/cgi-bin/mask.pl?client=" 
                     + currRecord['business_id'] 
                     + "&size=small-size&img=" 
                     + currRecord['image_name'] 
                     + "' rel='lightbox[" 
                     + currRecord['product_id'] 
                     + "]' title='" 
                     + currRecord['product_name'] 
                     + " - "
                     + currRecord['colour']
                     + "' /></a>"
                     + "</td></tr><tr><td>"
                     + "<h2>"
                     + "<a href='/cgi-bin/catalogue_detail/" 
                     + currRecord['stock_data_id'] 
                     + "/"
                     + currRecord['product_name'] 
                     + "'>" 
                     + v 
                     + "</a></h2></td></tr><tr><td class='price'>"
                     + "<div class='price_data'>"
                     + "<p>" + trimmedString + "</p>"
         
                     + "<p>" + currRecord['colour'] + "</p>"
                     + "<p>"  + currRecord['stock_availability'] + "</p>"
                     + "<p>"  + currRecord['currency_symbol_left'] + "&nbsp;" + currRecord['price'] + "</p>"
                     + "</div></td></tr></table>";
                row += ""+v+ "";
                }
                else if ( k === 'size' )
                {
                //v = "<div>" + v + "</div>";  
                row += "<p>"+v+"</p>";
                }
                else
                {
                //v = "<div style='width:100%'>" + v + "</div>";
                }

         
            })

            tbl_body += "<div class='image_tab'>"+row+"</div>";
        })

    return tbl_body;
    }
 
 



    function getCatalogueFilterOptions()
    {
    var opts = [];
   

        \$checkboxes.each(function()
        {
            if(this.checked)
            {
            opts.push(this.id);
            }
        });
 
    return opts;
    }
 


    function updateCatalogue(opts)
    {
    //var obj = \$.extend({}, opts); /* convert your array to an object */

        \$.ajax(
        {
        type: "POST",
        url: "/php-queries/product-catalogue-query.php",
        
        dataType : 'json',
        cache: false,
        data: {filterOpts: opts},
          success: function(records)
          {
          //alert('SUCCESS!');
          // alert(records);
          \$('#shopping_index').html(makeTable(records));
          }


         

        });
    }
    

  
    function subsidyIsValid()
    {
    var amount1 = \$("#amount1").val(),
    amount2 = \$("#amount2").val(),
    regex = /^\\d+\$/,
    inputValid = false;

        if(regex.test(amount1) && regex.test(amount2))
        {
        var newTotal = Number(amount1) + Number(amount2)
        
        \$("#total").text(newTotal);
        inputValid = true;
        }

    return inputValid
    }





    function updatePrices()
    {
    var subsidyTotal = Number(\$("#total").text());

        \$(".price").each(function()
        {
        var origVal = Number(\$(this).text())
        \$(this).text(origVal - subsidyTotal)
        })
    }



//# this seems to be where the data is pushed to the catalogue output
//# we need to get the data for pushing to the nav menu 

    var \$checkboxes = \$("input:checkbox");
    \$checkboxes.on("change", function()
    {
    var opts = getCatalogueFilterOptions();
    updateCatalogue(opts);
    });
    

// end //




  
    \$("#apply").on("click", function()
    {
    
         if(subsidyIsValid())
         {
         \$(this).prop("disabled", true);
         \$(this).next().prop("disabled", false);
         updatePrices();
         }
         else 
         {
         alert("Subsidy invalid!")
         }
    });




    \$("#remove").on("click", function()
    {
    \$("#amount1").val("");
    \$("#amount2").val("");
    \$("#total").text("0");
    \$(this).prop("disabled", true);
    \$(this).prev().prop("disabled", false);
    \$checkboxes.trigger("change");
    });



    \$checkboxes.trigger("change");
    updatePrices();
    </script> 
);

the html form

<div id="filter_div"> 

        <p style='display:none'>
          <input type="checkbox" id="product_category:kitchen equipment" checked=checked readonly/>
          <label for="kitchen equipment">kitchen equipment</label>
        </p> 
  <h2 class="accordion-toggle">Sub Category</h2>
  <div class="accordion-content">
        <p>
          <input type="checkbox" id="sub_category:kettles" />
          <label for="kettles">kettles</label>
        </p>
        <p>
          <input type="checkbox" id="sub_category:pedal bins" />
          <label for="pedal bins">pedal bins</label>
        </p>
        <p>
          <input type="checkbox" id="sub_category:tea makers" />
          <label for="tea makers">tea makers</label>
        </p>
        <p>
          <input type="checkbox" id="sub_category:utensils" />
          <label for="utensils">utensils</label>
        </p>
  </div>
  <h2 class="accordion-toggle">Brand names</h2>
  <div class="accordion-content"> 
        <p>
          <input type="checkbox" id="brand_name:brabantia" />
          <label for="brabantia">brabantia</label>
        </p>  
        <p>
          <input type="checkbox" id="brand_name:goodgrips" />
          <label for="goodgrips">goodgrips</label>
        </p>  
        <p>
          <input type="checkbox" id="brand_name:kenwood" />
          <label for="kenwood">kenwood</label>
        </p> 
  </div>
  <h3 class="accordion-toggle">Colours</h3>
  <div class="accordion-content">
    <p> 
      <input type="checkbox" id="colours:red black and silver" />
      <label for="red black and silver">red black and silver</label>
    </p>  
    <p> 
      <input type="checkbox" id="colours:stainless steel" />
      <label for="stainless steel">stainless steel</label>
    </p>  
    <p> 
      <input type="checkbox" id="colours:stainless steel & black" />
      <label for="stainless steel & black">stainless steel & black</label>
    </p>  
  </div>
  <h3 class="accordion-toggle" style='visibility:invisible;'>&nbsp;</h3>
  <div class='accordion-content'><p>&nbsp;</p></div> 
</div>
<div id="shopping_index" class='four'>

</div>


#11

Needing to catch when no results are returned…

The js sending off the ajax request

 function updateCatalogue(opts)
    {
 
        \$.ajax(
        {
        type: "POST",
        url: "/php-queries/product-catalogue-query.php",
        
        dataType : 'json',
        cache: false,
        data: {filterOpts: opts},
          success: function(records)
          {
          //alert('SUCCESS!');
          // alert(records);
          \$('#shopping_index').html(makeTable(records));
          }
          failure: function(records)
          {
          alert('no results');
          }
     
        });
    }

and then it processes it in this function

function makeTable(data)
    {
    var tbl_body = "";

      


        \$.each(data, function(k, v) 
        {
        var row = "",
        currRecord = this;


            \$.each(this, function(k , v) 
            {
                
                if( k==='brand_name' )
                {

                /* trim the product name to be just 'length' characters */
                var string = currRecord['product_name'];
                var length = 25;
                var trimmedString = (string.substring(0, length));



                v =  "<table><tr><td class='product_image'>"
                     + "<a href='/cgi-bin/catalogue_detail/" 
                     + currRecord['stock_data_id'] 
                     + "/"
                     + currRecord['product_name'] 
                     + "'>"
                     + "<img class='galleryThumbnail' src='/cgi-bin/mask.pl?client=" 
                     + currRecord['business_id'] 
                     + "&size=small-size&img=" 
                     + currRecord['image_name'] 
                     + "' rel='lightbox[" 
                     + currRecord['product_id'] 
                     + "]' title='" 
                     + currRecord['product_name'] 
                     + " - "
                     + currRecord['colour']
                     + "' /></a>"
                     + "</td></tr><tr><td>"
                     + "<h2>"
                     + "<a href='/cgi-bin/catalogue_detail/" 
                     + currRecord['stock_data_id'] 
                     + "/"
                     + currRecord['product_name'] 
                     + "'>" 
                     + v 
                     + "</a></h2></td></tr><tr><td class='price'>"
                     + "<div class='price_data'>"
                     + "<p>" + trimmedString + "</p>"
         
                     + "<p>" + currRecord['colour'] + "</p>"
                     + "<p>"  + currRecord['stock_availability'] + "</p>"
                     + "<p>"  + currRecord['currency_symbol_left'] + "&nbsp;" + currRecord['price'] + "</p>"
                     + "</div></td></tr></table>";
                row += ""+v+ "";
                }                
                else
                {
               // row += "" + k + v + "";
                }

         
            })

            tbl_body += "<div class='image_tab'>"+row+"</div>";
        })

    
    
    return tbl_body;
    }
 

I want the ‘else condition’ to output when no results are returned. Something like

Sorry! we have no products that match your filters.

If I select too many filters - so that nothing matches when the db is queried - I get no output from this js above.
So, in that instance, there is no key ‘brand_name’.

Why does my else clause not output when there is no brand_name key? Is it because there’s no data for that loop to process?

Then, perhaps a fairer question…, how can I see what ‘blank’ result is being returned?

In the function that gets the data back, I get no output when there is failure instead of success.

Bazz