Teil 1 "ClassOverloading" aus der Serie "updatesichere Anpassungen in GX2"

Thema wurde von Nonito (Gambio), 31. Januar 2012 erstellt.

  1. Nonito (Gambio)

    Nonito (Gambio) Administrator

    Registriert seit:
    21. April 2011
    Beiträge:
    279
    Danke erhalten:
    134
    Danke vergeben:
    52
    Aufmerksame Leser dürften den nachfolgenden Text bereits aus einem anderen Thread kennen. Ich nehme diesen als ersten Teil unserer neuen Serie "updatesichere Anpassungen in GX2" auf.


    Mit dem Service Pack 1.1 bzw. der Release v2.0.7 führen wir das ClassOverloading in weite Teile des Shops ein. Damit können Code-Anpassungen an allen Klassen in z.B. includes/classes/ und includes/modules/ update-sicher vorgenommen werden.

    Nehmen wir an, wir wollten die Klasse xtcPrice überladen. Hierfür muss im Vezeichnis user_classes/overloads ein Unterverzeichnis angelegt werden, dessen Name dem der zu überladenen Klasse entspricht, d.h. in diesem Fall ein Unterverzeichnis "xtcPrice".

    In diesem Unterverzeichnis legen wir nun eine PHP-Datei an, die die Klassendefinition der erweiternden Klasse enthält, z.B. der Klasse "test1_xtcPrice". Der Name dieser PHP-Datei muss folgenden Aufbau haben: KLASSENNAME.inc.php, d.h. in diesem Beispiel "test1_xtcPrice.inc.php

    Die Klasse "test1_xtcPrice" soll im Code dabei nicht direkt von der Klasse "xtcPrice" erben, sondern von der Klasse "test1_xtcPrice_parent". Hier muss also auf die Endung "_parent" geachtet werden. Die fertige Klassendefinition sieht somit wie folgt aus:
    Code:
    class test1_xtcPrice extends test1_xtcPrice_parent {
    	...
    }
    
    Ein fertiges Code-Beispiel, mit der die Ausgabe der Funktion xtcPrice->xtcFormat() update-sicher manipuiliert wird, befindet sich im Verzeichnis user_classes/overloads/_samples/xtcPrice.

    Mehrfaches Überladen derselben Klasse durch verschiedene Entwickler ist ebenfalls möglich. Ein Beispiel dafür befindet sich im Verzeichnis user_classes/overloads/_samples/FooterContentView. Hier liegen mehrere Klassen, die alle die FooterContentView nacheinander überladen, um die Ausgabe des Footers zu manipulieren.
     
  2. Christel Schrader

    Christel Schrader Neues Mitglied

    Registriert seit:
    2. März 2012
    Beiträge:
    2
    Danke erhalten:
    0
    Wenn ich in der Klasse xtcPrice mehrere Funktionen überladen möchte, kann ich die dann alle in die gleiche Datei nach einander reinschreiben?
     
  3. Avenger

    Avenger G-WARD 2012/13/14/15

    Registriert seit:
    26. April 2011
    Beiträge:
    4.771
    Danke erhalten:
    1.478
    Danke vergeben:
    89
    Ja, sicher...
     
  4. Burn

    Burn Mitglied

    Registriert seit:
    9. Mai 2011
    Beiträge:
    18
    Danke erhalten:
    2
    Danke vergeben:
    2
    Hallo zusammen,

    ich poste meine Frage mal hier, da es evtl. dem ein oder anderem auch helfen wird.

    Ich habe derzeit Änderungen in /system/views/product_info/ProductInfoContentView.inc.php vorgenommen.
    Diese Änderungen wollte ich jetzt "updatesicher" machen.

    Dazu habe ich die folgende Datei angelegt /user_classes/overloads/ProductInfoContentView/blub_ProductInfoContentView.inc.php und meinen Code eingefügt.

    Ich brauch jetzt aber unbedingt die Werte aus "$p_coo_product->data['products_id']". In der ProductInfoContentView.inc.php funktioniert es aber in meiner Überladenen Klasse nicht. Ich weiß einfach nicht weiter. Evtl. kann mir ja jemand einen Hinweis geben.

    Danke und viele Grüße
    Burn
     
  5. Avenger

    Avenger G-WARD 2012/13/14/15

    Registriert seit:
    26. April 2011
    Beiträge:
    4.771
    Danke erhalten:
    1.478
    Danke vergeben:
    89
    Welche Methoden hast Du denn wie überladen?
     
  6. Burn

    Burn Mitglied

    Registriert seit:
    9. Mai 2011
    Beiträge:
    18
    Danke erhalten:
    2
    Danke vergeben:
    2
    oh man das war schon der entscheidende hinweis :). Zumindest hab ich mal die Augen auf gemcht.

    ich habe statt der funktione get_html die build_html benutzt. so gehts:

    Code:
     class lf_ProductInfoContentView extends lf_ProductInfoContentView_parent {
    
    
        function get_html($p_coo_product, $p_current_category_id = 0)
        {
    
    //Sonderangebot - Preis und Angebotsende
            $special_price_query = xtc_db_query("select status, date_format(date_sub(expires_date, interval 1 day), '%d.%m.%Y') as expire from specials where products_id = '". stripslashes($p_coo_product->data['products_id']) ."'");
            $special_price_query = mysql_fetch_row($special_price_query);
            $special_price = $special_price_query[0];
            $special_expire = $special_price_query[1];
            $this->set_content_data('PRODUCTS_SPECIAL_PRICE', $special_price);
            $this->set_content_data('PRODUCTS_SPECIAL_EXPIRE', $special_expire);
    
    
    
            return parent::get_html($p_coo_product, $p_current_category_id = 0);
        }
    danke!
     
  7. Tobias Michaelis

    Tobias Michaelis Erfahrener Benutzer

    Registriert seit:
    31. August 2011
    Beiträge:
    746
    Danke erhalten:
    42
    Danke vergeben:
    50
    Habe soeben einen Ordner erstellt in user_classes/overloads

    ImageSliderContentView

    In diesen Ordner habe ich die Datei ImageSliderContentView.inc.php kopiert und umbenannt in AS_ImageSliderContentView.inc.php

    Die Zeilen habe ich wie folgt geändert.

    PHP:
    class AS_ImageSliderContentView extends AS_ContentView_parent
    {
      
    /*
       * constructor
       */
        
    function ImageSliderContentView()
        {
            
    $this->set_template('module/image_slider.html');
        }


        function 
    get_html($p_slider_id$p_language_id)
        {
    Jetzt bekomme ich folgende Fehlermeldung:

    Code:
    Fatal error: Class 'AS_ContentView_parent' not found in /www/htdocs/w00e9da9/augenshop-online.de/user_classes/overloads/ImageSliderContentView/AS_ImageSliderContentView.inc.php on line 13
     
  8. Tobias Michaelis

    Tobias Michaelis Erfahrener Benutzer

    Registriert seit:
    31. August 2011
    Beiträge:
    746
    Danke erhalten:
    42
    Danke vergeben:
    50
    Oh mein Gott...... ich lach mich schlapp.... hab den Fehler grad beim einstellen gesehen:

    Code:
    class AS_ImageSliderContentView extends AS_ImageSliderContentView_parent
    {
      /*
       * constructor
       */
    	function ImageSliderContentView()
    	{
    		$this->set_template('module/image_slider.html');
    	}
    
    
     
  9. Nonito (Gambio)

    Nonito (Gambio) Administrator

    Registriert seit:
    21. April 2011
    Beiträge:
    279
    Danke erhalten:
    134
    Danke vergeben:
    52
    Dies hier
    PHP:
    class AS_ImageSliderContentView extends AS_ContentView_parent
    sollte stattdessen heißen:
    PHP:
    class AS_ImageSliderContentView extends AS_ImageSliderContentView_parent
     
  10. Tobias Michaelis

    Tobias Michaelis Erfahrener Benutzer

    Registriert seit:
    31. August 2011
    Beiträge:
    746
    Danke erhalten:
    42
    Danke vergeben:
    50
    Danke Nonito, habe es selbst grad gemerkt.

    In der besagten Klasse habe ich die Thumbs nun auf 5px eingestellt, dennoch sprengen diesen fast den Bildschirm. So ganz richtig kann das aber von mir dann auch nicht sein.
     
  11. Nonito (Gambio)

    Nonito (Gambio) Administrator

    Registriert seit:
    21. April 2011
    Beiträge:
    279
    Danke erhalten:
    134
    Danke vergeben:
    52
    Ich brauche mehr Details ;)
     
  12. Tobias Michaelis

    Tobias Michaelis Erfahrener Benutzer

    Registriert seit:
    31. August 2011
    Beiträge:
    746
    Danke erhalten:
    42
    Danke vergeben:
    50
    Es geht um die Thumbs im Teaser Slider.

    In der Datei ImageSliderContentView.inc.php im Ordner /Templates/EyeCandy/Source/classes/ habe ich die Größe von 60px auf 5px angepasst. Danach eben das Classoverloading eingerichtet, damit es bei einem späteren Update sicher ist.

    Danach die Originalsatei wieder geändert auf 60px.

    Leider nix gebracht.

    Die schnellere Lösung war nun, die Grafiken einfach kleiner zu machen und die Originaldatei zu nutzen. Die Grafiken habe ich nun auf 15px angepasst. Sieht schick, nur sollten die jetzt nicht eigentlich 60px groß sein???
     
  13. Timo (Gambio)

    Timo (Gambio) Administrator

    Registriert seit:
    23. Juni 2011
    Beiträge:
    1.688
    Danke erhalten:
    651
    Danke vergeben:
    46
    Hallo Tobias,
    der Quellcode wird von dem aktuellen Slider nicht mehr berücksichtigt. Im aktuellen Slider gibt es keine nachträgliche Größenanpassung mehr, sondern die Bilder werden in ihrer Originalgröße dargestellt.

    MfG,
    Timo
     
  14. Tobias Michaelis

    Tobias Michaelis Erfahrener Benutzer

    Registriert seit:
    31. August 2011
    Beiträge:
    746
    Danke erhalten:
    42
    Danke vergeben:
    50
    Aha! Danke Timo.
     
  15. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    14. Juli 2011
    Beiträge:
    988
    Danke erhalten:
    69
    Danke vergeben:
    128
    Das könnte man ja einfach so hinnehmen und umsetzen :) Aber kann mir jemand den Hintergrund erklären? Ist das PHP-typisch oder eine Gambio Besonderheit?
     
  16. Avenger

    Avenger G-WARD 2012/13/14/15

    Registriert seit:
    26. April 2011
    Beiträge:
    4.771
    Danke erhalten:
    1.478
    Danke vergeben:
    89
    Beides.....

    Die Klassenvererbung selbst ist natürlich in PHP definiert.

    Aber die Flexibilität, die man hier hat, nämlich die automatische Erzeugung der "xxxxx_parent"-Klasse um einfache Möglichkeiten der Mehrfachüberladung einer Klasse ohne Eingriffe in den PHP-Code zu haben, ist eine spezielle Gambio-Entwicklung, (OXID macht das ähnlich, und hat das Verfahren eigentlich erfunden.)

    Ohne diesen Mechanismus müsste man bei mehrfacher Überladung etwa folgendes machen:

    Im Programm hat man die

    PHP:
    class Basisklasse
    {
       .... 
    Klassencode
    }
    und verwendet dann im Programm Basisklasse::eine_methode();

    Wenn man dann diese Basisklasse erweitern will (Entwickler 1)

    PHP:
    class erste_Erweiterungsklasse extends Basisklasse
    {
       .... 
    Klassencode
    }
    Und Entwickler 2:

    PHP:
    class zweite_Erweiterungsklasse extends Basisklasse
     
    {
        .... 
    Klassencode
     
    }
    Problem ist nur: um die Erweiterungen der Basisklasse in erste_Erweiterungsklasse verwenden zu können, müsste man dann erste_Erweiterungsklasse::eine_neue_methode() verwenden

    Analog gilt das für die zweite Erweiterung.

    Um das zu vermeiden, und zusätzlich zu verhindern, dass Entwickler 1 und Entwickler 2 voneinander wissen müssen und/oder sich gar in die Quere kommen, haben sich kluge Köpfe diesen Umweg über die "_parent"-Klasse ausgedacht, der alle diese Probleme löst...

    Und wichtig: man kann auch die neuen Methoden und Eigenschaften der "erste_Erweiterungsklasse" und "zweite_Erweiterungsklasse" mit "Basisklasse::eine_neue_methode()".

    Und man hat in der "Basisklasse" dann zusätzliche alle neuen/geänderten Methoden und Eigenschaften der Erweiterungsklassen zur Verfügung....

    Also einfach als Kochrezept hinnehmen, und gut ist.
     
  17. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    14. Juli 2011
    Beiträge:
    988
    Danke erhalten:
    69
    Danke vergeben:
    128
    Vielen Dank. Jetzt hab ich das verstanden.
     
  18. Avenger

    Avenger G-WARD 2012/13/14/15

    Registriert seit:
    26. April 2011
    Beiträge:
    4.771
    Danke erhalten:
    1.478
    Danke vergeben:
    89
    Sicher??? :)
     
  19. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    14. Juli 2011
    Beiträge:
    988
    Danke erhalten:
    69
    Danke vergeben:
    128
    Ja sicher! Objektorientierte Programmierung ist nichts neues für mich. Mich hat nur die _parent Sache gewundert. Nun ist klar, dass diese Klasse automatisch generiert wird und somit einige Probleme (z.B. Mehrfachüberschreibung - nicht -Überladung, oder?! ;) ) löst.

    Aber was passiert wenn Entwickler 1 und Entwickler 2 die gleiche Funktion überschreiben?
     
  20. Avenger

    Avenger G-WARD 2012/13/14/15

    Registriert seit:
    26. April 2011
    Beiträge:
    4.771
    Danke erhalten:
    1.478
    Danke vergeben:
    89
    Wenn sie in Ihrer überladenden Methode "parent::meine_methode()" aufrufen werden alle vererbten "meine_methode()" in allen Klassen ausgeführt...

    Es entsteht ja im Grunde eine Kette von überladenden "meine_methode()" in den Klassen.

    Wenn "parent::meine_methode()" nicht aufgerufen wird, geht das natürlich schief, und der Entwickler wird standrechtlich erschlagen!

    Das bedeutet natürlich auch, dass die Klassen mit der Überladungsmöglichkeit im Hinterkopf konzipiert sein müssen....

    Wenn Du Dir z.B. mal meine "AdvancedSearchResult"-Klasse unter http://www.gambio-forum.de/threads/...n-Artikeldetails?p=30235&viewfull=1#post30235 ansiehst, dann stellst Du fest, dass die so gestaltet ist, dass man seine eigenen Daten dort dazu geben kann.

    Beispiel:

    In der Basisklasse ist folgendes definiert:

    PHP:
      function get_search_fields()
      {
        return 
    "
            p.products_id,
            p.products_price,
            p.products_model,
            p.products_quantity,
            p.products_shippingtime,
            p.products_fsk18,
            p.products_image,
            p.products_weight,
            p.products_tax_class_id,
            p.products_vpe,
            p.products_vpe_status,
            p.products_vpe_value,
            pd.products_name,
            pd.products_short_description,
            pd.products_description"
    ;
      }
    Die "Overload"-Klasse hat die Definition

    PHP:
      function get_search_fields()
      {
        
    $search_fields=parent::get_search_fields();
        
    //Add product item codes fields to search fields
        
    $search_fields='
          pic.code_isbn,
          pic.code_upc,
          pic.code_mpn,
          pic.code_jan,
          pic.brand_name,'
    .
          
    $search_fields;

        return 
    $search_fields;
      }
    Dort holt man sich also die in allen "parent::"-Klassen definierten Felder, und packt seine eigenen Felder dann an den Anfang dieser Liste....

    Man muss also auch sehr genau verstehen, wie die zu überladende Methode funktioniert.

    Und die Entwickler der Basismethode müssen eingeplant haben, dass jemand die vielleicht überladen möchte, und sein eigenes Ding dazu packen will.

    Und da gibt es in einigen Gambio-Klassen durchaus noch Nachholbedarf, vor allem in den View-Klassen...

    In diesem Thread ( http://www.gambio-forum.de/threads/...-Module-in-SP1.1?p=28793&viewfull=1#post28793 ) hatte ich schon einige verbessrungswürdige Dinge dokumentiert