Calculate attribute value in indexer or cron?
-
28-02-2021 - |
Question
This is my observer and its updating my custom attribute every time when I save attributes on catalog_product_attribute_update_before event.
namespace MyVendor\MyModule\Observer;
class TotalCalcScore implements \Magento\Framework\Event\ObserverInterface
{
protected $_product;
public function __construct(
\Magento\Catalog\Model\ProductFactory $product
) {
$this->_product = $product;
}
public function execute(
\Magento\Framework\Event\Observer $observer
)
{
$productIds = $observer->getProductIds();
foreach($productIds as $id){
$product = $this->_product->create()->load($id);
if($product->getId()){
// attribute_first_count
$value_offirst_count = $product->getattribute_first_count();
// attribute_second_count
$value_offsecond_score = $product->getattribute_second_count();
// attribute_calculated_count
$value_calculated_score = $product->getattribute_calculated_count();
// calculate
$value_calculated_score = $value_offsecond_score + $value_offirst_count
//save calculated value
//$product->setCalculatedValue($value_calculated_score);
//save to attribute_calculated_score
$product->setAttrCalculatedScore($value_calculated_score);
$product->save();
}
}
}
But what should I do if I want to move this to Model and run this like cron job or indexation? Or is it better to run this before indexation like observer. (but I need load collection in that case?)
UPDATE:
I created mview.xml and indexer.xml and this is my Model/Review/Indexer/Review.php but still is not working corectly
class Review implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
{
/**
* Execute full indexation
*
* @return void
*/
public function executeFull()
{
// TODO: Implement executeFull() method.
}
/**
* Execute partial indexation by ID list
*
* @param int[] $ids
*
* @return void
*/
public function executeList(array $ids)
{
// TODO: Implement executeList() method.
}
/**
* Execute partial indexation by ID
*
* @param int $id
*
* @return void
*/
public function executeRow($id)
{
// TODO: Implement executeRow() method.
}
/**
* @var \Magento\Catalog\Api\Data\ProductInterfaceFactory
*/
private $productFactory;
/**
* @var \Magento\Catalog\Api\ProductRepositoryInterface
*/
private $productRepository;
/**
* MyClass constructor
*
* @param \Magento\Catalog\Api\Data\ProductInterfaceFactory $productFactory
* @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
*/
protected $collectionFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Catalog\Api\Data\ProductAttributeInterface $productAttribute,
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory
)
{
$this->productRepository = $productRepository;
$this->collectionFactory = $collectionFactory;
$this->collectionFactory = $productAttribute;
}
/**
* Execute materialization on ids entities
*
* @param int[] $ids
*
* @return void
* @api
*/
public function execute($ids)
{
// $post = $this->_postFactory->create();
// $collection = $post->getCollection();
// Use factory to create a new product collection
$productCollection = $this->collectionFactory->create();
// Apply filters here
$productCollection->addAttributeToSelect('*');
// Don't have to do this
$productCollection->load();
foreach($collection as $ids){
$productCollection->addAttributeToSelect('*');
// Don't have to do this
// $productCollection->load();
foreach ($productCollection as $product) {
// attribute_first_count
$value_offirst_count = $product->getattribute_first_count();
// attribute_second_count
$value_offsecond_score = $product->getattribute_second_count();
// attribute_calculated_count
$value_calculated_score = $product->getattribute_calculated_count();
// calculate
$value_calculated_score = $value_offsecond_score + $value_offirst_count
//save calculated value
//$product->setCalculatedValue($value_calculated_score);
//save to attribute_calculated_score
$product->setAttrCalculatedScore($value_calculated_score);
$product->save();
}
}
exit();
return $this->_pageFactory->create();
}
}
after reindex : index has been rebuilt successfully in 00:00:00 but there is no change in atribute value
Maybe I should add this like a cron job and this above not make any sense?
Solution
I finished to set this like a cron job. I'm not sure is it proper way to do this.
I moved my function from observer to controller and changed my crontab.xml to use this controller.
<job name="custom_cronjob" instance="MyVendor\MyModule\Controller\Calc" method="execute">
<schedule>* * * * *</schedule>
</job>