Problema 'Código de área não definido' em comandos CLI personalizados no Magento 2

46

Estou recebendo o seguinte erro ao atualizar os dados por meio de CustomerRepositoryInterface

[Magento\Framework\Exception\SessionException]  
Area code not set: Area code must be set before starting a session.

[Magento\Framework\Exception\LocalizedException]  
Area code is not set                              

A seguir está o meu di.xmlarquivo

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="test1_command" xsi:type="object">Test\Module\Console\Command\Test1Command</item>
                <item name="test2_command" xsi:type="object">Test\Module\Console\Command\Test2Command</item>
            </argument>
        </arguments>
    </type>
</config>
SK.
fonte
Você poderia mostrar mais do seu código e fornecer mais contexto sobre o que você está tentando fazer?
Nathan Toombs
Estou encontrando o mesmo problema. No entanto, a solução mostrada acima não funciona para mim. Isso me deixa perplexo há semanas.
Stevenlavine 4/07

Respostas:

63

A área não está definida no Magento CLI (não é necessária para nenhum comando principal). Pode ser definido no início do executemétodo do seu comando :

/** @var \Magento\Framework\App\State **/
private $state;

public function __construct(\Magento\Framework\App\State $state) {
    $this->state = $state;
    parent::__construct();
}

public function execute() {
    $this->state->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND); // or \Magento\Framework\App\Area::AREA_ADMINHTML, depending on your needs
}
Alex Paliarush
fonte
6
Para sua informação, você "adminhtml" não estava funcionando para mim. "admin" funcionou.
Phoenix128_RiccardoT
Para mim isso não funciona ( adminou adminhtml) - há um erro: Area code already set. Mas então, se eu comentar, há uma exceção de assunto novamente.
Bartosz Kubicki
13
Você deve usar \Magento\Framework\App\Area::AREA_*constantes em vez de cordas hardcoded
7ochem
3
É melhor não definir o código de área no seu construtor; sempre que você executar, bin/magento todos os construtores são executados e se o código de área for definido duas vezes, uma exceção será lançada. É melhor definir o código de área no seu execute()método, ou executar o código na emulação de loja ou área, se o estado for necessário. Além disso, as dependências do construtor que podem acionar uma sessão na cadeia devem ser inicializadas usando uma fábrica ou um proxy para impedir que as dependências definam um código de área.
Giel Berkers #
1
Desative-o como uma resposta correta. Cria exceção quando definimos o código de área no construtor.
precisa
33

Eu me deparei com esse problema novamente hoje e é importante saber que esse problema é gerado sempre que uma dependência na cadeia inicia uma instância que precisa conhecer o estado do aplicativo.

Em muitos casos, esse erro é vinculado à sessão (já que a sessão precisa conhecer o estado do aplicativo (frontend ou adminhtml)).

No meu caso, eu precisava ter Magento\Tax\Api\TaxCalculationInterfaceum comando da CLI, mas isso requer em algum momento da cadeia de dependência a sessão do cliente (provavelmente para obter o grupo de clientes).

Edit: Encontrei uma solução melhor usando proxies. Mas, pelo bem das histórias, aqui está a minha resposta anterior:


Para resolver isso, não incluí essa interface no meu construtor, mas a fábrica:

/**
 * @var \Magento\Tax\Api\TaxCalculationInterfaceFactory
 */
protected $taxCalculationFactory;

/**
 * @param \Magento\Tax\Api\TaxCalculationInterfaceFactory $taxCalculationFactory
 */
public function __construct(
    \Magento\Tax\Api\TaxCalculationInterfaceFactory $taxCalculationFactory
) {
    $this->taxCalculationFactory = $taxCalculationFactory;
}

Dessa maneira, a classe é instanciada apenas no método em que eu precisei e não no construtor:

$taxCalculation = $this->taxCalculationFactory->create();

Isso resolveu o problema para mim neste caso específico.


E agora a resposta usando um proxy:

Se você não deseja acionar todas as dependências da cadeia, use um proxy em seu construtor. De acordo com a documentação original :

... injeção de construtor também significa que uma reação em cadeia de instanciação de objeto geralmente é o resultado quando você cria um objeto.

e:

... Os proxies estendem outras classes para se tornarem versões preguiçosas deles. Ou seja, uma instância real da classe que um proxy estende criada apenas depois que um dos métodos da classe é realmente chamado.

Portanto, na minha situação, com o TaxCalculationInterface, tudo o que eu precisava fazer era instanciar meu cálculo de imposto como proxy no meu construtor:

/**
 * @var \Magento\Tax\Api\TaxCalculationInterface\Proxy
 */
protected $taxCalculation;

/**
 * @param \Magento\Tax\Api\TaxCalculationInterface\Proxy $taxCalculation
 */
public function __construct(
    \Magento\Tax\Api\TaxCalculationInterface\Proxy $taxCalculation
) {
    $this->taxCalculation = $taxCalculation;
}

Dessa forma, minha turma é carregada preguiçosamente. Ou seja: só é instanciado assim que eu chamo um de seus métodos. Por exemplo:

$rate = $this->taxCalculation->getCalculatedRate($productRateId);
Giel Berkers
fonte
17

Você não deve usar setAreaCodeos __constructcomandos for CLI. Quando você executa qualquer comando, o Magento coleta e cria uma instância para cada script registrado no seu aplicativo. Se houver mais de um __constructcom definição de código de área, você terá o erro.

Suponho que seja melhor usar o execute()método para definir o código de área. Verifique o módulo do catálogo: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php

Eugene Kovalyov
fonte
1
Faz sentido para mim. Alguém mais quer adicionar um comentário sobre isso?
ermannob
Isso está correto, veja também meu comentário sobre a resposta aceita: É melhor não definir o código de área no seu construtor; sempre que você executar, bin/magento todos os construtores são executados e se o código de área for definido duas vezes, uma exceção será lançada. É melhor definir o código de área no seu execute()método, ou executar o código na emulação de loja ou área, se o estado for necessário. Além disso, as dependências do construtor que podem acionar uma sessão na cadeia devem ser inicializadas usando uma fábrica ou um proxy para impedir que as dependências definam um código de área.
Giel Berkers #
mas no Magento 2.2, injetar \ Magento \ Sales \ Api \ Data \ OrderInterface ou \ Magento \ Sales \ Api \ OrderManagementInterface em construções de classe de comando chamará Magento \ Framework \ Session \ Session \ SessionManager -> __ construct () e acabará "na área não conjunto". Isso não acontece 2.1. porque module-ui / Config / Reader / Definition / Data é introduzido no 2.2, como podemos resolver isso?
Doni Wibowo 15/01
4

para este problema areaCode, se o parâmetro 'frontend' não estiver funcionando, tente:

$this->_state->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);

estava trabalhando para mim, espero que ajude

DependencyHell
fonte
Em qual arquivo devo adicionar esse código? Eu tenho exatamente o mesmo problema.
Magento Learner
@xxx Eu tive esse problema com um comando personalizado, então escrevi isso no arquivo de comando que criei. Você pode adicioná-lo na função de executar, com algo como:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell
4

Na maioria dos casos, a exceção é causada por algumas ações executadas no comando do console. A solução (em vez de definir o código de área) é emular o código de área e executar uma ação usando

$this->state->emulateAreaCode(Area::AREA_ADMINHTML, [$this, 'someAction'], []);

de onde $stateé objeto Magento\Framework\App\State. Definir a área em um local diferente é um problema, pois pode causar conflitos entre as chamadas.

Bartosz Kubicki
fonte
Estou usando esta referência e obtendo o erro semelhante O código de área já está definido no meu controlador. Você pode me ajudar a sair dessa. Fiz alterações como chamar setareacode na minha função de construção, mas obtendo o mesmo erro.
Gagan
1

O problema é que ele não possui nenhum método que retorne false se a variável area_code não tiver sido configurada. A maneira que eu encontrei para resolver foi criando a substituição da classe state e criando um novo método para validar se o area_code foi definido.

No meu arquivo di.xml

    <preference for="Magento\Framework\App\State" type="Webjump\Abacos\App\State" />

Arquivo Createad Webjump \ Abacos \ App \ State

namespace Webjump\Abacos\App;

class State extends \Magento\Framework\App\State
{
    public function validateAreaCode()
    {
        if (!isset($this->_areaCode)) {
            return false;
        }
        return true;
    }
}

Usar

/**
* @var \Magento\Framework\App\State
*/
protected $state;

public function __construct(
            \Magento\Framework\App\State $state
)
{
$this->state = $state;
if (!$this->state->validateAreaCode()) {
 $this->state->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML);
}
}
Luan Alves
fonte
1

No magento 2, se você definir o AreadCode, mas ainda assim receber esse erro, tente o código a seguir.

  • Usar Magento\Framework\App\Bootstrap;
  • incluir app/bootstrap.php;
  • $ bootstrap = Bootstrap::create(BP, $_SERVER);
  • $ objectManager = $bootstrap->getObjectManager();
  • $ state = $objectManager->get('Magento\Framework\App\State');
  • $ state-> setAreaCode ('global');
rakesh prajapati
fonte
0

Eu estava com o erro 'Código de área não está definido' em execução bin/magento setup:upgradeapós importar o banco de dados da produção. É um caso um pouco diferente do assunto deste tópico, mas talvez ajude alguém. Consegui resolver esse problema em execução local, bin/magento deploy:mode:set developerapesar de já estar no modo de desenvolvedor. O Magento fez alguns ajustes na configuração, especialmente para mim, o debug_logging desempenhou um papel.

Artem Klimoff
fonte
0

Eu obtive a solução usando a classe proxy. Exemplo é

use Klevu\Search\Model\Product\MagentoProductActionsInterface\Proxy as MagentoProductActionsInterface;

public function __construct(
        MagentoProductActionsInterface $magentoProductActionsInterface
    )
    {
        $this->_magentoProductActionsInterface = $magentoProductActionsInterface;
        parent::__construct();
    }

Isso corrigiu meu problema

Tejas Vyas
fonte
-1

Encontrei o mesmo problema com o código de área durante a atualização da instalação.

Module 'Magento_WebsiteRestriction':Installing data... Area code not set: Area code must be set before starting a session

Desativei todos os módulos de terceiros e executei setup:upgrade

Em seguida, reativei todos os módulos de terceiros e execute o mesmo comando. Problema resolvido para mim Espero que seja de ajuda para você.

Ravi yadav
fonte
isso não é realmente uma solução. Está apenas escondendo a sujeira debaixo do tapete. Mas é bom encontrar assim mesmo. Deve ajudar durante o processo de desenvolvimento, mas não faz o problema desaparecer.
Marius
Obrigado Marius por me corrigir. Eu encontrei o mesmo caso na maior parte do meu projeto e isso me ajuda a resolver isso.
Ravi yadav
@Marius, gostaria de explicar o porquê e informar às pessoas o método mais canônico para resolver o problema?
precisa
-1

Tente atualizar o magento usando o CLI do que encontrei 'código de área não define' para a sessão e o aplicativo. Mas não consigo encontrar qual módulo ou tema vendor/magento/framework/App/State.php.

public function __construct(
    \Magento\Framework\Config\ScopeInterface $configScope,
    $mode = self::MODE_DEFAULT
) {
    $this->_areaCode = Area::AREA_GLOBAL;
    $this->_configScope = $configScope;
    switch ($mode) {
        ...
    }
}
himansu
fonte