I want Magento (2.4) to set newly created products as new for specified period of time but only when product is created and not saved after being edited...
So, I would need something very similar to what's answered in Magento 2 Set Product as New when new product is created but for different method:
something like beforeCreate
which doesn't seem to exist...?
2 Answers
This answer is very similar to previous one, but use another one observer. In Magento for create
and update
operations uses the single action save
. If you want to check if is it new product on before_save
, you can check if a product has id or not.
Better to use event in correct area
app/code/Acme/StackExchange/etc/adminhtml/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="catalog_product_save_before">
<observer name="acme_stackexchange_observer_catalog_product_save_before"
instance="Acme\StackExchange\Observer\Catalog\ProductSaveBefore" />
</event>
</config>
app/code/Acme/StackExchange/Observer/Catalog/ProductSaveBefore.php
<?php
declare(strict_types=1);
namespace Acme\StackExchange\Observer\Catalog;
use Magento\Catalog\Model\Product;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProductSaveBefore implements ObserverInterface
{
/**
* @inheritDoc
*/
public function execute(Observer $observer)
{
/** @var Product $product */
$product = $observer->getEvent()->getData('product');
if (!$product->getId()) {
$newFromDate = date("m/d/Y");
$newToDate = date('m/d/Y', strtotime("+30 day"));
$product->setNewsFromDate($newFromDate);
$product->setNewsToDate($newToDate);
}
}
}
You don't need to double save product when you are using before_save
logic
[Update]
Alternative way with to do the same but with plugin
As I've pointed in comment, ideally to have properly configured dependencies
app/code/Acme/StackExchange/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Acme_StackExchange">
<sequence>
<module name="Magento_Catalog"/>
</sequence>
</module>
</config>
app/code/Acme/StackExchange/etc/adminhtml/di.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Model\ResourceModel\Product">
<plugin name="Acme_StackExchange_Plugin_Catalog_Model_ResourceModel_ProductPlugin"
type="Acme\StackExchange\Plugin\Catalog\Model\ResourceModel\ProductPlugin" sortOrder="10"/>
</type>
</config>
Acme/StackExchange/Plugin/Catalog/Model/ResourceModel/ProductPlugin.php
<?php
declare(strict_types=1);
namespace Acme\StackExchange\Plugin\Catalog\Model\ResourceModel;
use Magento\Catalog\Model\ResourceModel\Product;
use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Psr\Log\LoggerInterface;
class ProductPlugin
{
protected DateTime $coreDate;
protected LoggerInterface $logger;
public function __construct(
DateTime $coreDate,
LoggerInterface $logger
) {
$this->coreDate = $coreDate;
$this->logger = $logger;
}
public function beforeSave(Product $subject, AbstractModel $object): array
{
$this->logger->info('Before save product logic');
if (!$object->getId()) {
$this->logger->info('Set dates to new product');
$dateFrom = new \DateTime(date('Y-m-d H:i:s', $this->coreDate->timestamp()));
$dateTo = clone $dateFrom;
// add one month to current date
$dateTo->add(new \DateInterval('P1M'));
// optional remove one date from current date
$dateFrom->sub(new \DateInterval('P1D'));
$object->setNewsFromDate($dateFrom->format('Y-m-d H:i:s'));
$object->setNewsToDate($dateTo->format('Y-m-d H:i:s'));
$this->logger->info('setNewsFromDate = ' . $dateFrom->format('Y-m-d H:i:s'));
$this->logger->info('setNewsToDate = ' . $dateTo->format('Y-m-d H:i:s'));
}
return [$object];
}
}
In this plugin you can see example how to work with log and more correct way of date manipulations
system.log
[2022-06-21T16:46:56.666743+00:00] report.INFO: Before save product logic [] []
[2022-06-21T16:46:56.667859+00:00] report.INFO: Set dates to new product [] []
[2022-06-21T16:46:56.668130+00:00] report.INFO: setNewsFromDate = 2022-06-20 16:46:56 [] []
[2022-06-21T16:46:56.668260+00:00] report.INFO: setNewsToDate = 2022-07-21 16:46:56 [] []
Any solution or code provided by myself are were tested before publish on one of latest Magento version
To be sure you've cleared cache and for new extension register it and run bin/magento setup:upgrade
command.
For development purposes make sense to set your environment in developer mode with bin/magento deploy:mode:set developer
command
I'm also suggest to check what data is saved in DB and verify any places with custom logic for those fields in other events/plugins
-
Thanks. But I've been trying a few times and still can't get it working at all - no dates are set (in contrary to quoted plugin which changes dates after every save of product). I have changed namespace and so on to reflect my naming convention so, I can't find anything else to correct... What else I would need to check? Commented Jun 21, 2022 at 16:07
-
Ideally it's a sequence to
Magento_Catalog
inetc/modules.xml
but it's not required. I don't have any concrete idea what's wrong, please double check all file names, namespaces and class names and to be sure they are corresponding to their locations. To be sure you don't have few observers with the same name to the same event. I will update answer with plugin alternative, but anyway, observer should work. Try to add logging in observer to be sure your observer is properly configured and logic called on save Commented Jun 21, 2022 at 16:26 -
-
Hi @victor-tihonchuk, thanks again and finally it works! I had a small issue caused by copying code of di.xml as config declaration (xlmns) in this file was broken into 2 lines. BTW, why di.xml needs to be placed in adminhtml subfolder instead of directly in etc folder? Commented Jun 24, 2022 at 14:40
-
1You can register plugin in global scope and it will call for API as well Commented Jun 29, 2022 at 7:48
In this case, you can use the event like:
app/code/Vendor/Module/etc/events.xml:
<event name="catalog_product_save_after">
<observer name="my_custom_product_save_observer" instance="Vendor\module\Observer\Productsaveafter" />
</event>
And at this observer,you can get identify by below code
app/code/Vendor/Module/Observer/Productsaveafter.php
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
class Productsaveafter implements ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
/** @var Product $product */
$product = $observer->getEvent()->getProduct();
if($product->isObjectNew() )
{//new product
$new_from_date = date("m/d/Y");
$new_to_date = date('m/d/Y',strtotime("+30 day"));
$product->setNewsFromDate($new_from_date);
$product->setNewsToDate($new_to_date);
$product->save();
}
}
}
?>
-
Thanks, but where shall I apply it? After amending content of Vendor\Module\Plugin\SetNew.php it doesn't work at all... Commented Jun 14, 2022 at 14:59
-
-
I've changed it too but it doesn't work (set as new date isn't set at all) and also doesn't throw any errors... Commented Jun 15, 2022 at 15:31
-