Problema de 'Código de área no establecido' en comandos personalizados de CLI en Magento 2

46

Recibo el siguiente error al actualizar los datos a través 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                              

Siguiente es mi di.xmlarchivo

<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.
fuente
¿Podría mostrar más de su código y dar más contexto sobre lo que está tratando de hacer?
Nathan Toombs
Me encuentro con el mismo problema. Sin embargo, la solución que se muestra arriba no funciona para mí. Esto me ha estado desconcertando durante semanas.
Stevenlavine

Respuestas:

63

El área no está configurada en Magento CLI (no es necesario para ningún comando central). Se puede configurar al comienzo del executemétodo de su 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
fuente
66
FYI, tu "adminhtml" no estaba funcionando para mí. "admin" funcionó.
Phoenix128_RiccardoT
Para mí que no funciona ( admino adminhtml) - hay un error: Area code already set. Pero luego, si lo comento, hay una excepción del tema nuevamente.
Bartosz Kubicki
13
Debe usar \Magento\Framework\App\Area::AREA_*constantes en lugar de cadenas codificadas
7ochem
3
Es mejor no establecer el código de área en su constructor; cada vez que ejecuta bin/magento todos los constructores se ejecutan, y si se intenta establecer el código de área 2 veces, se genera una excepción. Es mejor establecer el código de área en su execute()método, o ejecutar su código en la tienda o emulación de área si se requiere un estado. Además: las dependencias del constructor que podrían desencadenar una sesión en la cadena deben inicializarse utilizando una fábrica o un proxy para evitar que las dependencias establezcan un código de área.
Giel Berkers
1
Desactívelo como una respuesta correcta. Crea una excepción cuando establecemos el código de área en el constructor.
Sandipan S
33

Hoy he vuelto a tropezar con este problema y es importante saber que este problema se produce cada vez que una dependencia en la cadena inicia una instancia que necesita conocer el estado de la aplicación.

En muchos casos, este error está vinculado a la sesión (ya que la sesión necesita conocer el estado de la aplicación (frontend o adminhtml)).

En mi caso, necesitaba tener Magento\Tax\Api\TaxCalculationInterfaceun comando CLI, pero esto requiere en algún momento de su cadena de dependencia la sesión del cliente (probablemente para obtener el grupo de clientes).

Editar: encontré una mejor solución usando proxies. Pero por el bien de las historias, aquí está mi respuesta anterior:


Para resolver esto, no incluí esta interfaz en mi constructor, sino que es de 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;
}

De esta manera, la clase solo se instancia en el método donde lo necesitaba, y ya no en el constructor:

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

Esto resolvió el problema para mí en este caso particular.


Y ahora la respuesta usando un proxy:

Si no desea activar todas las dependencias en la cadena, debe usar un proxy en su constructor. Según la documentación original :

... la inyección del constructor también significa que una reacción en cadena de creación de instancias de objeto es a menudo el resultado cuando se crea un objeto.

y:

... Los proxies extienden otras clases para convertirse en versiones perezosas de ellos. Es decir, una instancia real de la clase que un proxy extiende, creada solo después de que se llame a uno de los métodos de la clase.

Entonces, en mi situación, con el TaxCalculationInterface, todo lo que tenía que hacer era instanciar mi cálculo de impuestos como proxy en mi constructor:

/**
 * @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;
}

De esta manera, mi clase está perezosa. Es decir: solo se crea una instancia tan pronto como llamo a uno de sus métodos. Por ejemplo:

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

No debe usar setAreaCodeen los __constructcomandos para CLI. Cuando ejecuta cualquier comando, Magento recopila y crea instancias para cada script registrado en su aplicación. Si hay más de uno __constructcon la definición del código de área, tendrá el error.

Supongo que es mejor usar el execute()método para establecer el código de área. Consulte el módulo del catálogo: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php

Eugene Kovalyov
fuente
1
Tiene sentido para mi. ¿Alguien más quiere agregar un comentario sobre esto?
ermannob
Esto es correcto, vea también mi comentario sobre la respuesta aceptada: es mejor no establecer el código de área en su constructor; cada vez que ejecuta bin/magento todos los constructores se ejecutan, y si se intenta establecer el código de área 2 veces, se genera una excepción. Es mejor establecer el código de área en su execute()método, o ejecutar su código en la tienda o emulación de área si se requiere un estado. Además: las dependencias del constructor que podrían desencadenar una sesión en la cadena deben inicializarse utilizando una fábrica o un proxy para evitar que las dependencias establezcan un código de área.
Giel Berkers
pero en Magento 2.2, la inyección de \ Magento \ Sales \ Api \ Data \ OrderInterface o \ Magento \ Sales \ Api \ OrderManagementInterface en construcciones de clase de comando llamará a Magento \ Framework \ Session \ SessionManager -> __ construct () y terminará "área no conjunto". Esto no sucede 2.1. porque module-ui / Config / Reader / Definition / Data se introduce en 2.2 ¿cómo resolvemos esto?
Doni Wibowo
4

para este problema de areaCode, si el parámetro 'frontend' no funciona, intente:

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

estaba trabajando para mí, espero que ayude

Dependencia
fuente
¿En qué archivo debo agregar este código? Tengo exactamente el mismo problema.
Magento Learner
@xxx Tuve este problema con un comando personalizado, así que escribí esto en el archivo de comando que creé. Puede agregarlo en la función de ejecución, con algo como:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell
4

En la mayoría de los casos, la excepción es causada por algunas acciones realizadas en el comando de la consola. La solución (en lugar de configurar el código de área) es emular el código de área y realizar acciones usando

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

donde $statees objeto de Magento\Framework\App\State. Establecer el área en un lugar diferente es un problema, ya que puede causar conflictos entre las llamadas.

Bartosz Kubicki
fuente
Estoy usando esta referencia y obtengo el error similar El código de área ya está configurado en mi controlador, ¿pueden ayudarme a salir de esto? He realizado cambios como, llamando a setareacode en mi función de construcción pero obteniendo el mismo error.
Gagan
1

El problema es que no tiene ningún método que devuelva falso si la variable area_code no se ha establecido. La forma en que lo resolví fue creando una anulación de la clase de estado y creando un nuevo método para validar si se configuró el area_code.

En mi archivo di.xml

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

Archivo 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;
    }
}

Utilizar

/**
* @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
fuente
1

En magento 2, si configura AreadCode pero aún recibe este error, intente seguir el código.

  • Utilizar Magento\Framework\App\Bootstrap;
  • incluir app/bootstrap.php;
  • $ bootstrap = Bootstrap::create(BP, $_SERVER);
  • $ objectManager = $bootstrap->getObjectManager();
  • $ estado = $objectManager->get('Magento\Framework\App\State');
  • $ state-> setAreaCode ('global');
Rakesh Prajapati
fuente
0

Estaba sufriendo el error 'El código de área no está configurado' ejecutándose bin/magento setup:upgradedespués de importar la base de datos de producción. Es un caso un poco diferente al de este tema, pero quizás ayude a alguien. Pude resolver este problema a nivel local a bin/magento deploy:mode:set developerpesar de que ya estaba en modo desarrollador. Magento hizo algunos ajustes de configuración, especialmente para mí debug_logging desempeñado papel.

Artem Klimoff
fuente
0

Obtuve la solución usando la clase proxy. Ejemplo es

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

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

Esto solucionó mi problema

Tejas Vyas
fuente
-1

He encontrado el mismo problema con el código de área durante la actualización de la configuración.

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

He desactivado todos los módulos de terceros y ejecuto setup:upgrade

Luego he vuelto a habilitar todos los módulos de terceros y ejecuto el mismo comando. El problema está resuelto para mí Espero que esto sea de ayuda para ti.

Ravi yadav
fuente
Esto no es realmente una solución. Es solo esconder la suciedad debajo de la alfombra. Pero buen hallazgo de todos modos. Debería ayudar durante el proceso de desarrollo, pero no hace que el problema desaparezca.
Marius
Gracias Marius por corregirme. He encontrado el mismo caso en la mayoría de mi proyecto y esto me ayuda a resolverlo.
Ravi yadav el
@ Mario, ¿te gustaría explicar por qué y dejar que la gente conozca el método más canónico para resolver el problema?
chrBrd
-1

Intente actualizar magento usando CLI que encontré 'código de área no definido' para sesión y aplicación. Pero no puedo encontrar qué módulo o tema. Así que solo hago los cambios a continuación en el vendor/magento/framework/App/State.phparchivo y está funcionando.

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