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!
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 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
I need some help converting this code from SS3 to SS4.
I used the code below to pull my latest blog posts through to my custom homepage template. This no longer works for me in SS4. Not sure how what needs to be added to fix it.
class IndexPageController extends PageController {
public function LatestPostsHome()
{
return BlogCategory::get()
->filter('Title', 'Featured')
->relation('BlogPosts')
->sort('PublishDate', 'DESC');
}
}
Thank,
Do you have several BlogCategories with the same title?
If you only have one BlogCategory with title 'Featured' then this should work:
public function LatestPostsHome()
{
$blogCategory = BlogCategory::get()->filter('Title', 'Featured')->first();
if (!$blogCategory) {
return null;
}
// Get the corresponding has_many/many_many objects.
$blogPosts = $blogCategory->BlogPosts()->sort('PublishDate', 'DESC');
return $blogPosts;
}
If you have multiple categories with the same title, then you can maybe use something like this:
public function LatestPostsHome()
{
$blogCategories = BlogCategory::get()->filter('Title', 'Featured');
if (!$blogCategories->exists()) {
return null;
}
// Option 1 (not tested)
$categoryIDs = $blogCategories->column('ID');
$blogPosts = BlogPost::get()->byIDs($categoryIDs);
return $blogPosts;
// Option 2 (not tested)
$blogPosts = new \SilverStripe\ORM\ArrayList();
foreach ($blogCategories as $category) {
$posts = $category->BlogPosts();
$blogPosts->push($posts->toNestedArray());
}
return $blogPosts;
}
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');
I created a module that adds products from a remote resource but I want to check the price and availibility of a product before this is displayed in the browser.
I tried to change it in Bootstrap module:
<?php
public function hookHeader($params)
{
$controller = $this->context->controller;
if(!($controller instanceof ProductController)) {
return;
};
/* #var $controller ProductController */
$product = $controller->getProduct();
$product->name = 'Test Name';
$product->price = 20;
$product->quantity = 5;
$product->update();
}
But the old values are already in the templates.
Then I tried to override ProductController:
<?php
public function init()
{
parent::init();
$product = $this->product;
/* #var $product Product */
$product->price = 10;
$product->quantity = 10;
$product->update();
}
But happens the same that the first example.
So the questions are:
Where is the best place to check remote data and update the product before it is drawn on the output?
Best method to update price and quantity? Directly to the class or using StockAvailableCore class?
In my opinion the best way to way to update your product data is in your module hook function, and with StockAvailable class.