Problem „Nie ustawiono kodu obszaru” w niestandardowych komendach CLI w Magento 2

46

Podczas aktualizacji danych pojawia się błąd 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                              

Oto mój di.xmlplik

<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.
źródło
Czy mógłbyś pokazać więcej swojego kodu i dać więcej kontekstu, co próbujesz zrobić?
Nathan Toombs
Mam ten sam problem. Jednak pokazane powyżej rozwiązanie nie działa dla mnie. To mnie denerwuje od tygodni.
Stevenlavine

Odpowiedzi:

63

Obszar nie jest ustawiony w Magento CLI (nie jest wymagany dla żadnych podstawowych poleceń). Można go ustawić na początku executemetody polecenia :

/** @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
źródło
6
Do Twojej wiadomości „adminhtml” nie działał dla mnie. „admin” działał.
Phoenix128_RiccardoT
Dla mnie to nie działa ( adminlub adminhtml) - wystąpił błąd: Area code already set. Ale jeśli to skomentuję, będzie wyjątek od tematu.
Bartosz Kubicki
13
Powinieneś używać \Magento\Framework\App\Area::AREA_*stałych zamiast ciągów zakodowanych na stałe
7ochem
3
Najlepiej nie ustawiać kodu obszaru w swoim konstruktorze; przy każdym uruchomieniu bin/magento wszystkie konstruktory są wykonywane i jeśli próbujesz ustawić kod obszaru 2 razy, zgłaszany jest wyjątek. Lepiej ustawić kod obszaru w execute()metodzie lub uruchomić kod w emulacji sklepu lub obszaru, jeśli wymagany jest stan. Ponadto: zależności konstruktora, które mogą wyzwalać sesję w dół łańcucha, należy zainicjować za pomocą fabryki lub serwera proxy, aby zapobiec ustawianiu kodu obszaru przez zależności.
Giel Berkers
1
Proszę odznaczyć to jako poprawną odpowiedź. Tworzy wyjątek, gdy ustawiamy kod obszaru w konstruktorze.
Sandipan S
33

Znowu natknąłem się na ten problem dzisiaj i ważne jest, aby wiedzieć, że ten problem jest zgłaszany, ilekroć zależność w dół łańcucha inicjuje instancję, która musi znać stan aplikacji.

W wielu przypadkach błąd ten jest związany z sesją (ponieważ sesja musi znać stan aplikacji (frontend lub adminhtml)).

W moim przypadku musiałem mieć Magento\Tax\Api\TaxCalculationInterfacekomendę CLI, ale wymaga to w pewnym momencie łańcucha zależności sesji klienta (prawdopodobnie w celu uzyskania grupy klientów).

Edycja: Znalazłem lepsze rozwiązanie przy użyciu serwerów proxy. Ale ze względu na historię, oto moja poprzednia odpowiedź:


Aby rozwiązać ten problem, nie dodałem tego interfejsu do mojego konstruktora, ale raczej jest on fabryczny:

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

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

W ten sposób klasa jest tworzona tylko w jednej metodzie, w której jej potrzebowałem, a nie w konstruktorze:

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

To rozwiązało problem w tym konkretnym przypadku.


A teraz odpowiedź za pomocą proxy:

Jeśli nie chcesz wyzwalać wszystkich zależności w dół łańcucha, powinieneś użyć proxy w swoim konstruktorze. Według oryginalnej dokumentacji :

... wstrzyknięcie konstruktora oznacza również, że reakcja łańcuchowa tworzenia instancji obiektu jest często wynikiem tworzenia obiektu.

i:

... Proxy rozszerzają inne klasy, by stały się ich leniwymi wersjami. Oznacza to, że rzeczywista instancja klasy, którą rozszerza serwer proxy, tworzona tylko po wywołaniu jednej z metod klasy.

Więc w mojej sytuacji, jedyne TaxCalculationInterface, co musiałem zrobić, to utworzyć kalkulację podatkową jako przybliżenie w moim konstruktorze:

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

W ten sposób moja klasa jest leniwie załadowana. To znaczy: jest on tworzony tylko wtedy, gdy wywołam jedną z jego metod. Na przykład:

$rate = $this->taxCalculation->getCalculatedRate($productRateId);
Giel Berkers
źródło
17

Nie należy używać setAreaCodew poleceniach __constructfor CLI. Po uruchomieniu dowolnego polecenia Magento zbiera i tworzy instancję dla każdego skryptu zarejestrowanego w aplikacji. Jeśli jest więcej niż jeden __constructz definicją numeru kierunkowego, wystąpi błąd.

Przypuszczam, że lepiej użyć tej execute()metody do ustawienia kodu kierunkowego. Sprawdź moduł katalogu: vendor/magento/module-catalog/Console/Command/ImagesResizeCommand.php

Eugene Kovalyov
źródło
1
Dla mnie to ma sens. Czy ktoś jeszcze chce dodać komentarz na ten temat?
ermannob
Jest to poprawne, patrz także mój komentarz do zaakceptowanej odpowiedzi: Najlepiej nie ustawiać kodu obszaru w swoim konstruktorze; przy każdym uruchomieniu bin/magento wszystkie konstruktory są wykonywane i jeśli próbujesz ustawić kod obszaru 2 razy, zgłaszany jest wyjątek. Lepiej ustawić kod obszaru w execute()metodzie lub uruchomić kod w emulacji sklepu lub obszaru, jeśli wymagany jest stan. Ponadto: zależności konstruktora, które mogą wyzwalać sesję w dół łańcucha, należy zainicjować za pomocą fabryki lub serwera proxy, aby zapobiec ustawianiu kodu obszaru przez zależności.
Giel Berkers
ale w Magento 2.2 wstrzyknięcie \ Magento \ Sales \ Api \ Data \ OrderInterface lub \ Magento \ Sales \ Api \ OrderManagementInterface w konstrukcjach klas poleceń wywoła Magento \ Framework \ Session \ SessionManager -> __ construct () i zakończy się "obszarem nie zestaw". Tak się nie dzieje 2.1. ponieważ moduł-ui / Config / Reader / Definition / Data jest wprowadzony w 2.2, jak to rozwiązać?
Doni Wibowo
4

w przypadku tego kodu areaCode, jeśli parametr „frontend” nie działa, spróbuj:

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

pracował dla mnie, mam nadzieję, że to pomaga

DependencyHell
źródło
W jakim pliku powinienem dodać ten kod? Mam dokładnie ten sam problem.
Magento Learner,
@xxx Miałem ten problem z polecenia niestandardowego, więc napisałem to w utworzonym pliku poleceń. Możesz dodać go do funkcji wykonywania za pomocą czegoś takiego:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell
4

W większości przypadków wyjątek jest spowodowany niektórymi czynnościami wykonywanymi w poleceniu konsoli. Rozwiązaniem (zamiast ustawiania numeru kierunkowego) jest emulacja numeru kierunkowego i wykonywanie akcji za pomocą

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

gdzie $statejest przedmiotem Magento\Framework\App\State. Ustawienie obszaru w innym miejscu jest problemem, ponieważ może powodować konflikt między połączeniami.

Bartosz Kubicki
źródło
Korzystam z tego odniesienia i otrzymuję podobny błąd Kod obszaru jest już ustawiony w moim kontrolerze, czy możesz mi pomóc wydostać się z tego. Wprowadziłem zmiany, takie jak wywołanie setareacode w mojej funkcji konstrukcyjnej, ale otrzymałem ten sam błąd.
Gagan
1

Problem polega na tym, że nie ma żadnej metody, która zwraca false, jeśli zmienna kod_pola nie została ustawiona. Sposób, w jaki znalazłem to rozwiązanie, polegał na utworzeniu zastąpienia klasy stanu i utworzeniu nowej metody sprawdzania poprawności, jeśli został ustawiony kod_pola.

W moim pliku di.xml

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

Utwórz plik 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;
    }
}

Posługiwać się

/**
* @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
źródło
1

W Magento 2, jeśli ustawisz AreadCode, ale nadal pojawia się ten błąd, spróbuj wykonać następujący kod.

  • Posługiwać się Magento\Framework\App\Bootstrap;
  • zawierać app/bootstrap.php;
  • $ bootstrap = Bootstrap::create(BP, $_SERVER);
  • $ objectManager = $bootstrap->getObjectManager();
  • Stan $ = $objectManager->get('Magento\Framework\App\State');
  • $ state-> setAreaCode ('global');
rakesh prajapati
źródło
0

Wystąpił błąd „Kod obszaru nie jest ustawiony” uruchomiony bin/magento setup:upgradepo importowaniu bazy danych z produkcji. To trochę inna sprawa niż ten temat, ale może komuś pomoże. Byłem w stanie rozwiązać ten problem działający lokalnie, bin/magento deploy:mode:set developermimo że byłem już w trybie programisty. Magento dokonało pewnych modyfikacji konfiguracji, specjalnie dla mnie odegrała rolę debug_logging.

Artem Klimoff
źródło
0

Mam rozwiązanie za pomocą klasy proxy. Przykładem jest

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

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

To naprawiło mój problem

Tejas Vyas
źródło
-1

Znalazłem ten sam problem z numerem kierunkowym podczas aktualizacji instalacji.

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

Wyłączyłem wszystkie moduły stron trzecich i uruchomiłem setup:upgrade

Następnie ponownie włączyłem wszystkie moduły innych firm i uruchomiłem to samo polecenie. Problem został dla mnie rozwiązany. Mam nadzieję, że to jest pomoc dla ciebie.

Ravi yadav
źródło
to nie jest rozwiązanie. Po prostu chowa brud pod dywanikiem. Ale i tak dobre znalezisko. Powinno to pomóc w procesie rozwoju, ale nie rozwiązuje problemu.
Marius
Dziękuję Marius za poprawienie mnie. Znalazłem ten sam przypadek w większości moich projektów i to pomaga mi rozwiązać ten problem.
Ravi yadav
@Marius, czy zechciałbyś wyjaśnić, dlaczego i dać ludziom znać najbardziej kanoniczną metodę rozwiązania problemu?
chrBrd
-1

Spróbuj zaktualizować Magento przy użyciu interfejsu CLI, niż znalazłem „numer kierunkowy nie definiuje” dla sesji i aplikacji, ale nie mogę znaleźć modułu lub motywu, więc po prostu wykonuję poniższe zmiany w vendor/magento/framework/App/State.phppliku i działa.

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