Làm cách nào tôi có thể bootstrap Magento 2 trong tập lệnh test.php?


93

Trong magento 1 tôi có thể tạo một tệp mà tôi chỉ cần khởi tạo Mage_Core_Model_Applớp và sau đó tôi có thể thêm mã "bẩn" của mình cho mục đích thử nghiệm.
Một cái gì đó như thế này 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.

Sau đó, tôi đã có thể gọi test.phptrong trình duyệt và xem những gì tôi đang làm.

Làm thế nào tôi có thể làm tương tự cho Magento 2?


4
Làm thế nào để magento 2 cron hoạt động? Có thể bạn có thể sử dụng cùng một cách tiếp cận?
Vui vẻ

4
Ý tưởng tốt, nhưng ... mã từ cron.php: $app = $bootstrap->createApplication('Magento\Framework\App\Cron', ['parameters' => ['group::']]);. Tôi có nên tạo mô hình ứng dụng của riêng mình?
Marius

1
viết một bài kiểm tra đơn vị
Kristof tại Fooman

2
@Fooman. Hãy viết điều này như một câu trả lời, nhưng vui lòng cung cấp một ví dụ. Tôi là người mới thử nghiệm đơn vị.
Marius

Câu trả lời:


86

Dựa trên câu trả lời của @ Flyingmana, tôi đã đào một ít và đưa ra giải pháp. Nó đường may để làm việc cho tôi.
Đầu tiên là giải pháp của tôi, sau đó là một số giải thích.
Tôi đã tạo một tệp được gọi test.phptrong thư mục gốc của magento.

<?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);

Sau đó, tôi đã tạo một tệp được gọi TestApp.phpở cùng một nơi với nội dung này.

<?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;
    }

}

Bây giờ tôi chỉ có thể gọi test.phptrong trình duyệt và mọi thứ được đặt trong TestApp :: launch () sẽ được thực thi.

Bây giờ, tại sao điều này hoạt động:
Phương thức createApplicationtừ lớp bootstrap là phần quan trọng nhất. Nó tạo ra một thể hiện của một lớp ứng dụng. Phương thức này createApplicationdự kiến ​​thực hiện \Magento\Framework\AppInterfacecó chứa 2 phương thức.
Vì vậy, tôi đã tạo lớp riêng của mình trong TestAppđó thực hiện giao diện đó. Tôi đã luôn luôn catchExceptiontrả lại phương thức falsevì tôi không muốn ứng dụng của mình xử lý các ngoại lệ. Trong trường hợp có gì đó không đúng, chỉ cần in nó trên màn hình.
Sau đó tôi thực hiện phương pháp launch. cái này được gọi bằng \Magento\Framework\App\Bootstrap::run. Đây runphương pháp thực hiện gần như cùng một điều không có vấn đề gì các ứng dụng thông qua như là một tham số là.
Điều duy nhất phụ thuộc vào ứng dụng là dòng này:

$response = $application->launch();

Điều này có nghĩa là việc gọi \Magento\Framework\App\Bootstrap::runsẽ khởi tạo Magento env (có thể thực hiện một số nội dung điên rồ khác ... Tôi chưa kiểm tra mọi thứ) sau đó gọi launchphương thức từ ứng dụng.
Đó là lý do tại sao bạn cần đặt tất cả mã bẩn của mình vào trong phương thức đó.
Sau đó, các \Magento\Framework\App\Bootstrap::runcuộc gọi $response->sendResponse();ở đâu $responselaunchphương thức trả về.
Đó là lý do return $this->_response;cần thiết. Nó chỉ trả về một phản ứng trống rỗng.

Tôi đã làm cho lớp ứng dụng của mình mở rộng \Magento\Framework\App\Httpđể tôi sẽ có các tham số yêu cầu và phản hồi (và các tham số khác), nhưng bạn có thể làm cho lớp của mình mở rộng không có gì. Sau đó, bạn cần sao chép hàm tạo từ \Magento\Framework\App\Httplớp. Có thể thêm nhiều tham số trong hàm tạo nếu bạn cần nó.


2
Tất nhiên TestApplớp có thể đã được định nghĩa trong cùng một test.phptệp, nhưng tôi không muốn làm cho nó bẩn :)
Marius

Tôi đã phải thêm parent::launch();dòng launch()phương thức đầu tiên vì nó gây ra lỗi "Không đặt mã vùng"
OSdave

@OSdave. Nó đã làm việc mà không có điều đó khi tôi thử nghiệm. Hầu hết có lẽ một cái gì đó thay đổi trong các phiên bản mới nhất.
Marius

@Marius, tôi đã cài đặt magento bằng cách cài đặt nhanh máy chủ. Và đừng có bootstrap.php trong ứng dụng
er.irfankhan11

1
@Butoston Bạn không cần đưa nó vào bộ điều khiển tùy chỉnh của mình. Các tập tin được bao gồm trong index.php trước khi nó đến bộ điều khiển của bạn.
Marius

54

Đối với các bài kiểm tra nhanh / ngắn / bẩn, tôi đã sử dụng một cái gì đó như thế này:

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
những công việc này. Các câu trả lời khác thì không.
ahnbizcad

1
điều này kích hoạt HTTP 500 ở bên tôi.
Tối đa

Vẫn hoạt động trong 2.1.2. Tôi đã phải sửa đổi đường dẫn yêu cầu tho
simonthesorcerer

đã không làm việc cho tôi
Sarfaraj Sipai

20

Dựa trên câu trả lời của @ Marius, tôi đã nghĩ ra điều này.

Nó hoạt động thông qua cả dòng lệnh cũng như trình duyệt mà tôi thấy hữu ích.

Đây là một tập lệnh mẫu để xóa danh mục theo chương trình.

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);

Sau đó, tôi chỉ chạy nó như php scripts/delete-category.php


2
hoạt động tốt cho frontend, nếu tôi muốn truy cập mã quản trị thì nó hiển thị lỗi truy cập hoặc sự cố khu vực, bạn có thể cho biết cách gọi cho khu vực quản trị
Pradeep Kumar

Khi cố gắng gọi một cái gì đó, tôi nhận được : Magento\Framework\Exception\LocalizedException: Area code is not set. Làm thế nào tôi có thể thiết lập nó? Tôi cần fronend.
Tối đa

Tôi đã không nhìn vào M2 nhiều kể từ khi tôi viết mã này, tôi sợ, những thay đổi trong khung có thể khiến nó không hợp lệ hoặc cần sửa đổi, xin lỗi!
Luke Rodgers

18

Như đã yêu cầu một ví dụ rất ngắn về cách bạn có thể viết một bài kiểm tra (mà không đặt nó trong cấu trúc mở rộng thư mục của bạn). Than ôi đây là tất cả các dòng lệnh và không cho tiêu dùng thông qua một trình duyệt.

Tạo tập tin

dev/tests/unit/quicktest.php

với

<?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');

    }
}

sau đó từ thư mục dev/tests/unit/chạy phpunit quicktest.phpsẽ thực thi mã của bạn. Tất cả điều này hoạt động kể từ khi tập tin dev/tests/unit/phpunit.xml.distđược tự động tải và chuẩn bị môi trường.

Trong nhiều trường hợp, bạn có thể phải cung cấp đầu vào cho hàm tạo của lớp. Vui lòng xem các thử nghiệm hiện có bên dưới dev/tests/unit/testsuite/để biết thêm ví dụ về cách hiển thị này, bao gồm các đối tượng chế giễu.


1
Tôi yêu cầu một sân chơi "bẩn". Bạn đã cho ở đây một trong sạch :). Ý tưởng thú vị. Tôi sẽ cho nó nó một cơ hội.
Marius

7
Tôi thấy rằng những lần tôi đã tạo ra một test.php trong quá khứ, nỗ lực cũng có thể đã đi vào việc viết một bài kiểm tra sẽ có lợi ích liên tục.
Kristof tại Fooman

15

Đây là một cách tốt hơn so với việc kết nối vào hệ thống thử nghiệm: Sử dụng giao diện dòng lệnh của Magento 2.

Điều này không có nghĩa là bạn sẽ phải tích hợp mã hộp cát của mình vào một mô-đun thực tế (hoặc tạo một mục đích cho mục đích này), nhưng dù sao bạn cũng nên làm điều đó.

Khi bạn đã thiết lập mô-đun của mình , việc thêm một lệnh khá dễ dàng. Tất cả bạn cần là lớp và DI để đăng ký nó.

1. {mô-đun} /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/GreetCommand.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>');
    }
}

Ví dụ được lấy từ https://github.com/magento/magento2-samples/tree/master/sample-module-command - xem ở đó để biết mô-đun hoàn chỉnh kết hợp chức năng này. Có những ví dụ ít tầm thường hơn bao gồm.

Theo quy ước, lớp lệnh của bạn phải luôn ở trong {module}/Console/Commandvà kết thúc bằng Command.php.

Khi bạn đã thêm hai bit mã đó (và xóa bộ đệm Magento, v.v.), hãy thực hiện lệnh của bạn theo tên trong SSH : php bin/magento example:greeting.

Bạn có thể sử dụng phép nội xạ phụ thuộc trong ngữ cảnh này, vì vậy bạn có thể chạy bất kỳ mã nào bạn muốn trong đó execute().

Giao diện này được xây dựng trên thành phần Console của Symfony , vì vậy bạn cũng có quyền truy cập đầy đủ vào tất cả các chức năng rộng lớn đó, bao gồm các tùy chọn / đối số , bảngthanh tiến trình rất dễ dàng .

Nếu bạn gặp phải bất kỳ vấn đề nào khi thiết lập lệnh hoặc tùy chọn của mình, bạn thường có thể chạy lệnh 'list' để hiểu rõ hơn về những gì đang xảy ra: php bin/magento list

Thưởng thức.


Đẹp! với các thanh tiến trình của Symfony cho các tập lệnh có xuất khẩu lớn. cảm ơn
urbansurlike

13

Phần quan trọng là \Magento\Framework\App\Bootstrap::create

nhưng vì Bootstrap::init()phương thức này là riêng tư và có rất nhiều thứ quan trọng, nên các phương thức công khai gọi nó là cần thiết.

Thats trên một bên createApplication()và làm theo tấm run()phương pháp, mà còn là getDirList()getObjectManager()phương pháp, mà cả hai không cần tranh cãi.

Vì vậy, một ứng dụng là không cần thiết, nhược điểm là, Trình xử lý lỗi không được khởi tạo.


6

Có thể ngoài chủ đề, nhưng tôi luôn sử dụng tệp trình điều khiển chỉ mục Danh bạ trong Magento 1 để kiểm tra mọi thứ (phương thức IndexAction). Nó đơn giản như đi tới example.com/contacts. Bạn chỉ cần đảm bảo không cam kết những thay đổi đó;)

Tôi chắc chắn rằng bạn có thể làm điều gì đó tương tự trong Magento 2. Giúp bạn không phải tạo một tệp mới với mã bootstrap.


1
Trời cấm bạn quên, hoặc làm điều đó trên sản xuất! Vui lòng không sửa đổi mã lõi.
Ryan Hoerr 23/2/2016

@RyanH. Sẽ không xảy ra. Kiểm soát phiên bản, xây dựng tự động, phân tích mã tĩnh, đánh giá mã ngang hàng, thử nghiệm chấp nhận dàn / người dùng / v.v. Nhưng vâng, nếu bạn không có điều đó, có khả năng nó sẽ kết thúc sản xuất: P
Erfan

1
Điều đó thật tuyệt vời đối với bạn, nhưng hầu hết mọi người nhìn vào đây sẽ không có những kiểu kiểm soát đó. Tốt hơn là luôn luôn dạy (và làm) cách làm việc đúng đắn.
Ryan Hoerr 23/2/2016

5

Câu trả lời này là một sửa đổi nhỏ cho câu trả lời ở trên của Marius

Bởi vì trong Magento 2.1 có lỗi như Area code not setkhi sử dụng mã đó.So the intension of this answer is to fix that error on Magento 2.1

Những gì bạn phải làm để khắc phục lỗi này là xác định khu vực trong của bạn test.php file. (xem tập tin sửa đổi bên dưới).

<?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);

Và các TestApp.phptập tin sẽ vẫn như cũ.

<?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;
    }

}

Điều này cũng không hiệu quả với tôi trong 2.1.6, tôi nhận đượcUncaught TypeError: Argument 2 passed to Magento\\Framework\\App\\Http::__construct() must be an instance of Magento\\Framework\\Event\\Manager, none given
Guerrilla

5

Bạn có thể trực tiếp tập lệnh trên root magento bằng cách thêm mã bên dưới và bootstrap sẽ được bao gồm .. [Tạo test.php trên thư mục gốc magento và bao gồm mã bên dưới]

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');

Hy vọng điều này sẽ hữu ích.


2

Bạn có thể chạy tập lệnh trực tiếp từ root Magento 2 bằng mã bên dưới. Tạo một tệp mới trong thư mục gốc Magento 2 và thêm mã này và sau đó thêm tập lệnh của bạn vào tệp.

<?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

Đây là những gì tôi đã làm để đưa Magento khởi tạo vào tập lệnh tùy chỉnh của mình bên ngoài thư mục 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);

Đây là cách được đề xuất theo các tài liệu Magento. http://devdocs.magento.com/guides/v2.0/config-guide/bootstrap/magento-bootstrap.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.