Проблема «Код города не установлен» в пользовательских командах CLI в Magento 2


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>

Не могли бы вы показать больше своего кода и дать больше контекста относительно того, что вы пытаетесь сделать?
Натан Тоомбс

Я сталкиваюсь с той же проблемой. Однако приведенное выше решение не работает для меня. Это сбивало с толку меня уже несколько недель.
Стивенлавин

Ответы:


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

Для меня это не работает ( adminили adminhtml) - есть ошибка: Area code already set. Но потом, если я это прокомментирую, снова будет исключение из темы.
Бартош Кубицкий

13
Вы должны использовать \Magento\Framework\App\Area::AREA_*константы вместо жестко закодированных строк
7ochem

3
Лучше не устанавливать код области в вашем конструкторе; всякий раз, когда вы запускаете, bin/magento все конструкторы выполняются, и если код области пытаются установить 2 раза, генерируется исключение. Лучше установить код города в вашем execute()-методе или запустить код в эмуляции магазина или области, если требуется состояние. Также: зависимости конструктора, которые могут инициировать сеанс в цепочке, должны быть инициализированы с использованием фабрики или прокси-сервера, чтобы зависимости не могли установить код города.
Гил Беркерс

1
Пожалуйста, отмените это как правильный ответ. Это создает исключение, когда мы устанавливаем код области в конструкторе.
Сандипан С.

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в __constructкомандах для CLI. При запуске любой команды Magento собирайте и создавайте экземпляр для каждого скрипта, зарегистрированного в вашем приложении. Если есть более одного__construct с определением кода города, у вас будет ошибка.

Я полагаю, лучше использовать execute()метод для установки кода города. Проверьте модуль каталога: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php


1
Имеет смысл для меня. Кто-нибудь еще хочет добавить комментарий по этому поводу?
ermannob

Это правильно, см. Также мой комментарий к принятому ответу: лучше не устанавливать код области в вашем конструкторе; всякий раз, когда вы запускаете, bin/magento все конструкторы выполняются, и если код области пытаются установить 2 раза, генерируется исключение. Лучше установить код города в вашем execute()-методе или запустить код в эмуляции магазина или области, если требуется состояние. Также: зависимости конструктора, которые могут инициировать сеанс в цепочке, должны быть инициализированы с использованием фабрики или прокси-сервера, чтобы зависимости не могли установить код города.
Гил Беркерс

но в Magento 2.2 инъекция \ Magento \ Sales \ Api \ Data \ OrderInterface или \ Magento \ Sales \ Api \ OrderManagementInterface в конструкции командного класса будет вызывать Magento \ Framework \ Session \ SessionManager -> __ construct () и будет заканчиваться областью «не» поставил". Этого не происходит 2.1. потому что module-ui / Config / Reader / Definition / Data введен в 2.2, как мы решаем это?
Дони Вибово

4

для этой проблемы areaCode, если параметр 'frontend' не работает, попробуйте:

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

работал на меня, надеюсь, это поможет


В каком файле я должен добавить этот код? У меня точно такая же проблема.
Ученик Magento

@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

Проблема в том, что у него нет метода, который возвращает 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();
  • $ state = $objectManager->get('Magento\Framework\App\State');
  • $ State-> setAreaCode ( 'глобальный');

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, не могли бы вы объяснить, почему, и дать людям знать наиболее канонический метод решения проблемы?
chrBrd

-1

Попробуйте обновить magento с помощью CLI, чем я обнаружил «код области не определен» для сессии и приложения. Но я не могу найти какой модуль или тему. Поэтому я просто делаю изменения в 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) {
        ...
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.