Magento 2中的自定义CLI命令中的“未设置区域代码”问题


46

通过更新数据时出现以下错误 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                              

以下是我的di.xml档案

<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>

您能否显示更多代码,并提供更多有关尝试执行的操作的信息?
弥敦道(Nathan Toombs)

我遇到了同样的问题。但是,上面显示的解决方案对我不起作用。数周以来,这一直困扰着我。
Stevenlavine '17年

Answers:


63

Magento CLI中未设置该区域(任何核心命令均不需要此区域)。可以在命令execute方法的开头设置它:

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

6
仅供参考,您的“ adminhtml”不适用于我。“管理员”工作。
Phoenix128_RiccardoT

对我来说,它不起作用(adminadminhtml)-出现错误:Area code already set。但是然后,如果我将其注释掉,那么主题又有例外。
Bartosz Kubicki

13
您应该使用\Magento\Framework\App\Area::AREA_*常量而不是硬编码的字符串
7ochem '17

3
最好不要在构造函数中设置区号。无论何时运行,bin/magento 所有构造函数都会执行,并且如果尝试将区域代码设置为2次,则会引发异常。最好在方法中设置区号execute(),或者在需要状态的情况下在商店或区域仿真中运行代码。另外:应该使用工厂或代理初始化可能触发链下会话的构造函数依赖关系,以防止依赖关系设置区号。
Giel Berkers

1
请取消设置为正确答案。当我们在构造函数中设置区号时,它将创建异常。
Sandipan S

33

今天,我再次跌跌撞撞地遇到了这个问题,重要的是要知道,只要链下的依赖项启动了一个需要了解应用程序状态的实例,就会引发该问题。

在许多情况下,此错误是会话绑定的(因为会话需要知道应用程序的状态(前端或adminhtml))。

就我而言,我需要Magento\Tax\Api\TaxCalculationInterface在CLI命令中使用,但这在其依赖链中的某个时刻需要客户会话(可能是为了获得客户组)。

编辑:我发现使用代理更好的解决方案。但是出于历史的考虑,这是我以前的回答:


为了解决这个问题,我没有在构造函数中包含此接口,而是在工厂中使用:

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

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

这样,该类仅在我需要的一个方法中实例化,而不再在构造函数中实例化:

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

在这种情况下,这为我解决了问题。


现在使用代理的答案:

如果您不想触发所有依赖关系,则应在构造函数中使用代理。根据原始文档

...构造函数注入还意味着创建对象时通常会产生对象实例化的连锁反应。

和:

...代理扩展了其他类,使其成为它们的延迟加载版本。也就是说,只有在实际调用该类的方法之一之后,才创建代理扩展的类的真实实例。

因此,在我的情况下,使用TaxCalculationInterface,我要做的就是实例化我的纳税计算作为构造函数中的代理:

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

这样,我的课就被延迟加载了。那就是:它只有在我调用其中一种方法时才实例化。例如:

$rate = $this->taxCalculation->getCalculatedRate($productRateId);

17

您不应该setAreaCode__constructfor CLI命令中使用。当您运行任何命令时,Magento会为您的应用程序中注册的每个脚本收集并创建实例。如果一个以上__construct具有区号定义,则会出现错误。

我想最好使用该execute()方法设置区号。检查目录模块: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php


1
我感觉合理。还有其他人要对此发表评论吗?
ermannob

这是正确的,另请参阅我对已接受答案的评论:最好不要在构造函数中设置区号;每当运行时,bin/magento 所有构造函数都会执行,并且如果尝试将区域代码设置为2次,则会引发异常。最好在方法中设置区号execute(),或者在需要状态的情况下在商店或区域仿真中运行代码。另外:应该使用工厂或代理初始化可能触发链下会话的构造函数依赖关系,以防止依赖关系设置区号。
Giel Berkers

但在Magento 2.2中,在命令类构造中注入\ Magento \ Sales \ Api \ Data \ OrderInterface或\ Magento \ Sales \ Api \ OrderManagementInterface将调用Magento \ Framework \ Session \ SessionManager-> __ construct(),并且最终将“区域不是组”。2.1不会发生。因为在2.2中引入了module-ui / Config / Reader / Definition / Data,我们如何解决这个问题?
Doni Wibowo

4

对于此areaCode问题,如果“ frontend”参数不起作用,请尝试:

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

在为我工作,希望能帮上忙


我应该在哪个文件中添加此代码?我也有完全一样的问题。
Magento Learner

@xxx我在自定义命令中遇到了这个问题,所以我在创建的命令文件中写了这个问题。您可以将其添加到execute函数中,如下所示:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell

4

在大多数情况下,异常是由控制台命令中执行的某些操作引起的。解决方案(而不是设置区号)是模拟区号并使用以下命令执行操作

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

$state的对象在哪里Magento\Framework\App\State?将区域设置在不同的位置是一个问题,因为它可能导致通话之间发生冲突。


我正在使用此参考,并且在控制器中已经设置了类似的错误区号,请您帮我解决这个问题。我进行了更改,例如在我的构造函数中调用setareacode,但出现了相同的错误。
加根


1

问题在于,如果没有设置变量area_code,它没有任何返回false的方法。我发现要解决的方法是通过创建状态类的覆盖并创建一个新方法来验证是否设置了area_code。

在我的文件di.xml中

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

创建广告文件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;
    }
}

采用

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

1

magento 2中,如果您设置AreadCode但仍然出现此错误,请尝试使用以下代码。

  • 采用 Magento\Framework\App\Bootstrap;
  • 包括 app/bootstrap.php;
  • $ bootstrap = Bootstrap::create(BP, $_SERVER);
  • $ objectManager = $bootstrap->getObjectManager();
  • $状态= $objectManager->get('Magento\Framework\App\State');
  • $ state-> setAreaCode('global');

0

bin/magento setup:upgrade从生产导入数据库后,我遇到错误“未设置区域代码”的错误。这种情况与本主题有所不同,但可能会有所帮助。bin/magento deploy:mode:set developer尽管我已经处于开发人员模式,但能够解决本地运行的此问题。Magento做了一些配置调整,特别是对我来说debug_logging发挥了作用。


0

我通过使用代理类获得了解决方案。例子是

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

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

这解决了我的问题


-1

安装升级时,我发现区号存在相同问题。

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

我已禁用所有第三方模块并运行 setup:upgrade

然后,我重新启用了所有第三方模块,并运行相同的命令。问题为我解决了希望这对您有所帮助。


这实际上不是解决方案。它只是将灰尘藏在地毯下。但是反正很好找到。它应该在开发过程中提供帮助,但不会使问题消失。
Marius

谢谢Marius纠正我。我在大多数项目中都发现了同样的情况,这可以帮助我解决此问题。
拉维·亚达夫

@Marius,您是否愿意解释原因,并让人们知道解决该问题的最典型方法?
chrBrd

-1

尝试使用CLI升级magento而不是我发现会话和应用程序的“区域代码未定义”。但是我找不到哪个模块或主题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) {
        ...
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.