Jump to content
cinolas

Product attribute values not showing in shopping cart, but showing during checkout.

Recommended Posts

I'm using osCommerce 2.3.4 BS and QTPro and Attribute Sort Order.

As the title suggests, the product attribute values are not showing on the shopping cart page. It shows the correct number of dashes under the product name where the attributes should be listed, but there's nothing after the dashes. The attribute values show up fine during the checkout process, so it has to be a display problem specific to shopping_cart.php

I just moved host (new PHP version, new MySQL version, etc) and I believe that's when this problem started. Could this be caused by a change in PHP version or something like that?

Is this a known bug with certain PHP versions? I'm struggling with other bugs as well so this could be a hint as to what's happening.

The code in my shopping_cart.php is standard I believe:

if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
        reset($products[$i]['attributes']);
        while (list($option, $value) = each($products[$i]['attributes'])) {
          $products_name .= '<br /><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . str_ireplace('Select ', "<span style=\"color: red\">Select </span>", $products[$i][$option]['products_options_values_name']) . '</i></small>';
        }
      }

Again, this code generates the correct number of dashes, so it loops properly through the right number of attributes, it just doesn't pull the values. The values are in the DB. Any clues?

Thanks!

Edited by cinolas

Share this post


Link to post
Share on other sites

I'm surprised this isn't a common problem.

It may not have anything to do with the host move, I'm finding out some bugs I had attributed to the move were actually there before...

Share this post


Link to post
Share on other sites

My 2.3.4.1CE shopping cart.php is different from yours and looks neater:

 

Quote

      if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
        foreach($products[$i]['attributes'] as $option => $value) {
          $products_name .= '<br /><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name'] . '</i></small>';
        }
      }

You may want to try this version and see if it works.

Share this post


Link to post
Share on other sites

Thanks @kgtee, that was worth a try, but interestingly it gives the exact same result: It draws the right number of dashes, but the values are missing. So strange.

Share this post


Link to post
Share on other sites

Comparing to a 2.3.4 BS CE with the latest QTPro installed...

Edited by cinolas

Share this post


Link to post
Share on other sites

The kgtee version is PHP 7 compatible. 

The attributes would be set in includes/classes/order.php from values that it would try to load based on information from includes/classes/shopping_cart.php


Always back up before making changes.

Share this post


Link to post
Share on other sites
22 hours ago, ecartz said:

The kgtee version is PHP 7 compatible. 

The attributes would be set in includes/classes/order.php from values that it would try to load based on information from includes/classes/shopping_cart.php

Thanks @ecartz that's a good clue. Neither of those 2 file has been modified in my installation, other than for QTPro. I tested the sql query for the attribute values at the end of the cart function of includes/classes/order.php (which was modified for QTPro) the same way as I did the one in shopping_cart.php (replaced variables with specific ids from know product) and it returns the text values as expected.

The includes includes/classes/shopping_cart.php files doesn't deal with the text values that I can see, only setting the IDs, and that part works well. I can make the shopping cart page dump the attribute IDs array and the IDs are all there and fine, it's just the text it's not pulling.

There's this bit of SQL on /shopping_cart.php that seems to be cycling through the IDs in the cart array to request the related values in the product options table:

$products = $cart->get_products();
    for ($i=0, $n=sizeof($products); $i<$n; $i++) {
// Push all attributes information in an array
      if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
        while (list($option, $value) = each($products[$i]['attributes'])) {
          echo tep_draw_hidden_field('id[' . $products[$i]['id'] . '][' . $option . ']', $value);
		  
		  $attributes = tep_db_query("select popt.products_options_name, popt.products_options_track_stock, poval.products_options_values_name, pa.options_values_price, pa.price_prefix
                                      from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                      where pa.products_id = '" . (int)$products[$i]['id'] . "'
                                       and pa.options_id = '" . (int)$option . "'
                                       and pa.options_id = popt.products_options_id
                                       and pa.options_values_id = '" . (int)$value . "'
                                       and pa.options_values_id = poval.products_options_values_id
                                       and popt.language_id = '" . (int)$languages_id . "'
                                       and poval.language_id = '" . (int)$languages_id . "'");
          $attributes_values = tep_db_fetch_array($attributes);

          $products[$i][$option]['products_options_name'] = $attributes_values['products_options_name'];
          $products[$i][$option]['options_values_id'] = $value;
          $products[$i][$option]['products_options_values_name'] = $attributes_values['products_options_values_name'];
          $products[$i][$option]['options_values_price'] = $attributes_values['options_values_price'];
          $products[$i][$option]['price_prefix'] = $attributes_values['price_prefix'];

		  $products[$i][$option]['track_stock'] = $attributes_values['products_options_track_stock'];

        }
      }
    }

Since the data IS in the DBs, and since the SQL query has been tested to be correct, it seems the problem should be in the above code. Either in the way it tries to find the related records in products_options and products_options_values, or in the way it then puts the text data in the array to be displayed. But this code is standard and valid and I can see nothing wrong with it. Any idea how I can test or trace this bit of code, to see where between building the query, fetching the array, and putting it in the variables the text disappears?

Cheers!

Share this post


Link to post
Share on other sites
29 minutes ago, cinolas said:

Any idea how I can test or trace this bit of code, to see where between building the query, fetching the array, and putting it in the variables the text disappears?

If this is a test installation, just add

print_r(array($products[$i][$option], $i, $option, $attribute_values, $languages_id));

right after the last track_stock line.  If in production, figure out the customer ID of your test user and add something like

if (1 == $customer_id) {
  print_r(array($products[$i][$option], $i, $option, $attribute_values, $languages_id));
}

replace 1 with the appropriate value.  You can find the customer ID in admin/customers.php or by looking it up in the database. 

It's often easiest to do a view source to look at the debugging output, since the HTML display eats white space.  You may have to install developer tools to get a view source option. 

In admin > Configuration > Logging, you could turn on the option to log database queries.  That would tell you exactly what values are used in the query so that you can repeat it in phpMyAdmin. 


Always back up before making changes.

Share this post


Link to post
Share on other sites

trouble might be here  try to do it without 

str_ireplace
str_ireplace('Select ', "<span style=\"color: red\">Select </span>", $products[$i][$option]['products_options_values_name']) . '</i></small>';

Share this post


Link to post
Share on other sites
On 2/14/2020 at 11:51 PM, hungryfrank said:

trouble might be here  try to do it without 


str_ireplace

str_ireplace('Select ', "<span style=\"color: red\">Select </span>", $products[$i][$option]['products_options_values_name']) . '</i></small>';

@hungryfrank I did remove that until I can get the data to display. Same results. Good thinking though. Cheers!

Share this post


Link to post
Share on other sites
53 minutes ago, cinolas said:

@hungryfrank I did remove that until I can get the data to display. Same results. Good thinking though. Cheers!

 $products_name .= '<br /><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name']) . '</i></small>';
       

usually when a few guys look at the code they miss the small things

Share this post


Link to post
Share on other sites

Thanks @ecartz. I added the print_r line just under the track_stock line and it printed nothing. Nothing to be seen in the source:

<div class="contentContainer">
  <div class="contentText">

PRINT_R RESULTS SHOULD BE HERE
    
    <table class="table table-striped table-condensed">
      <tbody>
<tr>  <td valign="top" align="center"><a href="https://www.rollergirl.ca/skateshop/product_info.php?products_id=2183{98}2348"><img src="images/IMPROLLER1_holographic_300.jpg" alt="Impala - Holographic" title="Impala - Holographic" width="115" height="115" class="img-responsive" /></a></td>  <td valign="top"><a href="https://www.rollergirl.ca/skateshop/product_info.php?products_id=2183{98}2348"><strong>Impala - Holographic</strong></a><br /><small><i> -  </i></small><br><input type="text" name="cart_quantity[]" value="1" style="width: 45px;" class="form-control" /><input type="hidden" name="products_id[]" value="2183{98}2348" /> <button  type="submit" class="btn btn-info btn-xs">update</button> <a id="btn2" href="https://www.rollergirl.ca/skateshop/shopping_cart.php?products_id=2183{98}2348&amp;action=remove_product" class="btn btn-danger btn-xs"> <span class="glyphicon glyphicon-trash"></span> </a></td><td align="right" valign="top"><strong>$125<span class="cent">.00 CAD</span></strong></td></tr>
      </tbody>
    </table>

I tried adding an echo "hello world" to see if I would get that in the source, and that didn't show up either! Hmmmm I moved the echo outside the

while (list($option, $value) = each($products[$i]['attributes'])) {

and it finally showed up, so the contents of that while is not happening.

Strangely that very same while statement is used a few line under to cycle through the attributes to actually show the contents on screen:

if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
        reset($products[$i]['attributes']);
        while (list($option, $value) = each($products[$i]['attributes'])) {
		  $products_name .= '<br /><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name'] . '</i></small>';
        }
}

And that while statement seems to be happening since I see the dash on the page where the attribute should be.

I actually added a bunch of echos to run a trace of sorts. It goes into the FOR statement, then into the IF statement, but it does NOT go into the first WHILE. It does however go into the second WHILE. I copied the syntax over, it's the very same syntax and condition.

I truly don't understand how that can be. Any clues again, is gold. Thanks!

Share this post


Link to post
Share on other sites

The relevant part of my shopping_cart.php looks like this now with the echos in place. It shows "inside for", "inside if" then "inside SECOND while", but NOT "inside FIRST while" or "Victory!".

$any_out_of_stock = 0;
    $products = $cart->get_products();
    for ($i=0, $n=sizeof($products); $i<$n; $i++) {
		if (2 == $customer_id) {	
			echo "inside for<br>";
	}
// Push all attributes information in an array
      if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
		  if (2 == $customer_id) {	
			echo "inside if<br>";
		  }
        while (list($option, $value) = each($products[$i]['attributes'])) {
			if (2 == $customer_id) {	
			echo "inside FIRST while<br>";
			}
          echo tep_draw_hidden_field('id[' . $products[$i]['id'] . '][' . $option . ']', $value);

		  $attributes = tep_db_query("select popt.products_options_name, popt.products_options_track_stock, poval.products_options_values_name, pa.options_values_price, pa.price_prefix
                                      from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                      where pa.products_id = '" . (int)$products[$i]['id'] . "'
                                       and pa.options_id = '" . (int)$option . "'
                                       and pa.options_id = popt.products_options_id
                                       and pa.options_values_id = '" . (int)$value . "'
                                       and pa.options_values_id = poval.products_options_values_id
                                       and popt.language_id = '" . (int)$languages_id . "'
                                       and poval.language_id = '" . (int)$languages_id . "'");
          $attributes_values = tep_db_fetch_array($attributes);

          $products[$i][$option]['products_options_name'] = $attributes_values['products_options_name'];
          $products[$i][$option]['options_values_id'] = $value;
          $products[$i][$option]['products_options_values_name'] = $attributes_values['products_options_values_name'];
          $products[$i][$option]['options_values_price'] = $attributes_values['options_values_price'];
          $products[$i][$option]['price_prefix'] = $attributes_values['price_prefix'];

		  $products[$i][$option]['track_stock'] = $attributes_values['products_options_track_stock'];

		  if (2 == $customer_id) {
			  print_r(array($products[$i][$option], $i, $option, $attribute_values, $languages_id));
			  var_dump ($attributes_values);
			  var_dump ($attributes);
			  echo "Victory!";
		  }
        }
      }
    }
?>

    <table class="table table-striped table-condensed">
      <tbody>
<?php
    $products_name = NULL;
    for ($i=0, $n=sizeof($products); $i<$n; $i++) {
		
      $products_name .= '<tr>';

      $products_name .= '  <td valign="top" align="center"><a href="' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id']) . '">' . tep_image(DIR_WS_IMAGES . $products[$i]['image'], $products[$i]['name'], SMALL_IMAGE_WIDTH, SMALL_IMAGE_HEIGHT) . '</a></td>' .
                        '  <td valign="top"><a href="' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id']) . '"><strong>' . $products[$i]['name'] . '</strong></a>';

      if (STOCK_CHECK == 'true') {
		//$stock_check = tep_check_stock($products[$i]['id'], $products[$i]['quantity']);
		//++++ QT Pro: Begin Changed code
        if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
          $stock_check = tep_check_stock($products[$i]['id'], $products[$i]['quantity'], $products[$i]['attributes']); 
        }else{
          $stock_check = tep_check_stock($products[$i]['id'], $products[$i]['quantity']);
        }
//++++ QT Pro: End Changed Code

        if (tep_not_null($stock_check)) {
          $any_out_of_stock = 1;

          $products_name .= $stock_check;
        }
      }

		
	if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
        reset($products[$i]['attributes']);
        while (list($option, $value) = each($products[$i]['attributes'])) {
		 if (2 == $customer_id) {	
			echo "inside SECOND while<br>";
		  }
		  $products_name .= '<br /><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name'] . '</i></small>';
        }
      }

 

Edited by cinolas

Share this post


Link to post
Share on other sites

What does this line do: reset($products[$i]['attributes']);

It's just above the second while, but not above the first one. Could it explain why the first while is being skipped but not the second one?

Cheers!

Share this post


Link to post
Share on other sites

I also tried enabling the logging of SQL queries (though it's probably not an SQL query problem at this point) but it doesn't seem to work. My settings are like:

Store Page Parse Time    true 
Log Destination    /rollergirl.ca/html/skateshop/err_logs/page_parse_time.log
Log Date Format    %d/%m/%Y %H:%M:%S 
Display The Page Parse Time    true 
Store Database Queries    true

I created the /rollergirl.ca/html/skateshop/err_logs/page_parse_time.log folder and file chmodded both to 777, but nothing gets written in to the file...

Edited by cinolas

Share this post


Link to post
Share on other sites
44 minutes ago, cinolas said:

It's just above the second while, but not above the first one. Could it explain why the first while is being skipped but not the second one?

It tells it to start over at the beginning.  And yes. 

You could try switching the first while to a foreach. 

        foreach ($products[$i]['attributes'] as $option => $value) {

That would avoid the need to reset and it would be forwardly compatible if you wanted to update to PHP 7. 


Always back up before making changes.

Share this post


Link to post
Share on other sites

That solved it! Not sure why it didn't want to do the that WHILE, but the FOREACH works like a charm.

THANK YOU! so much. seriously.

2 hours ago, ecartz said:

It tells it to start over at the beginning.  And yes. 

You could try switching the first while to a foreach. 


        foreach ($products[$i]['attributes'] as $option => $value) {

That would avoid the need to reset and it would be forwardly compatible if you wanted to update to PHP 7. 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×