Überschreiben von Models und Methoden

Last modified by novalis on Wed, August 10, 2011 09:20
Source|Old Revisions  

Überschreiben von Models und Methoden

Beispiel #1 - Überschreiben eines Models

Im ersten Beispiel möchte ich erklären, wie Ihr eine Methode aus einem Core-Model überlagern/überschreiben könnt.

Zu Beginn erstellen wir uns ein eigenes Modul. Dazu legen wir im Verzeichnis /app/code/local/Mage ein Verzeichnis für unser Modul an. Ich nenne es mal Mymodul. Innerhalb dieses Verzeichnises legen wir zwei weitere Ordner an, einmal etc (enthält die Modulkonfiguration) und einmal Model (enthält die Models). In das Modelverzeichnis legen wir eine PHP-Datei mit dem Namen Mymodul.php; das ist das Model des neuen Moduls.

Mymodul.php

  1.       class Mage_Mymodul_Model_Mymodul extends Mage_Core_Model_Abstract
  2.       {
  3.       }

Im nächsten Schritt erstellen wir die config.xml Datei im Ordner etc des Moduls mit folgendem Inhalt:

  1.       <?xml version="1.0"?>
  2.       <config>
  3.           <modules>
  4.               /* Definiert mein Modul und dessen Version */
  5.               <Mage_Mymodul>
  6.                   <version>0.2.0</version>
  7.               </Mage_Mymodul>
  8.           </modules>
  9.    
  10.           <global>       
  11.               <models>
  12.                   /* Definiert mein Modul und das zugehörige Model */
  13.                   <mymodul>
  14.                       <class>Mage_Mymodul_Model</class>               
  15.                   </mymodul>           
  16.               </models>       
  17.           </global>   
  18.       </config>

Nun wollen wir die Grundlagen schaffen, die Funktion getTheme() aus dem Model Core/Design/Package.php zu üerschreiben. Hierzu erstellen wir in unserem Model Ordner einen neuen Ordner “Design” und darin die PHP Datei Package.php mit folgendem Inhalt.

  1.       /* Unser Model mit dem Ursprungsmodel erweitern */
  2.    
  3.       class Mage_Mymodul_Model_Design_Package extends Mage_Core_Model_Design_Package
  4.       {
  5.           public function getTheme($type)
  6.           {
  7.               if (empty($this->_theme[$type])) {           
  8.                   $this->_theme[$type] = Mage::getStoreConfig('design/theme/'.$type,$this->getStore());
  9.                   if ($type!=='default' && empty($this->_theme[$type])) {
  10.                       $this->_theme[$type] = $this->getTheme('default');
  11.                       if (empty($this->_theme[$type])) {
  12.                           $this->_theme[$type] = self::DEFAULT_THEME;
  13.                       }
  14.                   }
  15.               }
  16.  
  17.               return $this->_theme[$type];
  18.           }   
  19.       }

Als vorletzten Schritt editieren wir unsere config.xml, um Magento anzuweisen das Model zu überlagern/überschreiben. Hierzu fügen wir folgenden Code in die config.xml ein, und zwar in den Zweig <models>:

  1.       <core> /* Modul Core */
  2.                       <rewrite> /* überlagere/überschreibe */
  3.                           <design_package> /* Welches Model soll überschrieben werden */
  4.                           Mage_Mymodul_Model_Design_Package
  5.                           </design_package>
  6.                       </rewrite>
  7.                   </core>

Die config.xml sollte dann diesen Aufbau haben:

  1.       <?xml version="1.0"?>
  2.       <config>
  3.           <modules>
  4.               /* Definiert mein Modul und dessen Version */
  5.               <Mage_Mymodul>
  6.                   <version>0.2.0</version>
  7.               </Mage_Mymodul>
  8.           </modules>
  9.           <global>       
  10.               <models>
  11.                   /* Definiert mein Modul und das zugehörige Model */
  12.                   <mymodul>
  13.                       <class>Mage_Mymodul_Model</class>               
  14.                   </mymodul>
  15.                   <core> /* Modul Core */
  16.                       <rewrite> /* überlagere/überschreibe */
  17.                           <design_package> /* Welches Model soll überschrieben werden, Wert ist unser neues Model */
  18.                           Mage_Mymodul_Model_Design_Package
  19.                           </design_package>
  20.                       </rewrite>
  21.                   </core>
  22.               </models>       
  23.           </global>   
  24.       </config>

Im letzten Schritt legen wir eine Mage_Mymodul.xml, mit nachfolgendem Inhalt, im Verzeichnis app/etc/modules. Diese Datei weisst Magento an unser Modul zu laden

  1.       <?xml version="1.0"?>
  2.       <config>
  3.           <modules>
  4.               <Mage_Mymodul>
  5.                   <active>true</active> /* Aktivieren */
  6.                   <codePool>local</codePool>/* Wo liegt das Modul core,community oder local*/
  7.               </Mage_Mymodul>
  8.           </modules>
  9.       </config>

- - - - - - - - - - - - - - - - - - - - - - - - - - - -

Anmerkung 17.08.2010 (unter Magento 1.4.1.0 gilt vermutlich aber für alle Versionen)

Das Überschreiben von Model-Klassen funktioniert im Wesentlichen so wie oben beschrieben. Es gibt aber ein paar “Spezialfälle”. Es lassen sich etwa nicht alle Klassen im Model-Verzeichnis nach diesem Schema überschreiben.

Hierzu ein Beispiel:

Beispiel #a - Überschreiben eines Resource-Models

Wir wollen eine Methode im Resource-Model app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat.php überschreiben. Dazu legen wir in unserem Modul die Datei Model/Flat.php an mit etwa diesem Inhalt.

  1. <?php
  2. class Mycompany_Mymodule_Model_Flat extends Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat {
  3. ...
  4. /* Hier den Code für die zu überschreibende Methode einfügen */
  5. ...
  6. }

Die config.xml sieht dann so aus

  1. <?xml version="1.0"?>
  2. <config>
  3.     <modules>
  4.         /* Definiert mein Modul und dessen Version */
  5.         <Mycompany_Mymodule>
  6.             <version>0.0.1</version>
  7.         </Mycompany_Mymodule>
  8.     </modules>
  9.     <global>
  10.         <models>
  11.             <catalog_resource_eav_mysql4>
  12.                 <rewrite>
  13.                     <category_flat>Mycompany_Mymodel_Model_Flat</category_flat>
  14.                 </rewrite>
  15.             </catalog_resource_eav_mysql4>
  16.             <!-- Nach obigem Schema würde das XML so aussehen was nicht funktioniert -->
  17. <!--        <catalog> -->
  18. <!--            <rewrite> -->
  19. <!--                <resource_eav_mysql4_category_flat>Mycompany_Mymodel_Model_Flat</resource_eav_mysql4_category_flat> -->
  20. <!--            </rewrite> -->
  21. <!--        </catalog> -->
  22.         </models>
  23.     </global>
  24. </config>

Der Grund dafür das das auskommentierte XML-Snippet nicht funktioniert liegt, soweit ich das verstande habe, darin das der Aufruf zum Laden eines Resource-Models in Magento so aussieht.

  1. Mage::getResourceModel('catalog/category_flat');

Um diese Anfrage zu bewältigen schaut Magento nun im config.xml des Modules Mage/Catalog nach unter welchem Pfad die Resource-Model-Klassen des Moduls abgelegt sind. In Mage/Catalog/etc/config.xml kann man das im Tag

  1. <resourceModel>

nachlesen.

  1. <global>
  2.     <models>
  3.         <catalog>
  4.             <class>Mage_Catalog_Model</class>
  5.             <resourceModel>catalog_resource_eav_mysql4</resourceModel>
  6.         </catalog>
  7.     ....

Magento hat also

  1. catalog/category_flat

automatisch zu

  1. catalog_resource_eav_mysql4/category_flat

ergänzt.

Hier kann man auch erkennen das der Teil vor dem Schrägstrich das Tag außerhalb des rewrite-Tags darstellt und der Teil nach dem Schrägstrich den restlich Pfad zur überschreibenden Klasse angibt.

- - - - - - - - - - - - - - - - - - - - - - - - - - - -

Beispiel #2 - Überschreiben eines Blocks

Im zweiten Teil wollen wir eine Methode aus dem Block “Popular” (Erstellt die Box mit den beliebtesten Tags) des Moduls Tag überschreiben. Standardisiert werden die 20 beliebtesten Tags ausgelesen, wir wollen aber nur die beliebtesten 10 Tags angezeigt bekommen.

Im ersten Schritt erstellen wir einen neuen Ordner “Block” in unserem Modul. Angeleht am Tag Modul erstellen wir einen weiteren Ordner “Tag” in diesem Ordner und darin die PHP-Datei Popular.php.

  1.       /* Wir erweitern unser Model/Block mit dem original Model/Block */
  2.    
  3.       class Mage_Mymodul_Block_Tag_Popular extends Mage_Tag_Block_Popular
  4.       {
  5.              protected function _loadTags() {
  6.               if (empty($this->_tags)) {
  7.                   $this->_tags = array();
  8.                   $tags = Mage::getModel('tag/tag')->getPopularCollection()
  9.                       ->joinFields(Mage::app()->getStore()->getId())
  10.                       /*->limit(20)*/
  11.                       /* Wir definieren das Limit der Query neu */
  12.                       ->limit(10)
  13.                       ->load()
  14.                       ->getItems();
  15.  
  16.                   if (!count($tags)) {
  17.                       return $this;
  18.                   }
  19.  
  20.                   $this->_maxPopularity = reset($tags)->getPopularity();
  21.                   $this->_minPopularity = end($tags)->getPopularity();
  22.                   $range = $this->_maxPopularity - $this->_minPopularity;
  23.                   if (!$range) {
  24.                       $range = 1;
  25.                   }
  26.  
  27.                   foreach ($tags as $tag) {
  28.                       if (!$tag->getPopularity()) {
  29.                           continue;
  30.                       }
  31.  
  32.                       $tag->setRatio(($tag->getPopularity() - $this->_minPopularity) / $range);
  33.                       $this->_tags[$tag->getName()] = $tag;
  34.                   }
  35.                   ksort($this->_tags);
  36.               }
  37.               return $this;
  38.           }   
  39.       }

Wir haben nun die Methode überarbeitet und das SQL-Limit auf 10 gesetzt. Nun müssen wir wie beim Überlagern des Model in unserer config.xml dafür sorgen, dass nun der Block mit unserem Block überschrieben wird. Hierzu fügen wir folgenden Code in unsere config.xml ein:

  1.       <blocks> /* Blocks */
  2.             <tag>/* Modul */
  3.                   <rewrite>
  4.                         /* Welcher Block soll überlagert werden */
  5.                         <popular>Mage_Mymodul_Block_Tag_Popular</popular>
  6.                   </rewrite>
  7.             </tag>
  8.       </blocks>

Unsere neue config.xml sieht nun folgendermaßen aus:

  1.       <?xml version="1.0"?>
  2.       <config>
  3.           <modules>
  4.               /* Definiert mein Modul und dessen Version */
  5.               <Mage_Mymodul>
  6.                   <version>0.2.0</version>
  7.               </Mage_Mymodul>
  8.           </modules>
  9.  
  10.           <global>       
  11.               <models>
  12.                   /* Definiert mein Modul und das zugehörige Model */
  13.                   <mymodul>
  14.                       <class>Mage_Mymodul_Model</class>               
  15.                   </mymodul>
  16.                   <core> /* Modul Core */
  17.                       <rewrite> /* überlagere/überschreibe */
  18.  /* Welches Model soll überschrieben werden, Wert ist unser neues Model */
  19.                           <design_package>Mage_Mymodul_Model_Design_Package</design_package>
  20.                       </rewrite>
  21.                   </core>
  22.               </models>
  23.  
  24.               <blocks>           
  25.                   <tag>
  26.                        <rewrite>
  27.                           <popular>Mage_Mymodul_Block_Tag_Popular</popular>
  28.                       </rewrite>
  29.                   </tag>           
  30.               </blocks>
  31.           </global>   
  32.       </config>



 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs