Проблема «Код города не установлен» в пользовательских командах 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);

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

DependencyHell
источник
В каком файле я должен добавить этот код? У меня точно такая же проблема.
Ученик 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) {
        ...
    }
}
himansu
источник