ปัญหา 'ไม่ได้ตั้งรหัสพื้นที่' ในคำสั่ง 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>

คุณช่วยแสดงรหัสของคุณให้มากขึ้นและให้บริบทเพิ่มเติมกับสิ่งที่คุณพยายามทำได้หรือไม่?
Nathan Toombs

ฉันกำลังประสบปัญหาเดียวกัน อย่างไรก็ตามวิธีแก้ปัญหาที่แสดงด้านบนไม่ได้ผลสำหรับฉัน สิ่งนี้ทำให้ฉันงุนงงมาหลายสัปดาห์แล้ว
Stevenlavine

คำตอบ:


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
FYI คุณ "adminhtml" ไม่ทำงานสำหรับฉัน "admin" ทำงานแล้ว
Phoenix128_RiccardoT

สำหรับฉันมันไม่ทำงาน ( adminหรือadminhtml) - Area code already setมีข้อผิดพลาด: แต่ถ้าฉันแสดงความคิดเห็นมันมีข้อยกเว้นจากเรื่องอีกครั้ง
Bartosz Kubicki

13
คุณควรใช้\Magento\Framework\App\Area::AREA_*ค่าคงที่แทนสตริง hardcoded
7ochem

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ใน__constructคำสั่ง CLI เมื่อคุณเรียกใช้คำสั่งใด ๆ วีโอไอพีจะรวบรวมและสร้างอินสแตนซ์สำหรับแต่ละสคริปต์ที่ลงทะเบียนในแอปพลิเคชันของคุณ หากมีมากกว่าหนึ่งรายการที่__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 -> __ สร้าง () และจะจบลง "พื้นที่ไม่ ชุด" สิ่งนี้จะไม่เกิดขึ้น 2.1 เนื่องจาก module-ui / Config / Reader / Definition / Data ถูกนำมาใช้ใน 2.2 เราจะแก้ปัญหานี้ได้อย่างไร?
Doni Wibowo

4

สำหรับปัญหาพื้นที่รหัสนี้หากพารามิเตอร์ 'ส่วนหน้า' ไม่ทำงานให้ลอง:

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

ทำงานให้ฉันหวังว่าจะช่วยได้


ฉันควรเพิ่มรหัสนี้ในไฟล์ใด ฉันมีปัญหาเดียวกันทั้งหมด
วีโอไอพีเรียนที่

@xxx ฉันมีปัญหานี้จากคำสั่งที่กำหนดเองดังนั้นฉันจึงเขียนสิ่งนี้ในไฟล์คำสั่งที่ฉันสร้างขึ้น คุณสามารถเพิ่มมันในฟังก์ชั่นการดำเนินการโดยมีบางสิ่งเช่น:try { $this->_state->... } finally { $this->executeMyCommand() }
DependencyHell

4

ในกรณีส่วนใหญ่ข้อยกเว้นเกิดจากการกระทำบางอย่างในคอนโซลคำสั่ง โซลูชัน (แทนการตั้งค่ารหัสพื้นที่) คือเลียนแบบรหัสพื้นที่และดำเนินการโดยใช้

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

ที่เป็นวัตถุของ$state Magento\Framework\App\Stateการตั้งค่าพื้นที่ต่าง ๆ เป็นปัญหาเพราะอาจทำให้เกิดความขัดแย้งระหว่างการโทร


ฉันกำลังใช้การอ้างอิงนี้และการได้รับข้อผิดพลาดที่คล้ายกันรหัสพื้นที่ได้รับการตั้งค่าแล้วในคอนโทรลเลอร์ของฉันคุณสามารถช่วยฉันออกจากสิ่งนี้ได้ ฉันได้ทำการเปลี่ยนแปลงเช่นการเรียก setareacode ในฟังก์ชั่นการสร้างของฉัน แต่ได้รับข้อผิดพลาดเดียวกัน
Gagan


1

ปัญหาคือว่ามันไม่มีวิธีการใด ๆ ที่ส่งกลับเท็จถ้าตัวแปร area_code ไม่ได้รับการตั้งค่า วิธีที่ฉันพบวิธีแก้คือการสร้าง override ของ state state และสร้างวิธีการใหม่เพื่อตรวจสอบถ้ามีการตั้งค่า 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

ขอบคุณ Marius สำหรับการแก้ไขฉัน ฉันพบกรณีเดียวกันในโครงการส่วนใหญ่ของฉันและสิ่งนี้ช่วยให้ฉันแก้ไขปัญหานี้ได้
Ravi yadav

@Marius คุณจะอธิบายว่าทำไมและให้ผู้คนรู้วิธีการที่เป็นที่ยอมรับมากที่สุดในการแก้ไขปัญหาหรือไม่
chrBrd

-1

ลองอัปเกรดวีโอไอพีโดยใช้ 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) {
        ...
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.