Get product name and price from product collection - php

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.....

Related

Wrong discount calculation on Shopware 6 Price Collector/Processor

I implemented a price collector / processor exactly as described in the docs (https://developer.shopware.com/docs/guides/plugins/plugins/checkout/cart/change-price-of-item).
For testing purposes every line item product in the cart has a price of 100€.
When applying a discount (10%) that I have created in the admin, the discount is applied on the original price of the product but not on the actual new cart price.
What am I missing here? My OverwritePriceCollector.php looks as following:
<?php declare(strict_types=1);
namespace Test\TestPlugin\Core\Checkout\Cart;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\CartDataCollectorInterface;
use Shopware\Core\Checkout\Cart\CartProcessorInterface;
use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\AbsolutePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\PercentagePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class OverwritePriceCollector implements CartDataCollectorInterface, CartProcessorInterface
{
/**
* #var QuantityPriceCalculator
*/
private $calculator;
public function __construct(QuantityPriceCalculator $calculator) {
$this->calculator = $calculator;
}
public function collect(CartDataCollection $data, Cart $original, SalesChannelContext $context, CartBehavior $behavior): void
{
// get all product ids of current cart
$productIds = $original->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE)->getReferenceIds();
// remove all product ids which are already fetched from the database
$filtered = $this->filterAlreadyFetchedPrices($productIds, $data);
// Skip execution if there are no prices to be saved
if (empty($filtered)) {
return;
}
foreach ($filtered as $id) {
$key = $this->buildKey($id);
// Needs implementation, just an example
$newPrice = 100;
// we have to set a value for each product id to prevent duplicate queries in next calculation
$data->set($key, $newPrice);
}
}
public function process(CartDataCollection $data, Cart $original, Cart $toCalculate, SalesChannelContext $context, CartBehavior $behavior): void
{
// get all product line items
$products = $toCalculate->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE);
foreach ($products as $product) {
$key = $this->buildKey($product->getReferencedId());
// no overwritten price? continue with next product
if (!$data->has($key) || $data->get($key) === null) {
continue;
}
$newPrice = $data->get($key);
// build new price definition
$definition = new QuantityPriceDefinition(
$newPrice,
$product->getPrice()->getTaxRules(),
$product->getPrice()->getQuantity()
);
// build CalculatedPrice over calculator class for overwritten price
$calculated = $this->calculator->calculate($definition, $context);
// set new price into line item
$product->setPrice($calculated);
$product->setPriceDefinition($definition);
}
}
private function filterAlreadyFetchedPrices(array $productIds, CartDataCollection $data): array
{
$filtered = [];
foreach ($productIds as $id) {
$key = $this->buildKey($id);
// already fetched from database?
if ($data->has($key)) {
continue;
}
$filtered[] = $id;
}
return $filtered;
}
private function buildKey(string $id): string
{
return 'price-overwrite-'.$id;
}
}
I think your problem is that you registered your Collector with the same priority as in documentation (4500).
Shopware PromotionProcessor is registered with priority 4900, so your code is called after PromotionProcessor.
So what do you need is to register your OverwritePriceCollector with higher priority e.g. 5000.

How to update product quantity after order was placed in Laravel PHP

Product Table
Product Attribute Table
My PostOrder Function
public function getPaymentStatus(Request $request){
if ($result->getState() == 'approved') {
$user_id = Auth::user()->id;
$user_email = Auth::user()->email;
//get shipping details
$shippingDetails = DeliveryAddress::where(['user_email'=>$user_email])->first();
$order = new Order;
$order->user_id = $user_id;
$order->user_email = $user_email;
$order->name = $shippingDetails->name;
$order->address = $shippingDetails->address;
$order->city = $shippingDetails->city;
$order->state = $shippingDetails->state;
$order->country = $shippingDetails->country;
$order->postcode = $shippingDetails->postcode;
$order->mobile = $shippingDetails->mobile;
$order->coupon_code = $coupon_code;
$order->coupon_amount = $coupon_amount;
$order->order_status = "New";
$order->grand_total = Session::get('grand_total');
$order->save();
$order_id = DB::getPdo()->lastInsertId();
$cartProducts = DB::table('cart')->where(['user_email'=>$user_email])->get();
foreach($cartProducts as $pro){
$cartPro = new OrdersProduct;
$cartPro->order_id = $order_id;
$cartPro->user_id = $user_id;
$cartPro->product_id = $pro->product_id;
$cartPro->product_code = $pro->product_code;
$cartPro->product_name = $pro->product_name;
$cartPro->product_size = $pro->size;
$cartPro->product_color = $pro->product_color;
$cartPro->product_price = $pro->price;
$cartPro->product_qty = $pro->quantity;
$cartPro->save();
}
return redirect('/thank-you');
}
i have a table "products" which store product details and a table "products_attribute" which store the stock of the product. I don't know how link this to products_attribute table. Please Help.
It looks like you already have a grasp of Eloquent Models with your Order and DeliveryAddress model.
To setup relationships between your Product and Product Attribute simply define the relationship method inside your Product model:
<?php
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function attributes()
{
return $this->hasMany('ProductAttribute');
}
}
Eloquent will use snake case in determining the name of foreign key, which in this case would be product_id. If your foreign key is defined differently you may specify the name as a second argument:
return $this->hasMany('ProductAttribute', 'my_product_id');
If you want to have a relationship from ProductAttribute to Product use the belongsTo method:
<?php
use Illuminate\Database\Eloquent\Model;
class ProductAttribute extends Model
{
public function product()
{
return $this->belongsTo('Product');
}
}
You may also specify a custom foreign key name similar to the hasMany method:
return $this->belongsTo('Product', 'my_product_id');
To update the quauntity you could do something like this:
foreach($cartProducts as $pro){
$cartPro = new OrdersProduct;
$cartPro->order_id = $order_id;
$cartPro->user_id = $user_id;
$cartPro->product_id = $pro->product_id;
$cartPro->product_code = $pro->product_code;
$cartPro->product_name = $pro->product_name;
$cartPro->product_size = $pro->size;
$cartPro->product_color = $pro->product_color;
$cartPro->product_price = $pro->price;
$cartPro->product_qty = $pro->quantity;
$cartPro->save();
$product = Product::find($pro->product_id);
if (null !== $product) {
// you will need a sku or some other unique identifier
// from your attribute to determine the correct attribute
// to modify after your order is complete
$attribute = $product->attributes()-where('sku', $sku)->first();
$attribute->quantity = $attribute->quantity - $pro->quantity;
$attribute->save();
}
}
you should use relationships here
first you create ProductModel
after that you create one method like attributes
and use hasMany relationships
so you can do whatever you want

Create layered navigation with custom productcollection magento2

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!

Can Someone Explain me the below Code?

Now my question is:
1) what the use of Order.php and why he create? and how can i store the Refrence of $order with the Object?
2) And please describe the code(i know the comment is already there but i need help )
Now Main.php:
<?php
include("Order.php");
include("connect.php");
$query="SELECT * FROM `orders`";
$filter_Result=mysqli_query($con,$query);
$newOrders=Array();
$items = array();
while($row=mysqli_fetch_array($filter_Result))
{
$order;
$orderId= $row['id']; //fetch row id
echo "hello".$orderId;
if(in_array($orderId,$newOrders,true)){
//we already created an array object for this id..use it
$order=<get order object from $newOrders for which id is $orderId>
}
else{
$order=new Order($row['id'], $row['tableId'], $row['createdDate']);
//$newOrders.AddToArray($order);
array_push($newOrders,$order);
}
$item=new Item($row['ProductId'], $row['ProductName'], $row['Quantity']);
$Order.AddItem($item);
}
foreach($order as $newOrders)
{
//create box
}
include("Modal.php");
?>
now Order.php:
<?php
class Order {
/* Member variables */
var $orderId;
var $orderTime;
var $tableNumber;
var $items = array();
function __Order($orderId, $orderTime, $tableNumber)
{
$this->$orderId = $orderId;
$this->$orderTime = $orderTime;
$this->$tableNumber = $tableNumber;
}
function AddItem($itemId, $itemName, $quantity, $personalization)
{
$item = new Item($itemId, $itemName, $quantity, $personalization);
$items[] = $item;
}
}
class Item {
var $productId;
var $productName;
var $quantity;
var $personalization;
function __Item($productId, $productName, $quantity, $personalization)
{
$this->$productId = $productId;
$this->$productName = $productName;
$this->$quantity = $quantity;
$this->$personalization = $personalization;
}
}
?>
He created the Order.php to keep the class elements external from the main code. This is cleaner code and easier to maintain.
and how can i store the Refrence of $order with the Object? You are already storing this in $newOrders?
Added comments to each line for main.php
<?php
// these includes are just bringing in code from external files. Nothing much really to say here.
include("Order.php");
include("connect.php");
//$query is just setting up the SQL query to the database for selecting all columns from a table called orders.
$query="SELECT * FROM `orders`";
//$filter_Results is just saving the query in a variable, this is used later on to fetch the data in a while loop
$filter_Result=mysqli_query($con,$query);
//$newOrders and $items = array() is just pre-defining these variables as arrays.
$newOrders=Array();
$items = array();
//As said before, we need to use a while loop to extract the data fetched from sql where `mysqli_fetch_array` is the method of retrieving the data.
while($row=mysqli_fetch_array($filter_Result))
{
$order; //Not sure what the next line is doing.. `$order;` doesn't do anything..
$orderId= $row['id']; //Saving the column name `id` as a variable $orderID
echo "hello".$orderId; //echo out the hello# where # is the orderID
//This is checking if the orderID retrieved from sql has already been placed inside the $newOrders array returning true or false.
if(in_array($orderId,$newOrders,true)){
//Some more code needs to be added here, I'm guessing you need to add in something to find the object relating to the `orderID` that already exists in `$newOrders`
$order=<get order object from $newOrders for which id is $orderId>
}
// If $orderID not in $newOrders
else{
// Create a new instance of Order class called $order
$order=new Order($row['id'], $row['tableId'], $row['createdDate']);
//Add this order to the array $newOrders
array_push($newOrders,$order);
}
// Create a new instance of the Item class called $item takinging in the columns ProductId, ProductName, Quantity
$item=new Item($row['ProductId'], $row['ProductName'], $row['Quantity']);
// Using a method from orders called AddItem (this can be found in Order.php under the order class
$Order.AddItem($item);
}
// Looping through each order inside $newOrders (although this seems wrong, should be foreach($newOrders as $order)
foreach($order as $newOrders)
{
//create box
}
/ Finally including some more code inside the Modal.php file
include("Modal.php");
?>
Order.php
<?php
// Class called Order
class Order {
// properties of the class.
var $orderId;
var $orderTime;
var $tableNumber;
var $items = array();
// Function inside the method which fills the properties upon creating a new instance the class `$order=new Order($row['id'], $row['tableId'], $row['createdDate']);`
function __Order($orderId, $orderTime, $tableNumber)
{
// Using the parameters passed to the function to fill the properties of the class
$this->$orderId = $orderId;
$this->$orderTime = $orderTime;
$this->$tableNumber = $tableNumber;
}
//Function called AddItem which takes parameters and fills an items array however this should be using $this->
function AddItem($itemId, $itemName, $quantity, $personalization)
{
$item = new Item($itemId, $itemName, $quantity, $personalization);
$items[] = $item;
}
}
// New class called Item
class Item {
// properties of the class.
var $productId;
var $productName;
var $quantity;
var $personalization;
// Same as above: Function inside the method which fills the properties upon creating a new instance the class
function __Item($productId, $productName, $quantity, $personalization)
{
$this->$productId = $productId;
$this->$productName = $productName;
$this->$quantity = $quantity;
$this->$personalization = $personalization;
}
}
?>
To answer your question:
An array of objects just means you are creating a new instance of the object and then saving the object in an array. You are already doing this with your $newOrders array. You have created a new $order (the object) and then saved it in the array $newOrders using: array_push($newOrders,$order);
Not really sure what you are asking for here? Where has this code come from? Is this a tutorial of some sort?

Magento 2 How to get category by url_key

I try to get a category in Magento 2.0 by it url_key.
Now I've got :
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$categoryFactory = $objectManager->create('Magento\Catalog\Model\CategoryFactory');
$category = $categoryFactory->create()
->addAttributeToFilter('url_key','my_category_url_key');
It returns me this error :
Error filtering template: Invalid method
Magento\Catalog\Model\Category\Interceptor::addAttributeToFilter(Array
( [0] => url_key [1] => my_category_url_key ) )
Thanks.
/**
* #var \Magento\Catalog\Model\CategoryFactory
****** inject in constructor ******
*/
protected $categoryFactory;
---------
---------
---------
$categories = $this->categoryFactory->create()
->getCollection()
->addAttributeToFilter('url_key','devops')
->addAttributeToSelect(['entity_id']);
echo "<pre>";
print_r($categories->getFirstItem()->getEntityId());
I know this is an old question, but in case anybody wonders...
All answers here use the ObjectManager. That's bad practice. The correct way to implement this, is as follows:
namespace Vendor\Module\Model;
use Magento\Catalog\Model\CategoryFactory;
class MyClass {
private $categoryFactory;
public function __construct(
CategoryFactory $categoryFactory
} {
$this->categoryFactory = $categoryFactory;
}
public function MyFunction() {
$categoryFactory = $this->categoryFactory->create();
$category = $categoryFactory->loadByAttribute('url_key', 'my_category_key');
$categoryId = $category->getId(); // E.g. if you want the ID.
}
In this example, category will contain the object of the category with URL-key 'my_category_key'.
addAttributeToFilter is a method of collections.
You should execute in on a category collection, not on a category instance.
Try this below code, i hope you will get your result.
<?php
$objectManagerr = \Magento\Framework\App\ObjectManager::getInstance();
$categoryFactory = $objectManagerr->create('Magento\Catalog\Model\ResourceModel\Category\CollectionFactory');
$categoryy = $categoryFactory->create()
->addAttributeToFilter('url_key','your_category_url_key')
->addAttributeToSelect('*');
foreach ($categoryy as $productt){
echo $productt->getName().'<br>';
echo $productt->getId();
}
?>
Based on your code, you missed the correct method in order to get a category via url_key.
Right now we can use method loadByAttribute, so you code should be something like this:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$categoryFactory = $objectManager->create('Magento\Catalog\Model\CategoryFactory');
$category = $categoryFactory->create()->loadByAttribute('url_key','my_category_url_key');

Categories