DWB DWB - 5 months ago 20
PHP Question

Return a Key from the Next and Last Element in Array / Foreach Loop

I am hoping to modify the manner in which discounts are displayed for an eCommerce platform (OpenCart - PHP MVC based).

The default behaviour is that the discounts will be displayed as:


  • 5 or more: $20.00

  • 10 or more: $18.00

  • 20 or more: $16.00



I would prefer:


  • 5 - 9: $20.00

  • 10 - 19: $18.00

  • 20+: $16.00



Stripping out the "or more" text is simple enough through the template file (code provided below).

For all but the last element, this would require taking the quantity key ($discount['quantity']) from the next element and applying a basic maths function (- 1), then returning this new value besides the original.

For the last element, I would need to simply return the last quantity value and add "+" text.

Original code (controller):

$discounts = $this->model_catalog_product->getProductDiscounts($this->request->get['product_id']);

$this->data['discounts'] = array();

foreach ($discounts as $discount) {
$this->data['discounts'][] = array(
'quantity' => $discount['quantity'],
'price' => $this->currency->format($this->tax->calculate($discount['price'], $product_info['tax_class_id'], $this->config->get('config_tax')))
);
}


Original code (template):

<?php if ($discounts) { ?>
<div class="discount">
<?php foreach ($discounts as $discount) { ?>
<span><?php echo sprintf($text_discount, $discount['quantity'], $discount['price']); ?></span>
<?php } ?>
</div>
<?php } ?>


Modified code to strip "or more" text from template (Note: Separate echo's used to allow table formatting - To maintain simplicity, these tags are not included):

<?php if ($discounts) { ?>
<div class="discount">
<?php foreach ($discounts as $discount) { ?>
<?php echo $discount['quantity']; ?><?php echo $discount['price']; ?>
<?php } ?>
</div>
<?php } ?>


How can I further modify this code to return the quantities in the preferred format?

Note: The arrays are quite small but I would still consider performance as a priority.

Edit:

Thank you tttony for providing the solution below. This is the code I have used in the template file for the custom table formatting (without the sprintf/formatted string function).

<?php for ($i=0; $i < count($discounts) -1; $i++) { ?>
<tr>
<td><?php echo $discounts[$i]['quantity']; ?> - <?php echo (int)$discounts[$i+1]['quantity'] - 1; ?></td>
<td><?php echo $discounts[$i]['price']; ?></td>
</tr>
<?php } ?>
<?php if (count($discounts)) { ?>
<tr>
<td><?php echo $discounts[$i]['quantity']; ?>+</td>
<td><?php echo $discounts[$i]['price']; ?></td>
</tr>
<?php } ?>

Answer

You can try this, very simple, in the product.php controller file

$discounts = $this->model_catalog_product->getProductDiscounts($this->request->get['product_id']);

$discounts_formated = array();

for ($i=0; $i < count($discounts) -1; $i++) { 
    $discounts_formated[] =  sprintf("%s - %s", $discounts[$i]['quantity'], (int)$discounts[$i+1]['quantity'] - 1);
}

// Last discount: 30+
$discounts_formated[] =  sprintf("%s+", $discounts[$i]['quantity']);

var_dump($discounts_formated);

Output:

array (size=3)
  0 => string '10 - 19' (length=7)
  1 => string '20 - 29' (length=7)
  2 => string '30+' (length=3)

EDIT:

Edit the file product.tpl, I tested with OC 1.5.6.4 and it's working

<?php if ($discounts) { ?>
    <br />
    <div class="discount">
        <?php for ($i=0; $i < count($discounts) -1; $i++) { ?>
            <?php echo sprintf("%s - %s: %s", $discounts[$i]['quantity'], (int)$discounts[$i+1]['quantity'] - 1, $discounts[$i]['price']); ?><br />
        <?php } ?>
        <?php if (count($discounts)) { // last discount ?>
            <?php echo sprintf("%s+: %s", $discounts[$i]['quantity'],  $discounts[$i]['price']); ?><br />
        <?php } ?>
    </div>
<?php } ?>

Will print something like this:

10 - 19: $88.00
20 - 29: $77.00
30+: $66.00