?> Magento 2 - Quick tip : how to quickly execute any magento 2 code in command line

Magento 2 – Quick tip : how to quickly execute any magento 2 code in command line

Magento 2 – Quick tip : how to quickly execute any magento 2 code in command line

The solution I am about to present allows you to execute any magento 2 code from command line.

While developing on magento 2, the code you are working on can be difficult to access and test because it sometimes needs to be executed in a specific context or after having clicked several times to access a specific page. That's why you often need to test some code without being obliged to go all the way.

I simply use a simple PHP script that can be executed in command line.

Here is a the empty structure of this script :

<?php

require '/var/www/html/app/bootstrap.php';

use Magento\Framework\App\Bootstrap;

class tmp
{

    public function __construct()
    {
        $params = $_SERVER;
        $bootstrap = Bootstrap::create(BP, $params);
        $obj = $bootstrap->getObjectManager();
    }

    public function execute()
    {

    }
}

$script = new tmp();
$script->execute();

I store this file in my magento folder in a __utils folder, name it tmp.ph for example and execute it like that :

I won't go into details but I run the previous command in the PHP docker container where magento runs. Prior to running the commande, I have to cd in the magento root.

This can be very helpful because it allows you to execute some code out of any context and really isolate a specific process and identify why potential bugs occurs, but also it can handy if you want to :

  • test and debug patch code before writing a proper patch
  • execute SQL statement
  • verify collections contents
  • automatise test data creation (product, sales rules or any other entities)
  • check some third party API calls

Here is a full example.

<?php

require '/var/www/html/app/bootstrap.php';

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Customer\Model\ResourceModel\CustomerRepository;
use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\State;
use Magento\Framework\DataObject;
use Magento\Framework\ObjectManagerInterface;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\ResourceModel\Quote\Payment;
use Magento\QuoteGraphQl\Model\Cart\AssignBillingAddressToCart;
use Magento\QuoteGraphQl\Model\Cart\AssignShippingAddressToCart;
use Magento\QuoteGraphQl\Model\Cart\AssignShippingMethodToCart;
use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForCustomer;
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
use Magento\QuoteGraphQl\Model\Cart\QuoteAddressFactory;
use Magento\Store\Model\App\Emulation;
use Magento\Quote\Model\QuoteManagement;

class createOrder
{
    private State $state;
    private ObjectManagerInterface $objectManager;
    private CustomerRepository $customerRepository;
    private CreateEmptyCartForCustomer $createEmptyCartforCustomer;
    private GetCartForUser $getCartForUser;
    private Emulation $emulation;
    private ProductRepositoryInterface $productRepository;
    private QuoteManagement $quoteManagement;
    private QuoteAddressFactory $quoteAddressFactory;
    private AssignShippingAddressToCart $assignShippingAddressToCart;
    private AssignBillingAddressToCart $assignBillingAddressToCart;
    private AssignShippingMethodToCart $assignShippingMethodToCart;
    private Payment $resourcePayment;
    private \Magento\Quote\Model\ResourceModel\Quote $quoteResourceModel;
    private CartManagementInterface $cartManagement;

    public function __construct()
    {
        $params = $_SERVER;
        $bootstrap = Bootstrap::create(BP, $params);
        $obj = $bootstrap->getObjectManager();
        $this->state = $obj->get(State::class);
        $this->state->setAreaCode('frontend');

        $obj = $bootstrap->getObjectManager();
        $this->objectManager = $obj;
        $this->customerRepository = $obj->get(CustomerRepository::class);
        $this->createEmptyCartforCustomer = $obj->get(CreateEmptyCartForCustomer::class);
        $this->getCartForUser = $obj->get(GetCartForUser::class);
        $this->emulation = $obj->get(Emulation::class);
        $this->emulation->startEnvironmentEmulation(3);
        $this->productRepository = $obj->get(ProductRepositoryInterface::class);
        $this->quoteManagement = $obj->get(QuoteManagement::class);
        $this->quoteAddressFactory = $obj->get(QuoteAddressFactory::class);
        $this->assignBillingAddressToCart = $obj->get(AssignBillingAddressToCart::class);
        $this->assignShippingAddressToCart = $obj->get(AssignShippingAddressToCart::class);
        $this->assignShippingMethodToCart = $obj->get(AssignShippingMethodToCart::class);
        $this->resourcePayment = $obj->get(Payment::class);
        $this->quoteResourceModel = $obj->get(\Magento\Quote\Model\ResourceModel\Quote::class);
        $this->cartManagement = $obj->get(CartManagementInterface::class);
    }

    public function execute()
    {
        $customer = $this->customerRepository->get('customer@example.com', 3);

        // Create empty cart
        $maskedCartId = $this->createEmptyCartforCustomer->execute($customer->getId());

        // Get cart
        /** @var Quote $cart */
        $cart = $this->getCartForUser->execute($maskedCartId, $customer->getId(), 3);

        // Add bundle to cart
        $bundleRequest = ['bundle_option' => [578 => 1122]];
        $bundle = $this->productRepository->get('bundle_sku');
        $cart->addProduct($bundle, new DataObject($bundleRequest));

        $this->quoteResourceModel->save($cart);
        $quote = $this->cartManagement->getCartForCustomer($customer->getId());

        $addressInputBilling = [
            'country_code' => "FR",
            'street' => ["55 billing street"],
            'telephone' => "0123456789",
            'postcode' => "75000",
            'city' => "Paris",
            'firstname' => "Customer",
            'lastname' => "Test",
            'save_in_address_book' => false
        ];
        $billingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInputBilling);
        $this->assignBillingAddressToCart->execute($quote, $billingAddress, false);

        // Set shipping address
        $addressInputShipping = [
            'country_code' => "FR",
            'street' => ["55 shipping street"],
            'telephone' => "01223456789",
            'postcode' => "75001",
            'city' => "PAris",
            'firstname' => "Customer",
            'lastname' => "Test",
            'save_in_address_book' => false
        ];
        $shippingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInputShipping);
        $this->assignShippingAddressToCart->execute($quote, $shippingAddress);
        // Set shipping method
        $this->assignShippingMethodToCart->execute($quote, $shippingAddress, 'my_carrier_code', 'method_code');

        $payment = $quote->getPayment();
        $payment->setMethod('free');
        $this->resourcePayment->save($payment);

        $order = $this->quoteManagement->submit($quote);
    }
}

$script = new createOrder();
$script->execute();

In that example, we can see that we use the object manager in the constructor for creating several instances of specific repositories, or services that we later use in the execute method.

We simply programmatically create an order in that example using all the different services that it requires.

I recall that this script is only for testing and debugging your code. Directly using the object manager is not a good practice and we are using it here because dependency injection cannot be used.

That's all.

berliozd