Problème de "code régional non défini" dans les commandes CLI personnalisées dans Magento 2

46

Je reçois une erreur de suivi lors de la mise à jour des données via 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                              

Voici mon di.xmldossier

<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.
la source
Pourriez-vous s'il vous plaît montrer plus de votre code et donner plus de contexte à ce que vous essayez de faire?
Nathan Toombs
Je rencontre le même problème. Cependant, la solution présentée ci-dessus ne fonctionne pas pour moi. Cela me laisse perplexe depuis des semaines maintenant.
Stevenlavine

Réponses:

63

La zone n'est pas définie dans la CLI de Magento (elle n'est pas requise pour les commandes principales). Il peut être défini au début de la executeméthode de votre commande :

/** @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
la source
6
Pour votre information, "adminhtml" ne fonctionnait pas pour moi. "admin" a fonctionné.
Phoenix128_RiccardoT
Pour moi , il ne fonctionne pas ( adminou adminhtml) - il y a une erreur: Area code already set. Mais alors, si je le commente là-bas est encore une exception du sujet.
Bartosz Kubicki
13
Vous devriez utiliser des \Magento\Framework\App\Area::AREA_*constantes au lieu de chaînes codées en dur
7ochem
3
Il est préférable de ne pas définir l'indicatif régional dans votre constructeur. chaque fois que vous exécutez bin/magento tous les constructeurs sont exécutés, et si vous tentez de définir le code de zone 2 fois, une exception est levée Il est préférable de définir l'indicatif régional dans votre execute()méthode ou d'exécuter votre code en mode d'émulation magasin ou région si l'état est requis. En outre: les dépendances de constructeur susceptibles de déclencher une session en aval de la chaîne doivent être initialisées à l'aide d'une fabrique ou d'un proxy afin d'empêcher les dépendances de définir un indicatif régional.
Giel Berkers
1
S'il vous plaît désélectionnez-le comme une réponse correcte. Il crée une exception lorsque nous définissons le code de zone dans le constructeur.
Sandipan S
33

Aujourd'hui, je suis encore tombé sur ce problème et il est important de savoir que ce problème est posé chaque fois qu'une dépendance découle d'une instance qui nécessite de connaître l'état de l'application.

Dans de nombreux cas, cette erreur est liée à la session (car la session doit connaître l'état de l'application (frontend ou adminhtml)).

Dans mon cas, je devais avoir Magento\Tax\Api\TaxCalculationInterfaceune commande CLI, mais cela nécessite à un moment de sa chaîne de dépendance la session client (probablement pour obtenir le groupe de clients).

Edit: J'ai trouvé une meilleure solution en utilisant des proxies. Mais pour les histoires, voici ma réponse précédente:


Pour résoudre ce problème, je n'ai pas inclus cette interface dans mon constructeur, mais plutôt son usine:

/**
 * @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 cette façon, la classe n'est instanciée que dans la seule méthode où j'en avais besoin, et non plus dans le constructeur:

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

Cela a résolu le problème pour moi dans ce cas particulier.


Et maintenant la réponse en utilisant un proxy:

Si vous ne voulez pas déclencher toutes les dépendances en aval de la chaîne, vous devez utiliser un proxy dans votre constructeur. Selon la documentation originale :

... l'injection de constructeur signifie également qu'une réaction en chaîne d'instanciation d'objet est souvent le résultat de la création d'un objet.

et:

... Les mandataires étendent les autres classes pour en devenir des versions paresseuses. C'est-à-dire qu'une instance réelle de la classe qu'un proxy étend est créée uniquement après que l'une des méthodes de la classe a été appelée.

Donc, dans ma situation, avec TaxCalculationInterface, tout ce que j'avais à faire était d'instancier mon calcul de taxe comme proxy dans mon constructeur:

/**
 * @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 cette façon, ma classe est paresseuse chargée. C'est-à-dire: il n'est instancié que lorsque j'appelle l'une de ses méthodes. Par exemple:

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

Vous ne devriez pas utiliser setAreaCodedans les __constructcommandes for pour la CLI. Lorsque vous exécutez une commande, Magento collecte et crée une instance pour chaque script enregistré dans votre application. S'il y en a plus d'un __constructavec la définition de l'indicatif régional, vous aurez l'erreur.

Je suppose préférable d'utiliser la execute()méthode pour définir l'indicatif régional. Vérifiez le module de catalogue: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php

Eugene Kovalyov
la source
1
Cela a du sens pour moi. Quelqu'un d'autre veut ajouter un commentaire à ce sujet?
ermannob
C'est correct, voir aussi mon commentaire sur la réponse acceptée: il est préférable de ne pas définir l'indicatif régional dans votre constructeur; chaque fois que vous exécutez bin/magento tous les constructeurs sont exécutés, et si vous tentez de définir l'indicatif régional 2 fois, une exception est levée. Il est préférable de définir l'indicatif régional dans votre execute()méthode ou d'exécuter votre code en mode d'émulation magasin ou région si l'état est requis. En outre: les dépendances de constructeur susceptibles de déclencher une session en aval de la chaîne doivent être initialisées à l'aide d'une fabrique ou d'un proxy afin d'empêcher les dépendances de définir un indicatif régional.
Giel Berkers
mais dans Magento 2.2, l'injection de \ Magento \ Sales \ Api \ Data \ OrderInterface ou de \ Magento \ Sales \ Api \ OrderManagementInterface dans les constructions de classe de commande appellera Magento \ Framework \ Session \ SessionManager -> __ construct () et se terminera par "zone non ensemble". Cela n'arrive pas 2.1. car module-ui / Config / Reader / Definition / Data est introduit en 2.2, comment résoudre ce problème?
Doni Wibowo le
4

pour ce problème areaCode, si le paramètre 'frontend' ne fonctionne pas, essayez:

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

travaillait pour moi, espérons que cela aide

DependencyHell
la source
Dans quel fichier dois-je ajouter ce code? J ai exactement le même problème.
Magento Learner
@xxx J'ai eu ce problème avec une commande personnalisée, je l'ai donc écrit dans le fichier de commande que j'ai créé. Vous pouvez l'ajouter à la fonction execute, avec quelque chose comme:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell
4

Dans la plupart des cas, l'exception est causée par certaines actions effectuées dans la commande console. La solution (au lieu de définir l'indicatif régional) consiste à émuler l'indicatif régional et à exécuter l'action à l'aide de

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

$stateest l'objet de Magento\Framework\App\State. Il est difficile de définir une zone à un endroit différent, car cela peut entraîner des conflits entre les appels.

Bartosz Kubicki
la source
J'utilise cette référence et j'obtiens l'erreur similaire. L'indicatif régional est déjà défini dans mon contrôleur. Pouvez-vous m'aider à sortir de là? J'ai apporté des modifications, par exemple en appelant setareacode dans ma fonction de construction mais en obtenant la même erreur.
Gagan
1

Le problème est qu’il n’a pas de méthode qui retourne false si la variable area_code n’a pas été définie. La solution que j'ai trouvée était de créer un remplacement de la classe d'état et de créer une nouvelle méthode pour valider si le code de zone était défini.

Dans mon fichier di.xml

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

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

Utilisation

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

Dans magento 2, si vous définissez AreadCode mais obtenez quand même cette erreur, veuillez essayer le code suivant.

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

Je souffrais de l'erreur 'L'indicatif régional n'est pas défini' en cours d'exécution bin/magento setup:upgradeaprès l'importation de la base de données de la production. C'est un cas un peu différent de ce sujet, mais peut-être aidera quelqu'un. J'ai pu résoudre ce problème en exécutant localement bin/magento deploy:mode:set developeralors que j'étais déjà en mode développeur. Magento a fait quelques ajustements de configuration, spécialement pour moi debug_logging a joué un rôle.

Artem Klimoff
la source
0

J'ai eu la solution en utilisant la classe proxy. Exemple est

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

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

Cela a résolu mon problème

Tejas Vyas
la source
-1

J'ai trouvé le même problème avec l'indicatif régional lors de la mise à niveau de l'installation.

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

J'ai désactivé tous les modules tiers et je cours setup:upgrade

Ensuite, j'ai réactivé tous les modules tiers et exécuté la même commande. Le problème est résolu pour moi J'espère que ceci est une aide pour vous.

Ravi Yadav
la source
ce n'est pas vraiment une solution. Il ne fait que cacher la poussière sous le tapis. Mais bonne trouvaille quand même. Cela devrait aider pendant le processus de développement, mais cela ne fera pas disparaître le problème.
Marius
Merci Marius de m'avoir corrigé. J'ai trouvé le même cas dans la plupart de mon projet et cela m'aide à résoudre ce problème.
Ravi yadav
@Marius, voudriez-vous expliquer pourquoi et informer les gens de la méthode la plus canonique pour résoudre le problème?
chrBrd
-1

Essayez de mettre à niveau magento à l’aide de la CLI que je trouve "code régional non défini" pour session et application. Mais je ne trouve pas quel module ou thème 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
la source