Criar uma Exception personalizada no Magento 2



Contextualizando



O que é uma Exception?

É um mecanismo que sinaliza um evento excepcional, significa algo que não é comum. A exceção ocorre quando acontece algo fora da regra de negócio prevista.
O tratamento de exceção é o mecanismo responsável pelo tratamento da ocorrência de condições que alteram o fluxo normal da execução de programas de computadores.
Exceção são usadas para fazer tratamentos no código, ou seja, podemos fazer um controle de exceção em determinada parte de um código fonte para saber qual foi o erro que levou ao problema.
Uma exceção pode ser lançada através da palavra reservada throw quando o trecho de código estiver envolvido na palavra reservada try, e capturada através da palavra reservada catch. Cada bloco try precisa ter ao menos um catch ou finally correspondente.
Uma classe de exceção definida pelo usuário pode ser criada herdando a classe Exception, consequentemente, o objeto lançado precisa ser uma instância da classe Exception ou uma subclasse de Exception. Tentar lançar um objeto sem essa ascendência resultará em um erro fatal. Para saber mais, consulte a documentação oficial do PHP sobre as exceptions.



Código para criar uma Exception

Este tipo de arquivo deve seguir a estruturas de pastas VendorModuleExceptionNameException.php. Cada arquivo de Exception deve estender a classe MagentoFrameworkExceptionLocalizedException.

<?php

namespace VendorModuleException;

use MagentoFrameworkExceptionLocalizedException;
use MagentoFrameworkPhrase;

class NameException extends LocalizedException

    public function __construct(
        Phrase $phrase = null,
        Exception $cause = null,
        array $params = [],
        $code = 0
    ) 
        parent::__construct($phrase, $cause, $params, $code);
    

A classe MagentoFrameworkExceptionLocalizedException estende da classe Exception do PHP e é estendida por um conjunto de classes que o próprio Magento já disponibiliza para o uso, estas classes de excessão estão disponíveis no caminho MagentoFrameworkException.



Disparando uma excessão

Ao disparar uma excessão, o código será interrompido e será “capturado” pelo primeiro catch que envolverá o código (podendo ser de outra função ou método. Para disparar uma excessão personalizada no Magento, é igual a lançar qualquer outra excessão.

throw new VendorModuleExceptionNameException(
    __('Message exception')
);



Finalização

Valores entre chaves (test) devem ser alterados na implementação do código.



Habilitando as alterações

Execute o comando PHP para limpar todos os caches de armazenamento em cache do processos.

php bin/magento cache:clean
php bin/magento flush



Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

- app/
  - code/
    - Vendor/
      - Module/
        - etc/
          - module.xml
        - Exception/
          - NameException.php
        - registration.php
        - composer.json

Source link

Como sobrescrever arquivos no Magento 2 através de preferences



Contextualizando



Magento 2 e a injeção de dependência

Para entender melhor a injeção de dependência é importante o conhecimento do 5º princípio do SOLID, a Inversão de Dependência (Dependency Inversion Principle).

É chamada de dependência cada instância de objeto dentro de uma determinada classe, porque a classe fica dependente da instância do objeto para ser executada. Para a injeção desta instância, é recomendado, que seja realizado através do DIP (Inversão de dependência).

A Injeção de dependência é um padrão de projeto (design pattern) que permite uma classe mantenha um baixo nível de acoplamento entre diferentes módulos do sistema, ou seja, permite que uma classe não seja responsável por criar os objetos dos quais depende.



Object Manager

O Object Manager é uma classe de serviço do Magento que instancia objetos no início do processo de bootstrap, gerando e injetando as classes declaradas no arquivo di.xml como dependências nos construtores das classes instanciadas.

Como o Object Manager fornece seu serviço indiretamente, a classe não deve depender do próprio Object Manager. As únicas exceções são factories personalizadas com lógica complexa e integrações de testes que necessitam das configurações de ambiente.

O Magento utiliza sua ferramenta de compilação de código para coletar todas as informações das dependências das classes e as armazena em arquivos. Durante o processo de criação das classes, o Object Manager utiliza essas informações de criação para criar objetos concretos na aplicação.

Classes de serviço que não existem no código base, como proxies, factories e interceptors que são declarados no código ou nas configurações, são gerados com a ajuda do compilador.



O que são as preferências?

As preferências (preferences) são utilizadas para indicar a implementação padrão das interfaces através do Object Manager, caso a interface injetada no construtor de uma classe não tenha sido mapeada com um preference, ao instanciar a classe será exibido um erro. Para a que o Object Manager faça o mapeamento da interface para a classe, deve-se utilizar o nó <preference> no arquivo di.xml, indicando no atributo for qual a interface e no atributo type qual a classe que deverá ser sobrescrita e implementar os métodos determinados pela interface.

A preference não precisa ser utilizada apenas com interfaces, é possível sobrescrever uma classe de outro módulo, definindo a nova classe globalmente. Para que o Object Manager faça o mapeamento da classe que deve ser sobrescrita, deve-se utilizar o nó <preference> no arquivo di.xml, indicando no atributo for qual a classe que será sobrescrita e no atributo type qual a classe que deverá ser sobrescrever, e nesta sobrepor o método com a mesma assinatura (desde que ele seja do publico ou protegido).



Código para sobrescrever arquivos



di.xml

O Object Manager usa a implementação através da abstração mapeando quando a assinatura do construtor de uma classe solicita um objeto por sua interface. O Object Manager utiliza esse mapeamento para determinar qual é a implementação padrão para a classe de um escopo específico. Estes tipo de funcionalidade deve ser implementada dentro do arquivo di.xml, seguindo a estruturas de pastas VendorModuleetcareadi.xml.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- Override a custom Interface -->
    <preference for="VendorModuleApiDataEntityNameInterface" type="VendorModuleModelEntityName" />

    <!-- Override a Magento Class -->
    <preference for="VendorModuleDirectoryClassToReplace" type="VendorModuleDirectoryClassReplaced" />
</config>



Interface

O código a seguir se refere a interface de uma entidade que deverá receber uma sobrescrição.

<?php

namespace VendorModuleApiData;

interface EntityNameInterface

    public const ATTR_NAME = 'attribute_name';

    public function getMethod(): type;

    public function setMethod(): self;



Model da Interface

O código a seguir se refere a implementação dos métodos de uma interface.

<?php

namespace VendorModuleModel;

use VendorModuleApiDataEntityNameInterface;
use VendorModuleModelResourceModelResourceModelName;

class EntityName implements EntityNameInterface

    public function getMethod(): type
    
        return $this->getData(self::ATTR_NAME);
    

    public function setMethod(string $attrName): self
    
        return $this->setData(self::ATTR_NAME, $attrName);
    



Classe a substituir

O código a seguir se refere a sobrescrição do método de uma classe, podendo ser uma classe de qualquer tipo (Block, Controller, Data Provider, Model, Ui Component, Service, etc).

<?php

namespace VendorModuleDirectory;

class ClassToReplace

    public function methodName(): type
    
        // Old code here
    



Classe substituída

O código a seguir se refere a extensão do(s) método(s) de uma classe.

<?php

namespace VendorModuleDirectory;

use VendorModuleDirectoryClassToReplace;

class ClassReplaced extends ClassToReplace

    public function methodName(): type
    
        // New code here
    



Finalizando

Valores entre chaves (test) devem ser alterados na implementação do código.



Habilitando as alterações

Comando para gerar a configuração das injeções de dependência e todas as classes ausentes que precisam ser geradas (proxys, interceptors, etc).

php bin/magento setup:di:compile



Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

- app/
  - code/
    - Vendor/
        - Module/
          - Api/
            - Data/
              - EntityNameInterface.php
          - etc/
            - di.xml
            - module.xml
          - Directory/
            - ClassReplaced.php
          - Model/
            - EntityName.php
          - registration.php
          - composer.json

Source link