I currently have a plugin that outputs the SKU of an ordered product to CSV and it works perfectly, however whenever a variable product is ordered the sku is empty.
I've looked at the code responsible and can see its looking for product_id then outputting get_sku however putting in a conditional and changing product_id to variable_id doesn't work, here is what I have so far;
foreach($this->order->get_items() as $item) {
$this->lines[] = $this->addOrderLine($item);
}
public function __construct($item, $order)
{
$this->item = $item;
$this->order = $order;
$this->product = wc_get_product($item->get_product_id());
}
public function getSku()
{
return $this->product->get_sku();
}
Any help would be greatly appreciated
Related
I am trying to get product(s) name and price from product collection for that I have created a custom script for test.
$bootstrap = Bootstrap::create(BP, $_SERVER);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get('\Magento\Framework\App\State');
$state->setAreaCode('adminhtml');
$collection = $objectManager->create('\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory')->create();
try {
echo $collection->addAttributeToSelect(['name','sku'])->getSelect();
} catch (Exception $exception) {
echo $exception->getMessage()."\n";
}
but when I run this script to check MySQL query I am getting below output:
SELECT `e`.* FROM `catalog_product_entity` AS `e`;
How can I get only product name and price instead of whole data?
As you're trying to get a product collection it's automatically going to get the main product entity table. It would need this in the query as a minimum as it needs the entity Id to be able to join with other tables to get the attributes required for the collection. You would not be able to retrieve your name attribute otherwise.
Note that this table is quite small and doesn't include any other attributes apart from the sku code.
If you dunp the data returned you'll see it doesn't actually grab all of the attributes, but it does need the main table.
If you have a specific need for only those two fields it would be better to use a custom query rather than a product collection.
I suggest you try this
public function getProductCollection()
{
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('*');
$collection->setPageSize(3); // fetching only 3 products
foreach ($productCollection as $product) {
$productPrice = $product->getPrice();
$productName = $product->getName();
}
}
Try this,
<?php
namespace BRINDA\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
protected $productCollectionFactory;
protected $categoryFactory;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Catalog\Model\CategoryFactory $categoryFactory,
array $data = []
) {
$this->productCollectionFactory = $productCollectionFactory;
$this->categoryFactory = $categoryFactory;
parent::__construct($context, $data);
}
public function getProductCollection()
{
$collection = $this->productCollectionFactory->create();
$collection->setPageSize(3);
foreach ($collection as $product)
{
echo "<pre>";
print_r($product->getPrice());
print_r($product->getName());
}
return $collection;
}
}
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory');
$collection = $productCollection->create()->addAttributeToSelect('*')->load();
foreach ($collection as $product){
echo 'Name = '.$product->getName().'<br>';
echo 'Price = '.$product->getFinalPrice().'<br>';
echo 'Url = '.$product->getProductUrl().'<br>';
echo 'Image = '.$product->getImage().'<br>';
}
?>
Try This.....
I'm using woocommerce_update_product hook to get product data once a product has been created / updated.
I'm trying to get the terms from a taxonomy called wcpv_product_vendors. On first save (as draft) I can get the other product_cat terms but the terms for wcpv_product_vendors don't appear until I next save the post.
add_action( 'woocommerce_update_product', [$this, 'dcgsql_update_product'], 50, 1);
public function dcgsql_update_product(){
$get_vendors = get_the_terms($product_id, 'wcpv_product_vendors');
if (!empty($get_vendors)) {
foreach ($get_vendors as $vendor) {
$vendorsarray[] = $vendor->term_id;
}
$vendors = implode(',',$vendorsarray);
} else {
$vendors = '';
}
}
On first save as draft, $get_vendors is always empty but I have applied one.
All other terms for product_cat are coming back fine.
Use the below codes it will work...
add_action( 'woocommerce_update_product', 'dcgsql_update_product', 50, 1);
public function dcgsql_update_product(){
$get_vendors = wp_get_post_terms($product_id, 'wcpv_product_vendors');
if (!empty($get_vendors)) {
foreach ($get_vendors as $vendor) {
$vendorsarray[] = $vendor->term_id;
}
$vendors = implode(',',$vendorsarray);
} else {
$vendors = '';
}
}
I have a block class which has:
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Catalog\Helper\Category $categoryHelper,
\Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState,
\Magento\Catalog\Model\CategoryFactory $categoryFactory,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
....
) {
$this->_categoryHelper = $categoryHelper;
$this->_categoryFactory = $categoryFactory;
$this->_collectionFactory = $collectionFactory;
$this->categoryFlatConfig = $categoryFlatState;
$this->_productCollectionFactory = $productCollectionFactory;
parent::__construct($context);
....
}
and a function of...
public function getProductCollection($childId)
{
$categoryId = $childId;
$category = $this->_categoryFactory->create()->load($categoryId);
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('name');
$collection->addAttributeToSelect('url');
$collection->addAttributeToSelect('image');
$collection->addAttributeToSelect('price');
$collection->addAttributeToSelect('special_price');
$collection->addCategoryFilter($category);
$collection->addAttributeToFilter('visibility', \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH);
$collection->addAttributeToFilter('status',\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
return $collection;
}
How do I use this production collection to create a layered navigation which uses attributes available for the products returned, and then be able to filter through with those.
Due to the nature of the site, I have to loop through this X amount of times on a category page, as I am getting products of each subcategory on this page in a certain way due to the design.
So in my template for E.G I have:
`$products= $this->getProductCollection($idhere);
foreach ($getmeprods as $products):?>
... looping through data
<?php endforeach;?>
`
Any help would be appreciate but I am rather boggled here!
I am new to magneto I have tried to duplicate a product programmatically and I have succeeded problem is the duplicated product is showing in magneto admin side while in the frontend the product is not displaying below is my code could you please tell me what is the issue it will be very helpful for me. I have created a separate module for it below is my code.
class Magentotutorial_Helloworld_IndexController extends Mage_Core_Controller_Front_Action {
public function indexAction() {
$final = $_POST['value'];
$obj = Mage::getModel('catalog/product');
$_product = $obj->load($final);
$newProduct = $_product->duplicate();
$newProduct->setStatus(1);
$newProduct->setSku('value'.$final);
$newProduct->setWebsiteIds($_product->getWebsiteIds());
$newProduct->getResource()->save($newProduct);
}
}
This function posted by you very well creates Duplicate product. However, it does not set the below attribute (due to which it's not VISIBLE in the frontend):
Navigate to Catalog > Manage Products > Duplicated Product > Inventory
Qty is 0 and Stock is "Out of Stock" - You will need to write below piece of code in the function to set this product to Stock: "In Stock" and Qty: [some default value] say, 100.
After the line which calls out $newProduct->setWebsiteIds($_product->getWebsiteIds());, you can insert the below lines:
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($newProduct->getId());
if ($stockItem->getId() > 0 && $stockItem->getManageStock())
{
$qty = 100; //set a default max value
$stockItem->setQty($qty);
$stockItem->setIsInStock((int)($qty > 0));
$stockItem->save();
}
You will need to run a Re-Index either Manually or Automate it
The product will display in the frontend. See Screenshot below:
[EDIT]
Use the below code and let me know if it works for you:
public function indexAction()
{
$productId = $this->getRequest()->getParam('value');
$productObject = Mage::getModel('catalog/product');
$_product = $productObject->load($productId);
$newProduct = $_product->duplicate();
$newProduct->setStatus(1);
//$newProduct->setName('Duplicate-' . $_product->getName());
$newProduct->setSku('value' . $productId);
$newProduct->setWebsiteIds($_product->getWebsiteIds());
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($newProduct->getId());
if ($stockItem->getId() > 0 && $stockItem->getManageStock())
{
$qty = 100;
$stockItem->setQty($qty);
$stockItem->setIsInStock((int)($qty > 0));
$stockItem->save();
}
$newProduct->getResource()->save($newProduct);
$indexers = Mage::getSingleton('index/indexer')->getProcessesCollection();
foreach ($indexers as $indexer)
{
$indexer->reindexEverything();
}
}
Hope this helps.
Happy Coding...
I'm hooking into the sales_quote_save_after event disaptcher. Firstly as a test I'm trying to get the items in the cart and change their prices to 0. After I do that I'll be building in some other stuff.
I'm having trouble. I can change the unit price no problem, but when I go to recalculate the cart totals the prices are reverting back to the original price.
public function sales_quote_save_before($observer) {
if (Mage::registry('basket_observer_executed')) {
return $this;
}
$quote = $observer->getEvent()->getQuote();
foreach ($quote->getAllItems() as $item) {
if($item->getId()) {
$item->setCustomPrice(0);
}
}
Mage::register('basket_observer_executed', true);
$quote->save();
$quote->setTotalsCollectedFlag(false)->collectTotals();
}
Can anyone point me towards maintaining the new price whilst doing the recalculation of the totals?
I'd try using a different event. I always use checkout_cart_save_after for doing similar actions.Using the event I mentioned, use the following code:
$cart = $observer->getData('cart');
$quote = $cart->getData('quote');
$items = $quote->getAllVisibleItems();
foreach($items as $item)
{
$item->setCustomPrice(0);
$item->setOriginalCustomPrice(0);
$item->getProduct()->setIsSuperMode(true);
$item->save();
}
$quote->save();
$quote->setTotalsCollectedFlag(false)->collectTotals();