Magento 2'yi bir test.php betiğinde nasıl önyükleyebilirim?


93

1. magento'da sadece Mage_Core_Model_Appsınıfı başlatmak için ihtiyaç duyduğum bir dosyayı oluşturabilir ve daha sonra "kirli" kodumu test amacıyla ekleyebilirim.
Bunun gibi bir şey 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.

Sonra test.phptarayıcıyı arayabilip ne yaptığımı görebildim.

Magento 2 için nasıl aynı şeyi yapabilirim?


4
Magento 2 cron nasıl çalışır? Aynı yaklaşımı kullanabilir misiniz?
Amasty

4
İyi fikir, ama ... kod adlı cron.php: $app = $bootstrap->createApplication('Magento\Framework\App\Cron', ['parameters' => ['group::']]);. Kendi uygulama modelimi oluşturmalı mıyım?
Marius

1
birim testi yaz
Fooman Kristof

2
@Fooman. Bunu cevap olarak yazmaktan çekinmeyin, ancak lütfen bir örnek verin. Birim testlerinde yeniyim.
Marius

Yanıtlar:


86

@ Flyingmana'nın cevabına dayanarak biraz kazı yaptım ve bir çözüm buldum. Benim için çalışmak için dikiş atıyor.
Önce benim çözümüm, sonra bazı açıklamalar. Magento örneğimin kökünde
bir dosya yarattım 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);

Daha sonra TestApp.phpbu içerikle aynı yerde adı verilen bir dosya oluşturdum .

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

}

Şimdi test.phptarayıcıyı arayabilirim ve TestApp :: launch () içine yerleştirilen her şey çalıştırılacak.

Şimdi, neden bu işe yarıyor: Bootstrap sınıfından gelen
yöntem createApplicationen önemli kısımdır. Bir uygulama sınıfı örneği oluşturur. Yöntem , 2 yöntem içeren createApplicationbir uygulama beklemektedir \Magento\Framework\AppInterface.
Ben de TestAppbu arayüzü uygulayan kendi sınıfımı oluşturdum . Uygulamamın istisnaları ele almasını istemediğim için yöntemi her zaman catchExceptiongeri döndürdüm false. Bir şeyler yanlış olursa, sadece ekrana yazdırın.
Sonra yöntemi uyguladım launch. buna denir \Magento\Framework\App\Bootstrap::run. Bu runyöntem, uygulamanın bir parametre olarak nasıl geçtiği önemli değil, neredeyse aynı şeyi yapıyor.
Uygulamaya bağlı olan tek şey bu satırdır:

$response = $application->launch();

Bu, çağrının \Magento\Framework\App\Bootstrap::runMagento env'ini başlatacağı anlamına gelir (belki başka çılgınca şeyler de yapabilirim ... henüz her şeyi kontrol etmedim), daha sonra launchuygulamadan yöntemi çağırır .
Bu nedenle, tüm kirli kodlarınızı bu yöntemin içine koymanız gerekir.
Sonra \Magento\Framework\App\Bootstrap::runaramaları $response->sendResponse();nerede $responsebudur launchyöntem döner.
Bu yüzden return $this->_response;gerekli. Sadece boş bir cevap döndürür.

App sınıfımı genişlettiğim \Magento\Framework\App\Httpiçin zaten istek ve yanıt parametrelerine (ve diğerlerine) sahip olacağım, ancak sınıfınızın hiçbir şeyi genişletmemesini sağlayabilirsiniz. O zaman yapıcıyı \Magento\Framework\App\Httpsınıftan kopyalamanız gerekir . Belki ihtiyacınız varsa, yapıcıya daha fazla parametre ekleyin.


2
Elbette, TestAppsınıf aynı test.phpdosyada tanımlanmış olabilirdi , ama onu kirletmek istemiyorum :)
Marius

Bana bir "Alan kodu ayarlanmadı" hatası verdiği parent::launch();için ilk launch()yöntem satırı olarak eklemek zorunda kaldım
OSdave

@OSdave. Test ettiğimde o olmadan çalıştı. Büyük olasılıkla en son sürümlerinde bir şey değişti.
Marius

@Marius, magento'yu sunucunun hızlı kurulumunu izleyerek kurdum. Ve app bootstrap.php yok
er.irfankhan11

1
@Butterfly Özel denetleyicinize eklemeniz gerekmez. Dosya, kontrol cihazınıza ulaşmadan önce index.php dosyasına dahil edilir.
Marius

54

Hızlı / kısa / kirli testler için şöyle bir şey kullandım:

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
bu çalışıyor. diğer cevaplar yok.
ahnbizcad

1
Bu benim tarafımda HTTP 500 tetikler.
Maksimum

Hala 2.1.2'de çalışıyor.
Zorunluluk

benim için işe yaramadı
Sarfaraj Sipai

20

@ Marius'un cevabına dayanarak bu şekilde geldi.

Hem komut satırı hem de faydalı bulduğum tarayıcı üzerinden çalışıyor.

Programlı kategoriyi silmek için örnek bir betik.

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

Sonra sadece gibi koş php scripts/delete-category.php


2
ben hata erişimi veya alan sorunu göstermek ardından yönetici kod erişmek istiyorsanız, kullanıcı arabirimi için iyi çalışıyor yönetici alanına çağırmak için nasıl anlarım
Pradeep Kumar

Bir şey aramaya çalışıyorum, ben alıyorum: Magento\Framework\Exception\LocalizedException: Area code is not set. Nasıl ayarlayabilirim? Ön tarafa ihtiyacım var.
Maksimum

M2'ye çok fazla bakmadım, korkarım ki bu kodu yazdım, çerçevedeki değişiklikler geçersiz kılmış ya da değiştirilmesi gerekebilir, üzgünüm!
Luke Rodgers

18

İstenildiği gibi, nasıl bir test yazabileceğinize dair kısa bir örnek (klasör uzantı yapınıza yerleştirmeden). Maalesef bu tüm komut satırı ve bir tarayıcı üzerinden tüketim için değil.

Dosyayı oluşturun

dev/tests/unit/quicktest.php

ile

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

    }
}

daha sonra kodunuzu dev/tests/unit/çalıştıracak phpunit quicktest.phpolan dizinden çalıştırın. Bunların hepsi çalışır, çünkü dosya dev/tests/unit/phpunit.xml.distotomatik olarak yüklenir ve ortamı hazırlar.

Pek çok durumda, sınıfların yapıcısına girdi sağlamanız gerekebilir. Lütfen dev/tests/unit/testsuite/alaycı nesneler de dahil olmak üzere bunun nasıl görünebileceğine dair daha fazla örnek için mevcut testlere bakın.


1
"Kirli" bir oyun alanı istedim. Burada temiz bir tane verdin :). İlginç fikir. Bir deneyeceğim.
Marius

7
Geçmişte bir test.php oluşturduğum zamanların çabaların devam eden bir fayda sağlayacak bir test yazmaya başladığını da biliyorum.
Fooman'daki Kristof,

15

İşte test sistemine bağlanmaktan daha iyi bir yol: Magento 2'nin komut satırı arayüzünü kullanın.

Bu, sanal alan kodunuzu gerçek bir modüle entegre etmek zorunda kalacağınız (veya amaç için bir tane oluşturacağınız) anlamına gelir, ancak yine de yapmalısınız.

Modülünüzü kurduğunuzda , komut eklemek oldukça kolaydır. Tek ihtiyacınız olan sınıf ve onu kaydetmek için DI.

1. {module} /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 adresinden türetilmiş örnek - bu işlevselliği içeren eksiksiz bir modül için buraya bakınız. Dahil daha az önemsiz örnekler var .

Kurallara göre, komut sınıfınız daima içinde olmalı {module}/Console/Commandve ile bitmelidir Command.php.

Bu iki kod parçasını ekledikten sonra (ve Magento önbelleğini temizledik, vb.) Komutunuzu SSH: 'de isminizle yürütün php bin/magento example:greeting.

Bağımlılık enjeksiyonunu bu bağlamda kullanabilirsiniz, böylece içinde istediğiniz herhangi bir kodu çalıştırabilirsiniz execute().

Bu arayüz Symfony's Console bileşenine dayanmaktadır, böylece seçenekler / argümanlar , tablolar ve çok kolay ilerleme çubukları da dahil olmak üzere geniş bir işlev yelpazesine tam erişiminiz olur .

Komutunuzu veya seçeneklerinizi ayarlamada herhangi bir sorunla karşılaşırsanız, yanlış olanın daha iyi görünmesini sağlamak için genellikle 'list' komutunu çalıştırabilirsiniz: php bin/magento list

Keyfini çıkarın.


Güzel! Symfony'nin büyük ihracatlı senaryolar için ilerleme çubukları. teşekkürler
urbansurfers

13

Önemli kısım \Magento\Framework\App\Bootstrap::create

ancak Bootstrap::init()yöntem özel olduğu için ve birçok önemli şey olduğu için, buna halka açık yöntemlere ihtiyaç vardır.

Bir tarafta, yöntemi createApplication()izleyen ve run()izleyenler aynı zamanda her ikisinin de argüman gerektirmeyen getDirList()ve getObjectManager()yöntemidir.

Dolayısıyla bir Uygulamaya ihtiyaç duyulmaz, olumsuz taraflar, Hata İşleyicinin başlatılmadığıdır.


6

Muhtemelen konu dışı, ama her şeyi test etmek için Magento 1'deki Contacts index controller dosyasını kullanıyorum (IndexAction yöntemi). Example.com/contacts adresine gitmek kadar basit. Sadece bu değişiklikleri yapmamaya dikkat etmelisiniz;)

Magento 2'de benzer bir şeyler yapabileceğinizi eminim. Sizi bootstrap koduyla yeni bir dosya oluşturmak zorunda kalmazsınız.


1
Cennet unutmayı ya da üretimde yapmayı yasaklar! Lütfen çekirdek kodunu değiştirmeyin.
Ryan Hoerr

@RyanH. Olmayacak. Sürüm kontrolü, otomatik yapılar, statik kod analizi, eş kod incelemesi, evreleme / kullanıcı kabul testleri / vb. Ama evet, eğer sizde yoksa, üretime son verme şansı var: P
Erfan

1
Bu senin için harika, ama buraya bakan çoğu insan bu tür kontrollere sahip olmayacak. Her zaman işleri yapmanın doğru yolunu öğretmek (ve yapmak) daha iyidir.
Ryan Hoerr

5

Bu cevap, yukarıdaki cevapta Marius tarafından yapılan küçük bir değişikliktir.

Çünkü Magento 2.1 Area code not setbu kodu kullanırken olduğu gibi hatayı aldı .So the intension of this answer is to fix that error on Magento 2.1

Bu hatayı düzeltmek için yapmanız gereken alanınızdaki alanı tanımlamaktır test.php file. (aşağıdaki değiştirilmiş dosyaya bakınız).

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

Ve TestApp.phpdosya aynı kalacaktır.

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

}

Bu aynı zamanda benim için 2.1.6'da işe yaramaz, anlıyorumUncaught TypeError: Argument 2 passed to Magento\\Framework\\App\\Http::__construct() must be an instance of Magento\\Framework\\Event\\Manager, none given
Gerilla

5

Senaryoyu aşağıdaki kodları ekleyerek magento köküne yönlendirebilirsin ve bootstrap da eklenecektir.

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

Umarım bu yardımcı olacaktır.


2

Direkt betiği Magento 2 root'tan aşağıdaki kodu kullanarak çalıştırabilirsiniz. Magento 2 kök dizininde yeni bir dosya oluşturun ve bu kodu ekleyin ve bundan sonra komut dosyanızı dosyaya ekleyin.

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

İşte Magento'yu, magento dizini dışındaki özel senaryomun içine başlatmak için yaptığım şey.

//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 dokümanlarına göre önerilen yol budur. http://devdocs.magento.com/guides/v2.0/config-guide/bootstrap/magento-bootstrap.html

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.