Magento 2 Virtual Types

Dando prosseguimento aos nossos estudos de Dependency Injection, hoje falaremos sobre Magento 2 Virtual Types.

 

Virtual Types permite que você altere os argumentos de uma dependência injetável específica e altere o comportamento de uma classe específica. Isso permite que você use uma classe personalizada sem afetar outras classes que têm uma dependência do original.

Voltando a nosso módulo.

Em nosso controller, fizemos a seguinte modificação:

<?php

namespace ForMage\Learning\Controller\Page;

use Magento\Framework\App\Action\Context;
use Magento\Framework\App\ResponseInterface;
use ForMage\Learning\Api\SizeInterface;
use ForMage\Learning\Api\ColorInterface;
use ForMage\Learning\Model\Product\Shoe;
use ForMage\Learning\Model\Product\Shirt;

class Index extends \Magento\Framework\App\Action\Action
{
    protected $size;
    protected $color;
    protected $product;
    protected $shirt;

    public function __construct(
        Context $context,
        SizeInterface $size,
        ColorInterface $color,
        Shoe $product,
        Shirt $shirt
    ) {
        parent::__construct($context);
        $this->size = $size;
        $this->color = $color;
        $this->product = $product;
        $this->shirt = $shirt;
    }

    public function execute()
    {
        var_dump($this->product);
    }
}

Estamos dando um var_dump em nossa classe Shoe. Ao acessar a nossa rota, temos o seguinte resultado:

4Mage - Magento 2 Virtual Types

Ok. Mas como usamos o Virtual Types?

Magento 2 Virtual Types

O Virtual Types age como uma subclasse de uma classe específica, sem interferir em outras classes. É uma dependência numa classe existente que não afeta outras classes.

O que nós queremos, é adicionar uma dependência a nossa classe SizeGreat sem que isso afete outros classes.

Faremos as seguintes alterações:

Criamos uma nova interface:

<?php

namespace ForMage\Learning\Api;

interface MaterialInterface
{
    public function getMaterial();
}

Adicionamos uma nova Model que implementa o MaterialInterface

<?php

namespace ForMage\Learning\Model;

use ForMage\Learning\Api\MaterialInterface;

class MaterialSynthetic implements MaterialInterface
{
    public function getMaterial()
    {
        return "Synthetic";
    }
}

Alteramos o nosso SizeGreat

<?php

namespace ForMage\Learning\Model;

use ForMage\Learning\Api\SizeInterface;
use ForMage\Learning\Api\MaterialInterface;

class SizeGreat implements SizeInterface
{
    protected $material;

    public function __construct(MaterialInterface $material)
    {
        $this->material = $material;
    }

    public function getSize()
    {
        return "Great";
    }
}

O que fizemos nele foi adicionar o nosso MaterialInterface e instanciá-lo a partir do __construct() que criamos para a nossa classe.

Feito isso, voltamos ao nosso di.xml com as seguintes alterações:

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <preference for="ForMage\Learning\Api\SizeInterface"
                type="ForMage\Learning\Model\SizeSmall" />

    <preference for="ForMage\Learning\Api\ColorInterface"
                type="ForMage\Learning\Model\ColorWhite" />

    <preference for="ForMage\Learning\Api\MaterialInterface"
                type="ForMage\Learning\Model\MaterialSynthetic" />

    <virtualType name="typeMaterial" type="ForMage\Learning\Model\SizeGreat">
        <arguments>
            <argument name="material" xsi:type="object">ForMage\Learning\Model\MaterialSynthetic</argument>
        </arguments>
    </virtualType>

    <type name="ForMage\Learning\Model\Product\Shoe">
        <arguments>
            <argument name="color" xsi:type="object">ForMage\Learning\Model\ColorBlack</argument>
            <argument name="size" xsi:type="object">typeMaterial</argument>
        </arguments>
    </type>

    <type name="ForMage\Learning\Model\Product\Shirt">
        <arguments>
            <argument name="typeText" xsi:type="string">MY STRING IN ARGUMENT TYPE</argument>
            <argument name="typeNumber" xsi:type="number">19.80</argument>
            <argument name="typeArray" xsi:type="array">
                <item name="customName" xsi:type="string">Antonio da Silva</item>
                <item name="customColor" xsi:type="string">Purple</item>
            </argument>
            <argument name="typeInitParameter" xsi:type="init_parameter">ForMage\Learning\Model\Product\Shirt::MY_CONSTANT</argument>
        </arguments>
    </type>
</config>

Explicando:

Apontamos a nossa interface MaterialInterface para a classe concreta MaterialSynthetic:

<preference for="ForMage\Learning\Api\MaterialInterface"
            type="ForMage\Learning\Model\MaterialSynthetic" />

Adicionamos o nosso Virtual Types. Através dele, estamos informando que a classe SizeGreat tem uma dependência com a classe MaterialSynthetic

<virtualType name="typeMaterial" type="ForMage\Learning\Model\SizeGreat">
    <arguments>
        <argument name="material" xsi:type="object">ForMage\Learning\Model\MaterialSynthetic</argument>
    </arguments>
</virtualType>

virtualType name”typeMaterial” –> O nome do nosso virtual type

type=”ForMage\Learning\Model\SizeGreat” –> a classe que estamos atacando, adicionando a nossa dependência.

Alteramos o nosso argument type em:

<type name="ForMage\Learning\Model\Product\Shoe">
    <arguments>
        <argument name="color" xsi:type="object">ForMage\Learning\Model\ColorBlack</argument>
        <argument name="size" xsi:type="object">typeMaterial</argument>
    </arguments>
</type>

Em parâmetro name=”size” nós alteramos, chamando o nosso virtual types typeMaterial.

Após isso, ao executarmos a nossa rota novamente teremos:

4Mage - Magento 2 Virtual Types

Link do módulo

Dúvidas? Posta aí!

Um abraço!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *