test.php 스크립트에서 Magento 2를 어떻게 부트 스트랩 할 수 있습니까?


93

magento 1에서 Mage_Core_Model_App클래스 를 인스턴스화하는 데 필요한 파일을 만든 다음 테스트 목적으로 "더러운"코드를 추가 할 수있었습니다.
이와 같은 것 test.php:

<?php
//some settings
error_reporting(E_ALL | E_STRICT); 
define('MAGENTO_ROOT', getcwd()); 
$mageFilename = MAGENTO_ROOT . '/app/Mage.php'; 
require_once $mageFilename; 
Mage::setIsDeveloperMode(true); 
ini_set('display_errors', 1); 
umask(0);
//instantiate the app model
Mage::app(); 
//my toy code in here.

그런 다음 test.php브라우저에서 전화를 걸어 내가하고있는 일을 볼 수있었습니다 .

Magento 2에 대해 동일한 작업을 수행하려면 어떻게해야합니까?


4
magento 2 cron은 어떻게 작동합니까? 같은 접근법을 사용할 수 있습니까?
Amasty

4
좋은 생각이지만 ...에서 코드 cron.php: $app = $bootstrap->createApplication('Magento\Framework\App\Cron', ['parameters' => ['group::']]);. 나만의 앱 모델을 만들어야합니까?
Marius

1
단위 테스트 작성
Kristof at Fooman

2
@Fooman. 이 답변을 자유롭게 작성하십시오. 그러나 예를 들어주십시오. 나는 단위 테스트를 처음 사용합니다.
Marius

답변:


86

@ Flyingmana의 대답을 바탕으로 약간 파고 솔루션을 생각해 냈습니다. 나를 위해 일하는 것은 이음새입니다.
먼저 내 해결책과 설명이 있습니다. 내 magento 인스턴스의 루트에
있는 파일을 만들었습니다 test.php.

<?php
require __DIR__ . '/app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication('TestApp');
$bootstrap->run($app);

그런 다음 TestApp.php이 내용으로 같은 장소에서 파일을 만들었습니다 .

<?php
class TestApp
    extends \Magento\Framework\App\Http
    implements \Magento\Framework\AppInterface {
    public function launch()
    {
        //dirty code goes here. 
        //the example below just prints a class name
        echo get_class($this->_objectManager->create('\Magento\Catalog\Model\Category'));
        //the method must end with this line
        return $this->_response;
    }

    public function catchException(\Magento\Framework\App\Bootstrap $bootstrap, \Exception $exception)
    {
        return false;
    }

}

이제 test.php브라우저에서 호출 하면 TestApp :: launch ()에 배치 된 모든 것이 실행됩니다.

이제 이것이 작동하는 이유 : 부트 스트랩 클래스
의 메소드 createApplication가 가장 중요한 부분입니다. 응용 프로그램 클래스의 인스턴스를 만듭니다. 이 메소드 createApplication\Magento\Framework\AppInterface2 가지 메소드를 포함 하는 구현을 예상합니다 .
그래서 TestApp그 인터페이스를 구현하는 클래스를 만들었습니다 . 내 앱이 예외를 처리하지 않기 때문에 메소드가 항상 catchException반환 false되도록했습니다. 문제가있는 경우 화면에 인쇄하십시오.
그런 다음 방법을 구현했습니다 launch. 이것에 의해 호출됩니다 \Magento\Framework\App\Bootstrap::run. 이 run방법은 응용 프로그램이 매개 변수로 전달한 것이 무엇이든 거의 동일합니다.
응용 프로그램에 의존하는 유일한 것은이 줄입니다.

$response = $application->launch();

이것은 호출 \Magento\Framework\App\Bootstrap::run이 Magento env를 초기화하고 (아마도 다른 미친 것들을 할 수 있습니다 ... 아직 모든 것을 확인하지는 않았습니다) launch응용 프로그램 에서 메소드 를 호출합니다 .
그래서 모든 더러운 코드를 해당 메소드에 넣어야합니다.
그런 다음 \Magento\Framework\App\Bootstrap::run호출은 $response->sendResponse();어디에서 $response무엇 인 launch방법으로 돌아갑니다.
이것이 return $this->_response;필요한 이유 입니다. 빈 응답 만 반환합니다.

내 응용 프로그램 클래스를 확장 \Magento\Framework\App\Http하여 이미 요청 및 응답 매개 변수 (및 기타 매개 변수)를 갖지만 클래스를 아무것도 확장하지 못하게 할 수 있습니다. 그런 다음 생성자를 \Magento\Framework\App\Http클래스 에서 복사해야합니다 . 필요할 경우 생성자에 더 많은 매개 변수를 추가 할 수 있습니다.


2
물론 TestApp클래스는 동일한에 정의 된 수있는 test.php파일,하지만 난 그것을 더티 :) 만들고 싶어하지 않는다
마리우스

"지역 코드가 설정되지 않았습니다"라는 오류가 발생하여 메소드 parent::launch();의 첫 번째 행 으로 추가해야 했습니다.launch()
OSdave

@OSdave. 내가 테스트 할 때 그없이 작동했습니다. 아마도 최신 버전에서 변경된 것이있을 것입니다.
Marius

@Marius, 나는 서버의 빠른 설치를 원함으로써 magento를 설치했다. 그리고 앱에 bootstrap.php가 없습니다
er.irfankhan11

1
@Butterfly 사용자 정의 컨트롤러에 포함시킬 필요는 없습니다. 파일은 컨트롤러에 도달하기 전에 index.php에 포함됩니다.
마리우스

54

빠른 / 짧은 / 더러운 테스트를 위해 다음과 같이 사용했습니다.

use Magento\Framework\App\Bootstrap;
require __DIR__ . '/../app/bootstrap.php';

$bootstrap = Bootstrap::create(BP, $_SERVER);

$obj = $bootstrap->getObjectManager();

$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');

$quote = $obj->get('Magento\Checkout\Model\Session')->getQuote()->load(1);
print_r($quote->getOrigData());

4
이 작동합니다. 다른 답변은 그렇지 않습니다.
ahnbizcad

1
이것은 내 쪽에서 HTTP 500을 트리거합니다.
Max

여전히 2.1.2에서 작동합니다. 요구 경로를 수정해야했다
simonthesorcerer

나를 위해 작동하지 않았다
Sarfaraj Sipai

20

@Marius의 답변을 바탕으로 나는 이것을 생각해 냈습니다.

명령 줄과 브라우저를 통해 작동하며 유용합니다.

다음은 프로그래밍 방식으로 범주를 삭제하는 샘플 스크립트입니다.

scripts/abstract.php

<?php
use \Magento\Framework\AppInterface as AppInterface;
use \Magento\Framework\App\Http as Http;

use Magento\Framework\ObjectManager\ConfigLoaderInterface;
use Magento\Framework\App\Request\Http as RequestHttp;
use Magento\Framework\App\Response\Http as ResponseHttp;
use Magento\Framework\Event;
use Magento\Framework\Filesystem;
use Magento\Framework\App\AreaList as AreaList;
use Magento\Framework\App\State as State;

abstract class AbstractApp implements AppInterface
{
    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectManager,
        Event\Manager $eventManager,
        AreaList $areaList,
        RequestHttp $request,
        ResponseHttp $response,
        ConfigLoaderInterface $configLoader,
        State $state,
        Filesystem $filesystem,
        \Magento\Framework\Registry $registry
    ) {
        $this->_objectManager = $objectManager;
        $this->_eventManager = $eventManager;
        $this->_areaList = $areaList;
        $this->_request = $request;
        $this->_response = $response;
        $this->_configLoader = $configLoader;
        $this->_state = $state;
        $this->_filesystem = $filesystem;
        $this->registry = $registry;
    }

    public function launch()
    {
        $this->run();
        return $this->_response;
    }

    abstract public function run();

    public function catchException(\Magento\Framework\App\Bootstrap $bootstrap, \Exception $exception)
    {
        return false;
    }
}

scripts/delete-category.php

<?php
require dirname(__FILE__) . '/../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
require dirname(__FILE__) . '/abstract.php';

class CreateCategoriesApp extends AbstractApp
{

    public function run()
    {
        $this->_objectManager->get('Magento\Framework\Registry')
            ->register('isSecureArea', true);

        $category = $this->_objectManager->create('\Magento\Catalog\Model\Category');
        $category = $category->load(343);

        $category->delete();
    }
}

/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication('CreateCategoriesApp');
$bootstrap->run($app);

그런 다음 그냥 실행합니다 php scripts/delete-category.php


2
내가 그것을 오류 액세스 또는 지역의 문제를 보여 다음 관리 코드에 액세스하려는 경우, 프론트 엔드를 위해 잘 작동 당신은 관리 영역에 대한 호출하는 방법을 알 수 있습니다
프라 딥 쿠마르

무언가를 부를 때, 나는 얻는다 : Magento\Framework\Exception\LocalizedException: Area code is not set. 어떻게 설정할 수 있습니까? 나는 친구가 필요합니다.
Max

이 코드를 작성한 이후 M2를 많이 보지 못했습니다. 프레임 워크의 변경으로 인해 유효하지 않거나 수정해야 할 수도 있습니다. 죄송합니다!
Luke Rodgers

18

요청에 따라 테스트를 작성하는 방법에 대한 매우 짧은 예 (폴더 확장 구조에 배치하지 않고). 아아, 이것은 모든 명령 줄이며 브라우저를 통한 소비는 아닙니다.

파일 만들기

dev/tests/unit/quicktest.php

<?php

class QuickTest extends \PHPUnit_Framework_TestCase
{
    public function testExample()
    {
        //instantiate your class
        $context = new Magento\Framework\Object();

        $context->setData('param', 'value');

        //test whatever you want to test
        $this->assertEquals('value', $context->getData('param'));

        //you could even output to console
        echo $context->getData('param');

    }
}

그런 다음 디렉토리 dev/tests/unit/실행 에서 phpunit quicktest.php코드를 실행합니다. 파일 dev/tests/unit/phpunit.xml.dist이 자동으로로드되고 환경을 준비하기 때문에이 모든 것이 작동 합니다.

많은 경우 클래스의 생성자에 입력을 제공해야 할 수도 있습니다. dev/tests/unit/testsuite/모의 객체를 포함하여 이것이 어떻게 보이는지 에 대한 추가 예는 아래의 기존 테스트를 참조하십시오 .


1
나는 "더러운"놀이터를 요청했다. 당신은 여기에 깨끗한 것을주었습니다 :). 재미있는 생각. 나는 그것을 시도 할 것이다.
Marius

7
나는 과거에 test.php를 만들었을 때 노력이 지속적인 이익을 가져다 줄 테스트를 작성했을 수도 있다는 것을 알았습니다.
Kristof at Fooman

15

테스트 시스템에 연결하는 것보다 더 나은 방법이 있습니다. Magento 2의 명령 줄 인터페이스를 사용하십시오.

이것은 샌드 박스 코드를 실제 모듈에 통합해야하거나 목적에 맞게 코드를 작성해야한다는 것을 의미하지만 어쨌든 그렇게해야합니다.

당신은 당신의 모듈이 일단 설정 , 명령을 추가하는 것은 매우 쉽습니다. 수업과 DI 등록 만하면됩니다.

1. {모듈} /etc/di.xml

<?xml version="1.0"?>
<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="greeting_command" xsi:type="object">Magento\CommandExample\Console\Command\GreetingCommand</item>
            </argument>
        </arguments>
    </type>
</config>

2. {module} /Console/Command/GreetingCommand.php

<?php

namespace Magento\CommandExample\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Class GreetingCommand
 */
class GreetingCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('example:greeting')
             ->setDescription('Greeting command');

        parent::configure();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('<info>Hello world!</info>');
    }
}

https://github.com/magento/magento2-samples/tree/master/sample-module-command 에서 파생 된 예 -이 기능을 통합 한 전체 모듈은 여기를 참조하십시오. 있습니다 덜 사소한 예 포함 된.

규칙에 따라 명령 클래스는 항상로 {module}/Console/Command끝나고로 끝나야합니다 Command.php.

이 두 비트의 코드 (플러시 된 Magento 캐시 등)를 추가했으면 SSH에서 이름으로 명령을 실행하십시오 php bin/magento example:greeting.

이 컨텍스트에서 의존성 주입을 사용할 수 있으므로 원하는 코드를 모두 실행할 수 있습니다 execute().

이 인터페이스는 Symfony의 콘솔 구성 요소 를 기반으로하므로 옵션 / 인수 , 테이블 및 매우 쉬운 진행 표시 줄을 포함한 광범위한 기능에 모두 액세스 할 수 있습니다 .

명령 또는 옵션을 설정하는 데 문제가 발생하면 일반적으로 'list'명령을 실행하여 문제를 더 잘 파악할 수 있습니다. php bin/magento list

즐겨.


좋은! 내보내기가 많은 스크립트에 대한 Symfony의 진행 표시 줄이 있습니다. 감사합니다
urbansurfers

13

중요한 부분은 \Magento\Framework\App\Bootstrap::create

그러나 Bootstrap::init()메소드가 비공개이므로 많은 중요한 것들이 발생하기 때문에 메소드를 호출하는 공개 메소드가 필요합니다.

한 가지 측면 createApplication()과 그 run()방법뿐만 아니라 getDirList()and 및 getObjectManager()방법 도 마찬가지 입니다.

따라서 응용 프로그램이 필요하지 않으며 단점은 오류 처리기가 초기화되지 않는다는 것입니다.


6

아마도 주제를 벗어난 것이지만, 항상 Magento 1의 연락처 색인 제어기 파일을 사용하여 사물을 테스트합니다 (IndexAction 메소드). example.com/contacts로 이동하는 것만 큼 간단합니다. 그 변경 사항을 커밋하지 않아야합니다.)

Magento 2에서 비슷한 작업을 수행 할 수 있다고 확신합니다. 부트 스트랩 코드로 새 파일을 작성하지 않아도됩니다.


1
천국은 당신이 잊어 버리거나 생산하는 것을 금지합니다! 핵심 코드를 수정하지 마십시오.
Ryan Hoerr

@RyanH. 일어나지 않을 것입니다. 버전 관리, 자동화 된 빌드, 정적 코드 분석, 피어 코드 검토, 스테이징 / 사용자 승인 테스트 등 그러나, 만약 당신이 그것을 가지고 있지 않다면, 생산에이를 수도 있습니다. : P
Erfan

1
그것은 당신에게 좋지만, 여기를 찾는 대부분의 사람들은 그런 종류의 컨트롤을 가지고 있지 않을 것입니다. 항상 올바른 일을하는 방법을 가르치고하는 것이 좋습니다.
Ryan Hoerr

5

이 답변은 Marius의 위 답변에 대한 약간의 수정입니다.

Magento 2.1에서 Area code not set해당 코드를 사용할 때 와 같은 오류가 발생했기 때문입니다.So the intension of this answer is to fix that error on Magento 2.1

이 오류를 해결하기 위해해야 ​​할 일은의 영역을 정의하는 것 test.php file입니다. (아래 수정 된 파일 참조).

<?php
require __DIR__ . '/app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();

$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');
/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication('TestApp');
$bootstrap->run($app);

그리고 TestApp.php파일은 동일하게 유지됩니다.

<?php

class TestApp
    extends \Magento\Framework\App\Http
    implements \Magento\Framework\AppInterface {
    public function launch()
    {
        //dirty code goes here.
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $product = $objectManager->get('Magento\Catalog\Model\Product')->load(71);
        var_dump($product->getData());

        return $this->_response;
    }

    public function catchException(\Magento\Framework\App\Bootstrap $bootstrap, \Exception $exception)
    {
        return false;
    }

}

이것은 또한 2.1.6에서 작동하지 않습니다.Uncaught TypeError: Argument 2 passed to Magento\\Framework\\App\\Http::__construct() must be an instance of Magento\\Framework\\Event\\Manager, none given
Guerrilla

5

아래 코드를 추가하여 magento 루트에서 스크립트를 지시 할 수 있으며 부트 스트랩이 포함됩니다 .. [magento 루트 폴더에 test.php 생성 및 아래 코드 포함]

ini_set('display_errors', 1);
ini_set('max_execution_time', 0);
ini_set("memory_limit", "-1");
set_time_limit(0);
error_reporting(E_ALL);
require './app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('admin');

이것이 도움이 되길 바랍니다.


2

아래 코드를 사용하여 Magento 2 루트에서 직접 스크립트를 실행할 수 있습니다. Magento 2 루트 디렉토리에 새 파일을 작성하고이 코드를 추가 한 후 파일에 스크립트를 추가하십시오.

<?php
    use Magento\Framework\App\Bootstrap;
    include('app/bootstrap.php');
    $bootstrap = Bootstrap::create(BP, $_SERVER);

    $objectManager = $bootstrap->getObjectManager();

    $state = $objectManager->get('Magento\Framework\App\State');
    $state->setAreaCode('frontend');

1

다음은 magento 디렉토리 외부의 사용자 정의 스크립트로 Magento 초기화를 수행 한 작업입니다.

//Required to include Magento functions.
$magento_dir "your/path/to/the/magento/installation/directory/";
require $magento_dir . 'app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
//$app = $bootstrap->createApplication('Magento\Framework\App\Http');
$app = $bootstrap->createApplication('MyClass');
$bootstrap->run($app);

이것은 Magento 문서에 따라 권장되는 방법입니다. http://devdocs.magento.com/guides/v2.0/config-guide/bootstrap/magento-bootstrap.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.