Sostituisci classe astratta in Magento 2


13

In Magento 1 ho potuto copiare la classe astratta nella directory locale o della comunità e Magento l'ha usata quando il caricamento automatico ha caricato questa classe.

C'è invece una soluzione che Magento carica la mia classe vendor/magento/framework/Model/AbstractModel.php?

Le preferenze in di.xmlper le classi astratte non funzionano. Solo plugin?

Risposte:


9

Solo plugin?

Sì. Puoi scrivere plugin per classi astratte e, se possibile, i plugin dovrebbero sempre essere preferiti alle preferenze.

Le preferenze sono utili se si desidera sostituire un'implementazione. Non riesco a pensare a un caso d'uso per sostituire l'implementazione per tutti i modelli che si estendono AbstractModel, se ciò è anche logicamente possibile. Quindi quello che probabilmente vuoi è aggiungere o cambiare funzionalità e questo è ciò che serve per i plugin.


1
Ciao, come posso sostituire una funzione protetta dalla classe astratta in questo caso? potresti per favore aiutare
Manashvi Birla

2
Non e possibile. La cosa migliore è provare a trovare un modo per aggiungere plug-in ai metodi pubblici che utilizzano il metodo protetto e modificare il comportamento in questo modo, anche se comporta più codice e alcuni duplicati.
Fabian Schmengler,

1
"Non riesco a pensare a un caso d'uso per sostituire l'implementazione per tutti i modelli che estendono AbstractModel" Ho un tale caso d'uso: ho un modulo di pagamento, che utilizza la classe base astratta per 4 controller, ognuno dei quali utilizza un metodo dalla base per verificare la risposta dal gateway di pagamento. Ora, la risposta è cambiata e dovrei cambiare tutti 3.
Tero Lahtinen,

6

Soluzione completa: includi le classi sostituite prima che Magento le carichi automaticamente. Quindi passo dopo passo:

  1. Nel file app/etc/NonComposerComponentRegistration.phpaggiungi riga

    $pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';
  2. In app/etcfile di posto ClassReplacer.phpcon i contenuti

    class ClassReplacer
    {
        public function includeReplacedFiles($src)
        {
            try {
                $replacedFiles = $this->listDir($src, false, true);
                foreach ($replacedFiles as $replacedFile) {
                    include_once $src . $replacedFile;
                }
            } catch (Exception $e) {
                return;
            }
        }
    
        protected function listDir($dir, $prependDir = false, $recursive = false, $entityRegexp = null, $currPath = '')
        {
            if (!is_dir($dir)) {
                return array();
            }
            $currPath = $prependDir ? $dir : $currPath;
            $currPath = $currPath !== '' ? rtrim($currPath, '/') . '/' : '';
            $files = array();
            foreach (scandir($dir) as $file) {
                if (in_array($file, array('.', '..'))) {
                    continue;
                }
                $entity = $currPath . $file;
                if ($recursive && is_dir("$dir/$file")) {
                    $files = array_merge($files, $this->listDir("$dir/$file", false, true, $entityRegexp, $entity . '/'));
                    continue;
                }
                if ($entityRegexp && !preg_match($entityRegexp, $entity)) continue;
                $files[] = $entity;
            }
            return $files;
        }
    }
    $replace = new ClassReplacer();
    $replace->includeReplacedFiles(dirname(__DIR__) . '/code/Magento/');
  3. Posto in app/code/Magentouna classe, che verrà sostituita, ad esapp/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php



1
Hack sporco, ma a volte potrebbe essere utile essere in grado di farlo. M1 ha richiesto modifiche manuali nelle classi principali (quindi copia nell'app / codice / locale) se desideri che il PDF della fattura appaia diverso, scommetto che ci sarà qualche caso in cui sarà necessario.
Zefiryn,

5

Se la classe astratta ha qualche metodo pubblico o protetto che vuoi sovrascrivere, in realtà c'è un modo se non puoi usare plugin.

Ho dovuto scavalcare il metodo _processDownloadall'interno \Magento\Downloadable\Controller\Download, aggiungendo alcuni 'if-s' all'interno. (Se qualcuno ha idea di come posso aggiungere qualcosa come questo metodo interno usando i plugin, sarò grato). La classe è astratta, quindi la preferenza non ha funzionato. Anche i plugin, poiché il metodo è protetto. La cosa che dovevo fare era ignorare tutta la classe che si estendeva Download, usando la preferenza. Queste classi:

Magento\Downloadable\Controller\Download\Link Magento\Downloadable\Controller\Download\LinkSample Magento\Downloadable\Controller\Download\Sample

E al loro interno riscrivere il metodo dalla classe genitore (quello che dovevo sovrascrivere). Quindi in realtà il codice dei metodi sovrascritti è stato copiato in tre posizioni ed era esattamente lo stesso.

Non è l'ideale ma funziona.


4

Puoi provare a utilizzare Magento Plugin per migliorare la funzionalità esistente di qualsiasi classe Abstract, sebbene l'ambito della funzione dovrebbe essere Pubblico. Di recente ho lavorato sullo stesso problema in cui è necessario escludere i prodotti con un attributo personalizzato assegnato dall'elenco dei prodotti visualizzati di recente .

Ho usato il plugin per la funzione chiamata getItemsCollection dalla classe denominata Magento \ Reports \ Block \ Product \ AbstractProduct usando la sintassi seguente:

file: app \ code \ Package \ Module \ etc \ frontend \ di.xml

<type name="Magento\Reports\Block\Product\AbstractProduct">
    <plugin name="Package_Module::aroundGetItemsCollection" type="Package\Module\Block\Viewed" sortOrder="20"/>
</type>

file: app \ code \ Package \ Module \ Block \iew.php

public function afterGetItemsCollection(
    $subject, $result
) {
    $result = $result->addAttributeToFilter('skip_hire_product', [['neq' => 1], ['null' => true]], 'left');
    return $result;
}

Puoi usare anche plug-in prima e prima. Spero che questo lavoro per te.


1
ho avuto successo con il codice sopra in uno dei miei requisiti, in realtà volevo cambiare alcune funzionalità del metodo di classe astratta del modulo e-mail e il plugin mi ha aiutato a raggiungere questo obiettivo, grazie
bhargav shastri,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.