15

I want to create command for delete operation for simple product by sku. I'm getting following error.how to set admin area?

[Magento\Framework\Exception\LocalizedException]
Delete operation is forbidden for current area

<?php
namespace Sivakumar\Sample\Console;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;

class DeleteSimpleProduct extends Command
{
    protected $_product;
    public function __construct(\Magento\Catalog\Model\Product $_product)
    {
        $this->_product =$_product;
        parent::__construct();
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('delete_simple_product')
            ->setDescription('Delete Simple Product')
            ->setDefinition($this->getOptionsList());

        parent::configure();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $errors = $this->validate($input);
        if ($errors) {
            throw new \InvalidArgumentException(implode("\n", $errors));
        }

    $product_id = $this->_product->getIdBySku($input->getOption('sku'));
    $product=$this->_product->load($product_id);
        $product->delete();
        $output->writeln('<info>product deleted ' . $input->getOption('sku') . '</info>');
    }

    public function getOptionsList()
    {
        return [
            new InputOption('sku', null, InputOption::VALUE_REQUIRED, 'SKU'),
        ];
    }

    public function validate(InputInterface $input)
    {
        $errors = [];
        $required =['sku',]; 

        foreach ($required as $key) {
            if (!$input->getOption($key)) {
                $errors[] = 'Missing option ' . $key;
            }
        }
        return $errors;
    }
}

di.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
    <arguments>
        <argument name="commands" xsi:type="array">
            <item name="delete_simple_product" xsi:type="object">Sivakumar\Sample\Console\DeleteSimpleProduct</item>
        </argument>
    </arguments>
</type>
</config>

7 Answers 7

23

Agree with Max that you should use the ProductRepositoryInterface::deleteById($sku), but you'll also need to make an additional change to get permissions to delete.

Note that the Admin area handles this by creating the following config in app/code/Magento/Backend/etc/adminhtml/di.xml

    <preference for="Magento\Framework\Model\ActionValidator\RemoveAction" type="Magento\Framework\Model\ActionValidator\RemoveAction\Allowed" />

The Magento\Framework\Model\ActionValidator\RemoveAction\Allowed class prevents a permission check by simply returning true in the isAllowed method.

Without the above change to di.xml the Magento\Framework\Model\ActionValidator\RemoveAction class will be used, which will cause your delete request to fail unless $this->registry->registry('isSecureArea') is set to true.

It looks like you are trying to create some console commands and I'm not very familiar with them yet, so your best bet for now may be to set the registry to allow the delete operation and refactor later if a cleaner solution is found.

$this->registry->register('isSecureArea', true)
2
  • its working fine.i hope i will get some clarity why should i use ProductRepository.meanwhile i will try to search usage of this class in devdocs.
    – sivakumar
    Commented Apr 29, 2015 at 17:21
  • Ideally use https://github.com/magento/magento2/blob/develop/app/code/Magento/Catalog/Api/ProductRepositoryInterface.php since it is a public API and therefore more stable. Commented Apr 29, 2015 at 17:31
11

I recently had this problem while writing a console command to delete empty categories.

As said in another answer you need to register 'isSecureArea' to true.

To do this in a console command you need to have the Magento\Framework\Registry class passed into your constructor.

In my case I did in this way:

public function __construct(CategoryManagementInterface $categoryManagementInterface, CategoryRepositoryInterface $categoryRepositoryInterface, Registry $registry)
{
    $this->_categoryRepository = $categoryRepositoryInterface;
    $this->_categoryManagement = $categoryManagementInterface;
    $registry->register('isSecureArea', true);


    parent::__construct();
}

and then in the execute method I used the repository to perform the actual deletion:

$this->_categoryRepository->deleteByIdentifier($category->getId());

11

if you using script please create the registry object as shown below.

  $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
  $objectManager->get('Magento\Framework\Registry')->register('isSecureArea', true);

Please click here for detailed explanation. http://www.pearlbells.co.uk/mass-delete-magento-2-categories-programmatically/

if it is a one time script, you can use OM

1
  • 1
    Thank Bro, Good job! Commented Nov 7, 2019 at 10:48
5

Expanding on Chris O'Toole's answer. I too need to delete categories from a command, actually from multiple commands. Initially just having

$oRegistry->register('isSecureArea', true);

in one command worked fine, but when I put that in multiple commands (in the constructor) I got this error during compilation

Registry key "isSecureArea" already exists

First checking for the existence of the registry key solved it

if($oRegistry->registry('isSecureArea') === null) {
    $oRegistry->register('isSecureArea', true);
}

I'm not sure if it's bad form to put that in the constructor, but assume that's why the error was encountered. Alternatively, you should be able to get away with running the first snippet from your commands' execute methods. Again, I'm not sure what's considered best practice...

1
  • 2
    \Magento\Framework\Registry::register now also supports a third $graceful command, which suppresses the exception if the key is already set.
    – Simon
    Commented Apr 23, 2021 at 11:28
2

Instead of setting isSecureArea you can also allow to remove a single type of object by overriding type RemoveAction arguments in your di.xml like this:

<type name="Magento\Framework\Model\ActionValidator\RemoveAction">
    <arguments>
        <argument name="protectedModels" xsi:type="array">
            <item name="salesOrder" xsi:type="null" /> <!--allow orders to be removed from front area-->
        </argument>
    </arguments>
</type>
1

For operations with product you must use Repository.

Magento\Catalog\Model\ProductRepository
2
  • 2
    thank you for your response.now i'm getting following error.[Magento\Framework\Exception\StateException] Unable to remove product samsung
    – sivakumar
    Commented Apr 29, 2015 at 14:03
  • @sivakumar same error . have you fixed it? It was long time ago but anyway :D Commented Mar 25, 2020 at 4:46
0

This error could also mean that some required fields are not being submitted. Check in the admin which required fields are expected, and make sure each one is included in the form.

In my case I was not sending the "vat_id", so I added a hidden field:

<input type="hidden" name="vat_id" value="-"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.