Opencart 3.0: Get the 'Product_Id' of the Last Item Added To Cart - opencart

I'm working with Opencart 3.0 to set up a product cross-sell to display similar items to the user when they add something to the cart. I thought I had seen a pattern with the array of products in the cart that put the last item of cart at the end. So my php looked something like this:
$this->load->model('catalog/product');
$related_product_id = $products;
$related_product_id = end($related_product_id);
$related_product_id = $related_product_id['product_id'];
$related = $this->model_catalog_product->getProductRelated($related_product_id);
foreach ($related as $related) {
//..do something
}
Using the end() method in the above code would take the very last Key=>Value (Product_id) in the array so I could use it to display the product on the page.
This worked for a while until I noticed that it was not always accurate. If someone added something already in the cart, it wouldn't place it at the end of the array, and also other certain products for some reason didn't show up at the end of the array.
Is there another way to get the Product_Id of the last item a user added to the cart than the way I'm going about it? My way doesn't seem very consistent. Thanks!

I was able to figured it out adding my own function to /system/libray/cart/cart.php
I added this function
public function getProductsInCart() {
$product_data = array();
$cart_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "cart WHERE api_id = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND customer_id = '" . (int)$this->customer->getId() . "' AND session_id = '" . $this->db->escape($this->session->getId()) . "' ORDER BY date_added ASC");
foreach ($cart_query->rows as $cart) {
$product_data[] = array(
'cart_id' => $cart['cart_id'],
'product_id' => $cart['product_id'],
'date_added' => $cart['date_added'],
);
}
return $product_data;
}
And instead of using the $this->cart->getProducts() line to get products from the cart, I'm using my new function $this->cart->getProductsInCart().
This works way more consistent. The only thing it doesn't take into consideration is when someone goes back to a product already added. It doesn't count it as a new product added, but instead just updates it quantity.
Let me know if someone finds a better solution.

Related

Getting stock information in opencart 3.x

I want to implement a task similar to the one here Getting stock information in opencart 2.3.0.2, but my problem is that when deleting a product, the information about the warehouse will disappear. I want to enter the data into the table order_product, but I still don’t understand how. Help me please.
I can't figure out how to write information about the rest of the goods to the database. I don't understand how to implement it.
Hmm... You want to save product`s stock information in order_product table?
So first you must to add custom field in oc_order_product
ALTER TABLE `oc_order_product` ADD `stock_status` INT(11) NOT NULL AFTER `reward`;
Then in catalog/controller/checkout/confirm.php in $order_data['products'][] = array( You must add key - stock_status
'stock' => $this->model_catalog_product->getProduct($product['product_id'])['stock_status'],
So we modified our controller in customer side, and now our data receive the stock_status.
After receive products data from customer side, we must save in oc_order_table
Open path - catalog/model/checkout/order.php and edit addOrder function... After reward = '" . (int)$product['reward'] . "' in products loop add after comma:
stock_status = '" . $this->db->escape(product['stock_status']) . "'
I write an example, how to save data from customer side about product stock data.

PHP Query Updated Rows Count

I am a .NET programmer and rarely work with PHP. How can I tell if this query fails or if this query updates 0 rows? I am using OpenCart:
public function updateInventory($product_id, $quantity)
{
$query = $this->db->query("Update " . DB_PREFIX . "product SET quantity ='" . $this->db->escape($quantity) . "' WHERE sku='" . $this->db->escape($product_id) . "'");
return "OK";
}
replacing
return "OK";
with (depends on libraries you use to connect with database. mysql , mysqli or pdo)
return mysql_affected_rows();
will get you the affected rows. That is from PHP code side. Opencart has a default function that you can use: $this->db->countAffected()
but i am not sure if they have kept it the same through different versions.
source : http://us3.php.net//manual/en/function.mysql-affected-rows.php
Hope everything is clear enough.
You probably have no updated quantity for the product because you are comparing SKU and product_id in your query.
If you want to update product quantity by product_id, you need to change your expression to this one:
'UPDATE `' . DB_PREFIX . 'product` SET `quantity` =' . (int)$quantity . ' WHERE `product_id`= " . (int)$product_id
"WHERE product_id = some_product_id" instead of "WHERE sku = some_product_id"
Comparing SKU with product_id in WHERE statement is the reason why your query updates 0 rows.

Obtain product custom field value in Virtuemart

I am trying to obtain value of a custom field of a product. I only have ID of that product. I know title of the custom field.
How can I get value of that custom field?
Please help.
PS: I know PHP well but I am new to Joomla/Virtuemart.
This will work for VM2.x
VM is storing the custom field values in #__virtuemart_customs
The relation between the product and the custom field is maintaining in the #__virtuemart_product_customfields
You have title and Product Id so you can try this
$db = &JFactory::getDBO();
$sql = "SELECT F.custom_value #__virtuemart_customs AS C LEFT JOIN #__virtuemart_product_customfields AS F ON F.virtuemart_customfield_id = C.virtuemart_custom_id where (C.custom_title='$your_customtitle' and F.virtuemart_product_id = '$product_id')";
$db->setQuery($sql);
$db->query();
$res = $db->loadAssoc();
echo $res['custom_value'];
Also you try with inner sub query .
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('virtuemart_product_id,custom_value');
$query->from('#__virtuemart_product_customfields');
$db->setQuery((string)$query);
$results = $db->loadObjectList();
if ($results){
foreach($results as $result)
{
// do your stuff here
}

Doctrine 2 edit DQL in entity

I have several database tables with 2 primary keys, id and date. I do not update the records but instead insert a new record with the updated information. This new record has the same id and the date field is NOW(). I will use a product table to explain my question.
I want to be able to request the product details at a specific date. I therefore use the following subquery in DQL, which works fine:
WHERE p.date = (
SELECT MAX(pp.date)
FROM Entity\Product pp
WHERE pp.id = p.id
AND pp.date < :date
)
This product table has some referenced tables, like category. This category table has the same id and date primary key combination. I want to be able to request the product details and the category details at a specific date. I therefore expanded the DQL as shown above to the following, which also works fine:
JOIN p.category c
WHERE p.date = (
SELECT MAX(pp.date)
FROM Entity\Product pp
WHERE pp.id = p.id
AND pp.date < :date
)
AND c.date = (
SELECT MAX(cc.date)
FROM Entity\ProductCategory cc
WHERE cc.id = c.id
AND cc.date < :date
)
However, as you can see, if I have multiple referenced tables I will have to copy the same piece of DQL. I want to somehow add these subqueries to the entities so that every time an entity is called it adds this subquery.
I have thought of adding this in a __construct($date) or some kind of setUp($date) method, but I'm kind of stuck here. Also, would it help to add #Id to Entity\Product::date?
I hope someone can help me. I do not expect a complete solution, one step in a good direction would be very much appreciated.
I think I've found my solution. The trick was (first, to update to Doctrine 2.2 and) using a filter:
namespace Filter;
use Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\Filter\SQLFilter;
class VersionFilter extends SQLFilter {
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) {
$return = $targetTableAlias . '.date = (
SELECT MAX(sub.date)
FROM ' . $targetEntity->table['name'] . ' sub
WHERE sub.id = ' . $targetTableAlias . '.id
AND sub.date < ' . $this->getParameter('date') . '
)';
return $return;
}
}
Add the filter to the configuration:
$configuration->addFilter("version", Filter\VersionFilter");
And enable it in my repository:
$this->_em->getFilters()->enable("version")->setParameter('date', $date);

Is this the proper way to handle an ordered array with Doctrine2's WHERE IN expression?

Using Zend Lucene Search, I am returning a list of relevance-ordered IDs that map to blog records that I will fetch from the database.
Is this the proper way of handling an array with Doctrine2's WHERE IN expression:
$dql = "SELECT b FROM BlogPost WHERE b.id IN (" . implode(', ', $ids) . ")";
$query = $em->createQuery($dql);
...
Or is there a better way of maybe passing in the actual $ids array as a parameter to the query?
Also, the Zend Search returns the array of IDs based on relevance. Will using the above technique preserve the order of relevance in retrieving the blog posts?
If it makes you feel better, you can use the ExpressionBuilder.
$ex = $em->getExpressionBuilder();
$dql = 'SELECT b FROM BlogPost b WHERE ' . $ex->in('b.id', $ids));
$query = $em->createQuery($dql);
function cmp($a, $b) {
global $ids;
return (array_search($a->getId(), $ids) < array_search($b->getId(), $ids)) ? -1 : 1;
}
usort($res, 'cmp');
It's a bit cleaner, but does the same as you behind the screens.
You should pas the $ids array through setParameter() function as this is a best practice in doctrine:
$query = $this->_em->createQuery('SELECT b FROM BlogPost WHERE b.id IN (?1)');
$query->setParameter(1, implode(',', $ids));
I think the IN statement will not preserve the order of the passed ID's as IN will match the first found $id not depending on the order.