Cara yang Benar dan Didukung untuk Menambahkan Perintah CLI ke Magento 2

9

Apakah ada cara yang benar, dan didukung secara resmi, untuk menambahkan perintah CLI Anda ke modul Magento 2? Dari apa yang saya kumpulkan opsi Anda adalah

  1. Tambahkan kelas perintah Anda ke commandsargumen Magento\Framework\Console\CommandListvia di.xmlfile

  2. Daftarkan perintah Anda melalui \Magento\Framework\Console\CommandLocator::registerdalam registration.phpfile atau cli_commands.phpberkas

Tidak satu pun dari opsi ini diberkati dengan @api. Tidak jelas, sebagai pengembang ekstensi, bagaimana kita harus menambahkan skrip baris perintah sehingga mereka akan tetap menggunakan versi demi versi.

Adakah yang tahu jika ada kebijakan resmi Magento tentang cara Right ™ untuk melakukan ini?

Alan Storm
sumber

Jawaban:

6

cli_commands.phpharus digunakan jika perintah ditambahkan dalam paket non-modular. Jadi jika perintah ada di modul dan tidak apa-apa (diharapkan) bahwa itu hanya tersedia ketika modul diaktifkan, di.xmlharus digunakan. Jika Anda tidak ingin menambahkan modul dan hanya ingin memiliki paket Komposer yang berubah-ubah, Anda dapat menggunakan cli_commands.phpuntuk mendaftar perintah di sana. Tentu saja, itu harus benar-benar independen dari Magento. Atau, untuk saat ini, pendekatan ini dapat digunakan untuk mendaftarkan perintah yang diperlukan bahkan jika modul dinonaktifkan (pastikan modul tersebut tidak bergantung pada logika Modul apa pun yang hanya berfungsi saat diaktifkan).

BuskaMuza
sumber
11

Cara yang benar adalah:

Buat modul Anda seperti halnya modul apa pun

Cukup buat registration.phpfile Anda

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'My_Module',
    __DIR__
);

Dan buat module.xmlfile Anda :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="My_Module" setup_version="0.1.0">
    </module>
</config>

Tambahkan entri di 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="my_command" xsi:type="object">My\Module\Command\Mycommand</item>
            </argument>
        </arguments>
    </type>
</config>

Buat kelas perintah Anda:

<?php
namespace My\Module\Command;

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

class Mycommand extends Command
{
    protected function configure()
    {
        $this->setName('my:command');
        $this->setDescription('Run some task');

        parent::configure();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Hello world!');
    }
}

Untuk menjalankan tugas Anda cukup ketik:

php bin/magento my:command

Tentang kompatibilitas:

@api tidak diperlukan untuk perintah, itu digunakan untuk kontrak layanan AFAIK.

Jika Anda harus membiarkannya kompatibel, cukup gunakan antarmuka API di dalam skrip Anda alih-alih memasukkan logika di dalamnya.

Sebagai contoh:

<?php
use My\Module\Api\TaskInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends Command
{
    protected $taskInterface;

    public function __construct(
        TaskInterface $taskInterface
    ) {
        $this->taskInterface= $taskInterface;
        parent::__construct();
    }

    protected function configure()
    {
        $this->setName('my:command');
        $this->setDescription('Run some task');

        parent::configure();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->taskInterface->runTask();

        $output->writeln('Done.');
    }
}
Phoenix128_RiccardoT
sumber
1
Informasi bermanfaat, +1, tetapi apakah Anda yakin akan hal itu? Modul data sampel Magento menggunakan metode cli_commands.php, dan itu tampak lebih bersih, dan kecil kemungkinannya akan pecah jika Magento mengubah implementasiMagento\Framework\Console\CommandList
Alan Storm
Saya tidak 100% yakin, hanya Magento saja yang bisa menjawab ini, tetapi saya telah bermain beberapa saat di atasnya dan jika Anda menghapus "cli_commands.php" Anda masih akan melihat perintah Anda tersedia di bin / magento Anda. Mereka juga mendeklarasikannya di di.xml, jadi saya pikir itu masih ada sesuatu dari versi beta. Seperti itu untuk pembangun dan pabrik. Jika Anda melihat, cli_command.php hanya digunakan dalam data sampel.
Phoenix128_RiccardoT
Apa yang membuat Anda mengatakan bahwa @api akan menjadi usang?
Kristof di Fooman
@ Kristof, sangat menyesal saya tidak mengerti dengan benar salah satu slide solusi mitra terlatih, jadi abaikan kalimat itu. Saya memodifikasi posting saya dan menghapusnya.
Phoenix128_RiccardoT
3

jika saya melakukannya dengan benar, perintah yang didefinisikan dalam CommandList lebih dari DI hanya tersedia di Instance Magento diinstal dan juga hanya untuk Modul Magento (karena mereka harus didefinisikan dalam di.xml): https://github.com/magento /magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124

Magento \ Framework \ App \ DeploymentConfig :: isAvailable () dalam metode di atas memeriksa Tanggal instalasi di Config untuk memeriksa Magento2 yang diinstal: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc6045c/ internal / Magento / Framework / App / DeploymentConfig.php # L83 ).

Perintah yang didefinisikan dalam Magento \ Framework \ Console \ CommandLocator di sisi lain selalu tersedia dan bahkan dapat didefinisikan oleh Modul non Magento melalui CommandLocator :: metode register statis dalam file yang dimuat secara otomatis oleh komposer (misalnya cli_commands.php)

https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L130

https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L146

Jadi saya pikir kedua metode ini diperlukan dan memiliki hak untuk hidup

David Verholen
sumber
Itu adalah +1 pengamatan yang bagus, tetapi mengapa Anda harus memerlukan skrip Magento saat modul terkait tidak diinstal?
Phoenix128_RiccardoT
1
ini tentang contoh Magenta karena tidak diinstal. Ada beberapa perintah yang tersedia sebelum Anda menginstal magento2. Misalnya perintah sampledata: deploy, yang masuk akal jika Anda ingin langsung menginstal data sampel dengan pengaturan magento2.
David Verholen
Saya pikir kamu benar. Jadi cara "benar" untuk modul Magento adalah dengan menggunakan di.xml (seperti dalam jawaban saya) dan menggunakan "cli_command.php" ketika Anda perlu menjalankan beberapa tugas sebelum modul Anda diinstal. Itu masuk akal.
Phoenix128_RiccardoT
kamu, saya pikir seharusnya begitu. +1 karena saya pikir Anda memiliki jawaban yang benar (dan dijelaskan dengan sangat baik), tetapi ini tidak cocok dengan komentar;)
David Verholen
Terima kasih @vid Verholen, +1 saya berarti saya memberi Anda +1, bukan berarti Anda hanya pantas +1;)
Phoenix128_RiccardoT