displaying lowest starting from product price on opencart - php

Instead of having a base price on the product and displaying that I want to set the base price as 0.00 and display the lowest costing option price i.e
Polo shirt price = 0
Small = £10
Medium = £15
Large = £20
and it should display Starting from £10
Currently on the product page it displays price as 0 until and option is selected
<?php echo $price; ?>
I want it to do something like this but i am unsure of the syntax
<?php $min_value [] = $options['option_value']; ?>
<?php $min_value_price [] = $min_value['price']; ?>
<?php $min = min($min_value_price); ?>
<?php echo $min; ?>
Is this somewhere along the right lines? Currently it doesn't display anything with the above code
Model
public function getProductOptions($product_id) {
$product_option_data = array();
$product_option_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option po LEFT JOIN `" . DB_PREFIX . "option` o ON (po.option_id = o.option_id) LEFT JOIN " . DB_PREFIX . "option_description od ON (o.option_id = od.option_id) WHERE po.product_id = '" . (int)$product_id . "' AND od.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY o.sort_order");
foreach ($product_option_query->rows as $product_option) {
if ($product_option['type'] == 'select' || $product_option['type'] == 'radio' || $product_option['type'] == 'checkbox' || $product_option['type'] == 'image') {
$product_option_value_data = array();
$product_option_value_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_id = '" . (int)$product_id . "' AND pov.product_option_id = '" . (int)$product_option['product_option_id'] . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY ov.sort_order");
foreach ($product_option_value_query->rows as $product_option_value) {
$product_option_value_data[] = array(
'product_option_value_id' => $product_option_value['product_option_value_id'],
'option_value_id' => $product_option_value['option_value_id'],
'name' => $product_option_value['name'],
'image' => $product_option_value['image'],
'quantity' => $product_option_value['quantity'],
'subtract' => $product_option_value['subtract'],
'price' => $product_option_value['price'],
'price_prefix' => $product_option_value['price_prefix'],
'weight' => $product_option_value['weight'],
'weight_prefix' => $product_option_value['weight_prefix']
);
}
$product_option_data[] = array(
'product_option_id' => $product_option['product_option_id'],
'option_id' => $product_option['option_id'],
'name' => $product_option['name'],
'type' => $product_option['type'],
'option_value' => $product_option_value_data,
'required' => $product_option['required']
);
} else {
$product_option_data[] = array(
'product_option_id' => $product_option['product_option_id'],
'option_id' => $product_option['option_id'],
'name' => $product_option['name'],
'type' => $product_option['type'],
'option_value' => $product_option['option_value'],
'required' => $product_option['required']
);
}
}
return $product_option_data;
}
Controller
$this->data['options'] = array();
foreach ($this->model_catalog_product->getProductOptions($this- >request->get['product_id']) as $option) {
if ($option['type'] == 'select' || $option['type'] == 'radio' || $option['type'] == 'checkbox' || $option['type'] == 'image') {
$option_value_data = array();
foreach ($option['option_value'] as $option_value) {
if (!$option_value['subtract'] || ($option_value['quantity'] > 0)) {
if ((($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) && (float)$option_value['price']) {
$price = $this->currency->format($this->tax->calculate($option_value['price'], $product_info['tax_class_id'], $this->config->get('config_tax')));
} else {
$price = false;
}
$option_value_data[] = array(
'product_option_value_id' => $option_value['product_option_value_id'],
'option_value_id' => $option_value['option_value_id'],
'name' => $option_value['name'],
'image' => $this->model_tool_image->resize($option_value['image'], 50, 50),
'price' => $price,
'price_prefix' => $option_value['price_prefix']
);
}
}
$this->data['options'][] = array(
'product_option_id' => $option['product_option_id'],
'option_id' => $option['option_id'],
'name' => $option['name'],
'type' => $option['type'],
'option_value' => $option_value_data,
'required' => $option['required']
);
} elseif ($option['type'] == 'text' || $option['type'] == 'textarea' || $option['type'] == 'file' || $option['type'] == 'date' || $option['type'] == 'datetime' || $option['type'] == 'time') {
$this->data['options'][] = array(
'product_option_id' => $option['product_option_id'],
'option_id' => $option['option_id'],
'name' => $option['name'],
'type' => $option['type'],
'option_value' => $option['option_value'],
'required' => $option['required']
);
}
}

Simply add the following code in controller inside first loops if condition Just after
$option_value_data = array(); around line 349.
if($option['option_id'] == your_option_id){
function cmp($a, $b)
{
return $b['price'] + $a['price'];
}
usort($option['option_value'], "cmp");
$this->data['min_price'] = $option['option_value'][0]['price'];
}
Replace your_option_id with required option ID you want.
Now in template file check if $min_price is set then echo $min_price else echo default price.
if(isset($min_price)){
echo $min_price;
......
}else{
echo $price
......
}

The problem here is the settings... Product should not have a price $0.0 while options are setting the product's price. Instead of this the product should have some price (You can use the lowest possible for the product) and options then only modify this base price:
T-shirt polo: $10.0
Small (S): +$0.0
Medium (M): +$1.0
Large (L): +$2.0
X-Large (XL): +$3.0
XX-Large (XXL): +$4.0
If Your store is selling products where options will always modify the price, You can then only check (in the template) whether the product has options, and in this case You can display something like Price: starting from $10.0, if the products has no options, display it like usual, e.g. Price: $10.0.
Or is there any big reason for setting the base price to 0.0?
Just my very own opinion: people don't like (in general) when a T-shirt (or any other piece of clothes) has different price regarding the size they need and moreover they can be discouraged when their size is more expensive. It is a good practice to calculate some average price for a T-shirt (or any other piece of clothes) and use this average price for all sizes. If I had to do that, I would expect to sell e.g. 20% of S, 30% of M and L, 15% of XL and 5% of XXL - then I could calculate the average price as 0.2 x 10 + 0.3 x 11 + 0.3 x 12 + 0.15 x 13 + 0.05 x 14 = 2 + 3.3 + 3.6 + 1.95 + 0.7 = 11.55. I will then use this average price for all sizes of this very shirt...

Maybe replace order in mysql query (model file)
$product_option_value_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_id = '" . (int)$product_id . "' AND pov.product_option_id = '" . (int)$product_option['product_option_id'] . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY ov.sort_order");
to
$product_option_value_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_id = '" . (int)$product_id . "' AND pov.product_option_id = '" . (int)$product_option['product_option_id'] . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY pov.price ASC");
ov.sort_order >>
pov.price ASC
or
ov.sort_order >>
pov.price DESC

Related

Warning: Illegal string offset 'quantity' Opencart 2.1

Im trying to resolve this question about 5 hours, but I cant.
The problem is I have an error
"Warning: Illegal string offset 'quantity' in C:\laragon\www\opencart\system\library\cart.php on line 211"
My code from system\library\cart.php
elseif ($option_query->row['type'] == 'checkbox_shildik2') {
$value = json_decode(json_encode($value),true);
foreach ($value as $product_option_value_id => $data) {
$qnt = (int)$data['quantity'];
if($qnt > 0){
$option_value_query = $this->db->query("SELECT pov.option_value_id, ovd.name, pov.quantity, pov.subtract, pov.price, pov.price_prefix, pov.points, pov.points_prefix, pov.weight, pov.weight_prefix FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_option_value_id = '" . (int)$product_option_value_id . "' AND pov.product_option_id = '" . (int)$product_option_id . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "'");
$qnt = (int)$qnt;
if ($option_value_query->num_rows) {
if ($option_value_query->row['price_prefix'] == '+') {
$option_price += $qnt*$option_value_query->row['price'];
} elseif ($option_value_query->row['price_prefix'] == '-') {
$option_price -= $qnt*$option_value_query->row['price'];
}
if ($option_value_query->row['points_prefix'] == '+') {
$option_points += $qnt*$option_value_query->row['points'];
} elseif ($option_value_query->row['points_prefix'] == '-') {
$option_points -=$qnt* $option_value_query->row['points'];
}
if ($option_value_query->row['weight_prefix'] == '+') {
$option_weight += $qnt*$option_value_query->row['weight'];
} elseif ($option_value_query->row['weight_prefix'] == '-') {
$option_weight -= $qnt*$option_value_query->row['weight'];
}
if ($option_value_query->row['subtract'] && (!$option_value_query->row['quantity'] || ($option_value_query->row['quantity'] < $qnt * $cart['quantity']))) {
$stock = false;
}
$option_data[] = array(
'product_option_id' => $product_option_id,
'product_option_value_id' => $product_option_value_id,
'option_id' => $option_query->row['option_id'],
'option_value_id' => $option_value_query->row['option_value_id'],
'name' => $qnt.' x '.$option_query->row['name'],
'value' => $option_value_query->row['name'],
'type' => $option_query->row['type'],
'quantity' => $option_value_query->row['quantity'],
'subtract' => $option_value_query->row['subtract'],
'price' => $qnt*$option_value_query->row['price'],
'price_prefix' => $option_value_query->row['price_prefix'],
'points' => $qnt*$option_value_query->row['points'],
'points_prefix' => $option_value_query->row['points_prefix'],
'weight' => $qnt*$option_value_query->row['weight'],
'weight_prefix' => $option_value_query->row['weight_prefix']
);
}
}
}
}
So when I click on add to cart, I have Unexpected token json.
I dont know even how to resolve this and whats the problem
211 line is $qnt = (int)$data['quantity'];
use: $qnt = !empty((int)$data['quantity']) ? (int)$data['quantity'] : ' ';

MeDoo - Conditional LIKE in the WHERE part

How can I write the follow sql query in MeDoo???
SELECT * FROM lockers WHERE Active = 1 AND GymID = " . $gimid . " AND ForMale = " . $male .
($filter ? " AND Locker LIKE '%" . $filter . "%'" : "")
The problem for me is the conditional LIKE.
$total = $this->db->count('lockers',
['AND' => [
'Active' => 1,
'GymID' => $gimid,
'ForMale' => $male
]]
);
Some suggestion????
Thanks a lot!!!
Finally, I solved it in the follow way:
// getting locker's total
$total = $this->db->debug()->count('lockers', [
'AND' => [
'Active' => 1,
'GymID' => $gimid,
'ForMale' => $male,
'Locker[~]' => $filter ? $filter : '' //<- LIKE with empty string shows all
]
]);

PHP Payment Gateway Transaction Errors

I keep getting get the following 2 errors which I do not know how to fix
Fatal error: Uncaught exception 'InvalidArgumentException' with message 'invalid keys: lineItems[ in C:\wamp64\www\pay\braintree\lib\Braintree\Util.php on line 351
And
InvalidArgumentException: invalid keys: lineItems[ in C:\wamp64\www\pay\braintree\lib\Braintree\Util.php on line 351
This is line 351 throw new InvalidArgumentException('invalid keys: ' . $sortedList); from the code below.
public static function verifyKeys($signature, $attributes)
{
$validKeys = self::_flattenArray($signature);
$userKeys = self::_flattenUserKeys($attributes);
$invalidKeys = array_diff($userKeys, $validKeys);
$invalidKeys = self::_removeWildcardKeys($validKeys, $invalidKeys);
if(!empty($invalidKeys)) {
asort($invalidKeys);
$sortedList = join(', ', $invalidKeys);
throw new InvalidArgumentException('invalid keys: ' . $sortedList);
}
}
Here is the first of my two functions that seem to cause the errors
function payment_data($gateway, $order_id){
try{
$account_number = account_number();
$total_amount = total_amount();
$credit_cards = $gateway->customer()->find($account_number);
$members_first_name = $credit_cards->firstName;
$members_last_name = $credit_cards->lastName;
$members_email = $credit_cards->email;
if(!empty($credit_cards)){
foreach($credit_cards->creditCards as $c){
if($c->default === true){
$first_name = $c->billingAddress->firstName;
$last_name = $c->billingAddress->lastName;
$street_address = $c->billingAddress->streetAddress;
$extended_address = $c->billingAddress->extendedAddress;
$city = $c->billingAddress->locality;
$region = $c->billingAddress->region;
$postal_code = $c->billingAddress->postalCode;
$country_name = $c->billingAddress->countryName;
$card_token = $c->token;
$customer_id = $c->customerId;
if(empty($extended_address)){
$extended_address = null;
}
if(empty($region)){
$region = null;
}
$result = $gateway->transaction()->sale([
'amount' => $total_amount,
'orderId' => $order_id,
'customerId' => $customer_id,
'customer' => [
'firstName' => $members_first_name,
'lastName' => $members_last_name,
'email' => $members_email
],
'billing' => [
'firstName' => $first_name,
'lastName' => $last_name,
'streetAddress' => $street_address ,
'extendedAddress' => $extended_address,
'countryName' => $country_name,
'locality' => $city,
'region' => $region,
'postalCode' => $postal_code
],
'shipping' => [
'firstName' => $first_name,
'lastName' => $last_name,
'streetAddress' => $street_address ,
'extendedAddress' => $extended_address,
'countryName' => $country_name,
'locality' => $city,
'region' => $region,
'postalCode' => $postal_code
],
'lineItems' => [
products($order_id)
],
'options' => [
'submitForSettlement' => true
]
]);
}
}
}
} catch (Braintree_Exception_NotFound $e) {
return false;
}
}
Here is my second function
function products($order_id){
if(products('Now') !== false){
$total = count(products('Now'));
$x = 1;
$line_items = '';
foreach(products('Now') as $product){
$title = $product['title'];
$quantity = $product['quantity'];
$sales_tax = $product['sales_tax'];
$regular_price = $product['regular_price'];
$total_sales_tax = $product['total_sales_tax'];
$total_amount = $product['total_amount'];
$savings_price = $product['savings_price'];
$product_id = $product['product_id'];
$line_items .= "[";
$line_items .= "'name' => '" . $title . "',";
$line_items .= "'description' => 'Product',";
$line_items .= "'quantity' => '" . $quantity . "',";
$line_items .= "'unitTaxAmount' => '" . $sales_tax . "',";
$line_items .= "'unitAmount' => '" . $regular_price . "',";
$line_items .= "'taxAmount' => '" . $total_sales_tax . "',";
$line_items .= "'totalAmount' => '" . $total_amount . "',";
$line_items .= "'discountAmount' => '" . $savings_price . "',";
$line_items .= "'productCode' => '" . $product_id . "',";
$line_items .= "'kind' => 'debit',";
$line_items .= "'url' => 'http://localhost/product.php?id=" . $product_id . "'";
if($x !== $total){
$line_items .= "],";
} else {
$line_items .= "]";
}
$x++;
}
return $line_items;
}
}
I'm guessing you need something more like this, I've used Braintree a bit and I've never passed it a big string of data like that.
function products($order_id){
if(products('Now') !== false){
$total = count(products('Now'));
$line_items = Array();
foreach(products('Now') as $product){
$title = $product['title'];
$quantity = $product['quantity'];
$sales_tax = $product['sales_tax'];
$regular_price = $product['regular_price'];
$total_sales_tax = $product['total_sales_tax'];
$total_amount = $product['total_amount'];
$savings_price = $product['savings_price'];
$product_id = $product['product_id'];
$line_item = Array();
$line_item['name'] = $title;
$line_item['description'] = 'Product';
$line_item['quantity'] = $quantity;
$line_item['unitTaxAmount'] = $sales_tax;
$line_item['unitAmount'] = $regular_price;
$line_item['taxAmount'] = $total_sales_tax;
$line_item['totalAmount'] = $total_amount;
$line_item['discountAmount'] = $savings_price;
$line_item['productCode'] = $product_id;
$line_item['kind'] = 'debit';
$line_item['url'] = 'http://localhost/product.php?id=' . $product_id;
$line_items[] = $line_item;
}
return $line_items;
}
}

separating and adding the array data

I have an array like this, which has the product selected data.
$option_data[] = array(
'product_option_id' => $product_option_id,
'product_option_value_id' => $option_value,
'name1' => $option_value['name'],
'option_id' => $option_query->row['option_id'],
'option_value_id' => $option_value_query->row['option_value_id'],
'name' => $option_query->row['name'],
'option_value' => $option_value_query->row['name'],
'type' => $option_query->row['type'],
'quantity' => $option_value_query->row['quantity'],
'subtract' => $option_value_query->row['subtract'],
'price' => $option_value_query->row['price'],
'sdate' => $option_value_query->row['sdate'],
'edate' => $option_value_query->row['edate'],
'price_prefix' => $option_value_query->row['price_prefix'],
'points' => $option_value_query->row['points'],
'points_prefix' => $option_value_query->row['points_prefix'],
'weight' => $option_value_query->row['weight'],
'weight_prefix' => $option_value_query->row['weight_prefix']
);
And I need the values for price, So I have assigned price value like this
$pricelist = $option_value_query->row['price'];
Actually it has two values , now I want to add those two values. I am not getting how to separate it and add those values.
EDITED ****
My function is like this
public function getProducts12() {
if ($this->data) {
foreach ($this->session->data['cart'] as $key => $quantity) {
$product = explode(':', $key);
$product_id = $product[0];
$stock = true;
//echo $product_id;
// Options
if (isset($product[1])) {
$options = unserialize(base64_decode($product[1]));
} else {
$options = array();
}
$product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) WHERE p.product_id = '" . (int)$product_id . "' AND pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.date_available <= NOW() AND p.status = '1'");
if ($product_query->num_rows) {
$option_price = 0;
$option_points = 0;
$option_weight = 0;
foreach ($options as $option)
{
$array123[] = $option;
$var123 = $array123[0];
}
$option_data = array();
foreach ($options as $product_option_id => $option_value) {
$option_query = $this->db->query("SELECT po.product_option_id, po.option_id, od.name, o.type FROM " . DB_PREFIX . "product_option po LEFT JOIN `" . DB_PREFIX . "option` o ON (po.option_id = o.option_id) LEFT JOIN " . DB_PREFIX . "option_description od ON (o.option_id = od.option_id) WHERE po.product_option_id = '" . (int)$product_option_id . "' AND po.product_id = '" . (int)$product_id . "' AND od.language_id = '" . (int)$this->config->get('config_language_id') . "'");
if ($option_query->num_rows) {
if ($option_query->row['type'] == 'radio' ){
$option_value_query = $this->db->query("SELECT pov.option_value_id, ovd.name, pov.price, pov.sdate, pov.edate, pov.price_prefix, pov.points, pov.points_prefix, pov.weight, pov.weight_prefix FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_option_value_id = '" . (int)$option_value . "' AND pov.product_option_id = '" . (int)$product_option_id . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "'");
if ($option_value_query->num_rows) {
if ($option_value_query->row['price_prefix'] == '+') {
$option_price += $option_value_query->row['price'];
} elseif ($option_value_query->row['price_prefix'] == '-') {
$option_price -= $option_value_query->row['price'];
}
if ($option_value_query->row['points_prefix'] == '+') {
$option_points += $option_value_query->row['points'];
} elseif ($option_value_query->row['points_prefix'] == '-') {
$option_points -= $option_value_query->row['points'];
}
if ($option_value_query->row['weight_prefix'] == '+') {
$option_weight += $option_value_query->row['weight'];
} elseif ($option_value_query->row['weight_prefix'] == '-') {
$option_weight -= $option_value_query->row['weight'];
}
$option_data[] = array(
'product_option_id' => $product_option_id,
'product_option_value_id' => $option_value,
'name1' => $option_value['name'],
'option_id' => $option_query->row['option_id'],
'option_value_id' => $option_value_query->row['option_value_id'],
'name' => $option_query->row['name'],
'option_value' => $option_value_query->row['name'],
'type' => $option_query->row['type'],
'quantity' => $option_value_query->row['quantity'],
'subtract' => $option_value_query->row['subtract'],
'price' => $option_value_query->row['price'],
'sdate' => $option_value_query->row['sdate'],
'edate' => $option_value_query->row['edate'],
'price_prefix' => $option_value_query->row['price_prefix'],
'points' => $option_value_query->row['points'],
'points_prefix' => $option_value_query->row['points_prefix'],
'weight' => $option_value_query->row['weight'],
'weight_prefix' => $option_value_query->row['weight_prefix']
);
}
//var_dump ($option_value_query->row['price']);
$pricelist = $option_value_query->row['price'];
//$_SESSION['m'] = $pricelist[0];
}
}
}
var_dump($pricelist);
}
}
}
//echo ($option_price);
return $this->data;
//echo $this->data;
}
}

get index of array with condition

I have this kind of array :
$arrVar = array(
0 => array(
'val'=> 9
),
1 => array(
'val'=> 12,
),
2 => array(
'val'=> 4
),
);
How do I make a function that returns the index of an array based on a variable $myVar?
For example :
if $myVar = 4 the function will return $arrVar['2']
if $myVar = 8 the function will return $arrVar['2']
if $myVar = 10 the function will return $arrVar['0']
This is my array
$arrVar = array(
0 => array(
'qty'=>9,
'disc'=> 0.15
),
1 => array(
'qty'=>12,
'disc'=> 0.20
),
2 => array(
'qty'=>4,
'disc'=> 0.10
),
);
when customer A buy 4 products he will get disc 10%
or when customer A buy 8 products he will get disc 10%
or when customer A buy 10 products he will get disc 15%
Use following php function to calculate your discount percentage:
function searchArr($needle) {
global $arrVar;
$arr=array();
foreach($arrVar as $key => $value) {
$vals = array_values($value);
$arr[$vals[0]] = $vals[1];
}
ksort($arr);
$prev=0;
foreach($arr as $key => $value) {
if ($needle < $key)
return 100 * ($prev==0 ? $value : $prev);
$prev = $value;
}
return 100 * $prev;
}
TESTING:
echo "Discount: " . searchArr(4) . "%\n";
echo "Discount: " . searchArr(8) . "%\n";
echo "Discount: " . searchArr(10) . "%\n";
echo "Discount: " . searchArr(12) . "%\n";
OUTPUT:
Discount: 10%
Discount: 10%
Discount: 15%
Discount: 20%
See this code running here: http://ideone.com/zLDen

Categories