Eigene Artikelfelder im Adminbereich 2.7.x

Thema wurde von javierfrangenheim, 15. Februar 2016 erstellt.

  1. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    Hallo.

    Ich hatte bisher eigene Felder für die Artikel im Adminbereich angelegt.
    Diese wurden über die
    admin/includes/classes/categories.php
    mit der Funktion

    Code:
    insert_product($products_data, $dest_category_id, $action = 'insert')
    ab ca. Zeile 913 gespeichert.

    Nun musste ich feststellen daß in der Version 2.7.x dies nicht mehr funktioniert. Diese Funktion ist scheinbar unwirksam.
    Kann mir jemand sagen wo sich diese Funktion jetzt befindet?

    Danke und Gruß
     
  2. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    push...

    Ich habe in der neuen Beta gesehen daß es neue overloads/_samples gibt.

    Hier gibt es jetzt auch "ProductWriteService".
    Kann mir jemand auf die Sprünge helfen wie ich hier neue Artikelfelder integriere?

    Danke und Gruß
     
  3. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Hallo Javier,

    wo speicherst du aktuell die Daten in der Datenbank? Also in welcher Tabelle/Spalte? Davon ausgehend können wir dir weiterhelfen.
     
  4. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    Hallo.

    Ich habe die Tabelle PRODUCTS um das Feld products_region (und einige mehr) erweitert.

    Die würde ich gerne speichern wie früher mit Hilfe der
    admin/includes/classes/categories.php (siehe oben)

    Gruß
     
  5. barbara

    barbara G-WARD 2014-2020

    Registriert seit:
    14. August 2011
    Beiträge:
    35.543
    Danke erhalten:
    11.305
    Danke vergeben:
    1.611
    #5 barbara, 29. Februar 2016
    Zuletzt bearbeitet: 29. Februar 2016
    Das Klingt nach den Extrafeldern, für die Cyrus für die Version 2.1 - 2.6 Anleitungen geschrieben hat.
    Die Anleitung für 2.6 geht auch in der 2.7 noch.

    Schau bitte mal, ob es das ist:
    (Link nur für registrierte Nutzer sichtbar.)

    Die dazugehörenden Overloads findest du hier:
    (Link nur für registrierte Nutzer sichtbar.)
     
  6. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Das kann man mittlerweile elegant mit dem ProductService über AddOn-Values lösen. Heute Abend bekomme ich das nicht mehr erklärt. Wir haben in den letzten 2 Wochen auch einiges an Dokumentation geschrieben. Die Inhalte werden gerade aufbereitet, damit sie in Kürze auf http://developers.gambio.de online gestellt werden.

    Ich versuche morgen ins Detail zu gehen.
     
  7. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    Danke für den Hinweis Barbara...

    Für die Versionen bis 2.6 gilt das alles noch.
    Bis dahin ging das Speichern der Zusatzfelder tadellos (siehe oben).

    Ab 2.7 kann ich nur über die Veränderungen der Dateien im GXEngine und der admin/includes/modules/set_product_data.inc.php speichern. Das ist aber nicht Sinn der Sache.

    Ich warte mal auf die Doku von Moritz...
     
  8. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Hallo,

    ich habe heute viel um die Ohren, so dass ich es voraussichtlich nicht mehr heute mit einer Antwort schaffe. Ich habe es aber nicht vergessen!
     
  9. M. Zitzmann

    M. Zitzmann Erfahrener Benutzer

    Registriert seit:
    3. März 2016
    Beiträge:
    383
    Danke erhalten:
    125
    Danke vergeben:
    41
    Hallo.

    Die Lösung würde mich auch interessieren...

    ;)
     
  10. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Hallo,

    mit etwas Verspätung hier nun das versprochene Tutorial. Ich habe mich für das Speichern eines Einkaufpreises entschieden. Als Erstes benötigen wir also ein Eingabefeld auf der "Artikel bearbeiten"-Seite. Das funktioniert über den AdminEditProduct-Extender. Dazu wird ein Overload der AdminEditProductExtenderComponent-Klasse angelegt (user_classes/overloads/AdminEditProductExtenderComponent/EkpFormExtender.inc.php)
    PHP:
    /**
     * Class EkpFormExtender
     *
     * Adds a form for a EKP value to the edit product page
     * 
     * @see AdminEditProductExtenderComponent
     */
    class EkpFormExtender extends EkpFormExtender_parent
    {
        
    /**
         * Overloaded "proceed" method. 
         */
        
    public function proceed()
        {
            
    parent::proceed();

            
    $ekp 0;

            if(isset(
    $this->v_data_array['GET']['pID']))
            {
                
    $productId = (int)$this->v_data_array['GET']['pID'];

                
    /** @var ProductReadService $productReadService */
                
    $productReadService StaticGXCoreLoader::getService('ProductRead');

                
    /** @var StoredProduct $product */
                
    $product $productReadService->getProductById(new IdType($productId));

                try
                {
                    
    $ekp $product->getAddonValue(new StringType('ekp'));
                }
                catch(
    InvalidArgumentException $e)
                {
                    
    // product has no EKP yet
                
    }
            }

            
    $html '<div class="grid control-group span6 remove-border">
                        <div class="span6">
                            <label>EKP</label>
                        </div>
                        <div class="span6">
                            <input name="ekp" type="text" value="' 
    $ekp '" />
                        </div>
                    </div>'
    ;

            
    $this->v_output_buffer['top']['ekp'] = array('title' => 'EKP''content' => $html);
        }
    }
    Das wars auch schon für die Anzeige des EKP-Felds mit dem aktuellen Wert.

    Jetzt kümmern wir uns um das Speichern. Dazu nutzen wir den AdminCategories-Extender, der für das Verändern von Kategorie- und Artikeldaten der passende Einstiegspunkt ist. Dazu wird ein Overload der AdminCategoriesExtenderComponent-Klasse angelegt (user_classes/overloads/AdminCategoriesExtenderComponent/StoreEkpExtender.inc.php):
    PHP:
    /**
     * Class StoreEkpExtender
     * 
     * Store product's EKP
     * 
     * @see AdminCategoriesExtenderComponent
     */
    class StoreEkpExtender extends StoreEkpExtender_parent
    {
        
    /**
         * Overloaded "proceed" method.
         */
        
    public function proceed()
        {
            
    parent::proceed();

            if(isset(
    $this->v_data_array['GET']['action']) && $this->v_data_array['GET']['action'] === 'update_product')
            {
                
    $productId = (int)$this->v_data_array['GET']['pID'];

                
    /** @var ProductReadService $productReadService */
                
    $productReadService StaticGXCoreLoader::getService('ProductRead');

                
    /** @var StoredProduct $product */
                
    $product $productReadService->getProductById(new IdType($productId));

                
    $addonValues $product->getAddonValues()->getArray();
                
    $addonValues['ekp'] = (double)$this->v_data_array['POST']['ekp'];
                
    $addonValueCollection MainFactory::create('KeyValueCollection'$addonValues);

                
    $product->addAddonValues($addonValueCollection);

                
    /** @var ProductWriteService $productWriteService */
                
    $productWriteService StaticGXCoreLoader::getService('ProductWrite');

                
    $productWriteService->updateProduct($product);
            }
        }
    }
    Das wars auch schon! Der EKP wird als AddonValue gespeichert und benötigt daher keine Anpassungen in der Datenbank.

    Optional:
    Angenommen wir möchten aber in eine neue Spalte in der Tabelle products speichern. Nennen wir sie "einkaufspreis". So sagen wir dem Product-Service, dass er den AddonValue "ekp" in der Spalte "einkaufspreis" speichern soll:
    Wir benötigen einen Overload der Klasse ProductAddonValueStorage (user_classes/overloads/ProductAddonValueStorage/AddEkpField.inc.php)
    PHP:
    /**
     * Class AddEkpField
     *
     * @category   System
     * @package    Product
     * @subpackage Storages
     *             
     * @see ProductAddonValueStorage            
     */
    class AddEkpField extends AddEkpField_parent
    {
        
    /**
         * Maps ekp addon value to einkaufspreis field in products table
         *
         * @return array
         */
        
    protected function _getExternalFieldsArray()
        {
            
    $externalFields parent::_getExternalFieldsArray();
            
    $externalFields['products']['fields']['einkaufspreis'] = 'ekp';

            return 
    $externalFields;
        }
    }
    Bei dieser Variante ist der Wert aber nicht mehr über den Product-Service auslesbar. Entsprechend müsste man sich beim Auslesen für die Artikelbearbeitung selbst darum kümmern:
    PHP:
    $db StaticGXCoreLoader::getDatabaseQueryBuilder();
    $ekp = (double)$db->select('einkaufspreis')->from('products')->where('products_id'$productId)->get()->row()->einkaufspreis;
    In der Shopversion 2.7.1 und 2.7.2 gibt es leider einen blöden Bug der verursacht, dass das Speichern nur über den Button "Speichern" jedoch nicht "Aktualisieren" funktioniert. Um das zu beheben muss in der Datei admin/categories.php für die action-Fälle "update_product" und "insert_product" am Ende das xtc_redirect ersetzt werden durch eine Wertzuweisung der Url in die Variable $redirectUrl. Das ist in ca. Zeile 269 und Folgende zu finden. Der Fix wird im nächsten SP enthalten sein.


    Seit heute Abend gibt es übrigens eine Menge neuer Dokumentation auf http://developers.gambio.de. Schaut euch das am besten mal an :).
    Passende Themen: Class-Overloading, Extender-System, Liste aller Extender
     
  11. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    Danke Moritz.

    Funktioniert auf Anhieb.
    Da ich die Felder bereits vorher schon in der Tabelle products hatte habe ich mich für Deine optionale Lösung entschieden und alle drei Dateien verwendet.

    Sehe ich das richtig daß in diesem Falle die Tabelle addon_values_storage nur temporär verwendet wird?

    Gruß
     
  12. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Hallo,

    die Tabelle dürfte dann gar nicht genutzt werden.
     
  13. javierfrangenheim

    Registriert seit:
    7. Juli 2015
    Beiträge:
    16
    Danke erhalten:
    0
    Danke vergeben:
    3
    #13 javierfrangenheim, 7. März 2016
    Zuletzt bearbeitet: 7. März 2016
    Stimmt. Die ist leer...

    Kann ich dann die (user_classes/overloads/AdminCategoriesExtenderComponent/StoreEkpExtender.inc.php) weglassen oder brauche ich die trotzem?

    Dann hätte ich noch eine Frage:
    In der (user_classes/overloads/AdminEditProductExtenderComponent/EkpFormExtender.inc.php) steht u.a.:

    <input name="ekp" type="text" value="' . $ekp . '" />

    Wie kann ich hier eine Checkbox realisieren wenn der Feldinhalt nur 1 oder null ist?

    Gruß

    Edit:

    Habs gefunden: Man braucht die php innerhalb des html-Containers nur in Anführungszeichen zu setzen...

    ' . xtc_draw_radio_field('ekp', '1', ($ekp ? True : False)) . '
     
  14. barbara

    barbara G-WARD 2014-2020

    Registriert seit:
    14. August 2011
    Beiträge:
    35.543
    Danke erhalten:
    11.305
    Danke vergeben:
    1.611
    Hallo Moritz,

    bin jetzt gerade dabei und habe eine frage:
    der Ordner "ProductAddonValueStorage" mit der Datei "AddEkpField.inc.php"
    muss nur in den Ordner user_classes und nicht in user_classes/ overloads?
     
  15. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    StoreEkpExtender.inc.php wird trotzdem benötigt. overloads-Ordner hatte ich im Pfad vergessen.
     
  16. M. Zitzmann

    M. Zitzmann Erfahrener Benutzer

    Registriert seit:
    3. März 2016
    Beiträge:
    383
    Danke erhalten:
    125
    Danke vergeben:
    41
    Hallo.

    Danke dafür...
    Geht das analog auch für die Kategorien?
    Kann man diese AddonValue auch für die Kategorien verwenden?

    Ich denke das müsste dann die AdminEditCategoryExtenderComponent sein.


    Gruß
    Mike
     
  17. barbara

    barbara G-WARD 2014-2020

    Registriert seit:
    14. August 2011
    Beiträge:
    35.543
    Danke erhalten:
    11.305
    Danke vergeben:
    1.611
    Rein aus Neugierde ;): Was für Zusatzfelder willst Du in der Kategorie?

    Bei mir funkt das irgendwie nicht ,
    Da habe ich wohl nicht einen Fehler irgendwo...
    Die Extrafelder werden zwar angezeigt, aber ich bekomme weder den Inhalt aus der Datenbank zu sehen, noch wird etwas in der DB gespeichert.
    Mal sehen welchen "." ich übersehen habe. :)



     
  18. M. Zitzmann

    M. Zitzmann Erfahrener Benutzer

    Registriert seit:
    3. März 2016
    Beiträge:
    383
    Danke erhalten:
    125
    Danke vergeben:
    41
    #18 M. Zitzmann, 8. März 2016
    Zuletzt bearbeitet: 9. März 2016
    Hallo Barbara.

    Ich möchte eine zweite Kategoriegruppe (section) erstellen bzw habe diese schon erstellt.
    Das stammt aus den alten xtc/modified Zeiten für eine zweite Kategoriebox, deren Kategorien unabhängig voneinander sind.
    Dazu gibt es ein neues Feld in der Tabelle categories.
    Die Anzeige im Frontend habe ich bereits vorher gelöst.
    Nur die "Deaktivierung" der /admin/includes/classes/categories.php in den neuen Versionen macht mir Kopfschmerzen.
    Da war alles noch einfacher...

    Die Lösung von Moritz für ein Artikelfeld habe ich 1zu1 eingebaut, funktioniert auf Anhieb.
    Analog dazu sind jetzt vermutlich die
    AdminEditCategoryExtenderComponent
    und
    CategoryAddonValueStorage
    zuständig.

    Ich komme nicht weiter mit dem Befehl für die Kategorien analog zu

    if(isset($this->v_data_array['GET']['pID']))
    {
    $productId = (int)$this->v_data_array['GET']['pID'];

    Wie ist denn der Aufruf für das Öffnen der Kategorie?

    Gruß
    Mike

    (wie kann ich hier ein Code-Fenster einfügen???)

    EDIT:
    Habs gefunden:

    if(isset($this->v_data_array['GET']['id']))
     
  19. Moritz (Gambio)

    Moritz (Gambio) Administrator

    Registriert seit:
    26. April 2011
    Beiträge:
    5.786
    Danke erhalten:
    2.693
    Danke vergeben:
    903
    Für das Schreiben des Werts in der Kategorie wird wieder ein Overload der Klasse
    AdminCategoriesExtenderComponent benötigt. Der Code darin sieht beispielsweise so aus (Zusatzfeld ist eine Url):
    PHP:
    class StoreUrlExtender extends StoreUrlExtender_parent
    {
        
    /**
         * Overloaded "proceed" method.
         */
        
    public function proceed()
        {
            
    parent::proceed();
          
            if(isset(
    $this->v_data_array['GET']['action']) && $this->v_data_array['GET']['action'] === 'update_category')
            {
                
    $categoryId = (int)$this->v_data_array['GET']['cID'];
              
                
    /** @var CategoryReadService $categoryReadService */
                
    $categoryReadService StaticGXCoreLoader::getService('CategoryRead');
              
                
    /** @var StoredCategory $category */
                
    $category $categoryReadService->getCategoryById(new IdType($categoryId));
              
                
    $addonValues $category->getAddonValues()->getArray();
                
    $addonValues['url'] = $this->v_data_array['POST']['url'];
                
    $addonValueCollection MainFactory::create('KeyValueCollection'$addonValues);
              
                
    $category->addAddonValues($addonValueCollection);
              
                
    /** @var CategoryWriteService $categoryWriteService */
                
    $categoryWriteService StaticGXCoreLoader::getService('CategoryWrite');
              
                
    $categoryWriteService->updateCategory($category);
            }
        }
    }
    Für die Ausgabe ist ein Overload der Klasse AdminEditCategoryExtenderComponent notwendig. Das passende Beispiel dazu:
    PHP:
    class AddUrlFormExtender extends AddUrlFormExtender_parent
    {
        
    /**
         * Overloaded "proceed" method.
         */
        
    public function proceed()
        {
            
    parent::proceed();
          
            
    $url '';
          
            if(isset(
    $this->v_data_array['GET']['cID']))
            {
                
    $categoryId = (int)$this->v_data_array['GET']['cID'];
              
                
    /** @var CategoryReadService $categoryReadService */
                
    $categoryReadService StaticGXCoreLoader::getService('CategoryRead');
              
                
    /** @var StoredCategory $category */
                
    $category $categoryReadService->getCategoryById(new IdType($categoryId));
              
                try
                {
                    
    $url $category->getAddonValue(new StringType('url'));
                }
                catch(
    InvalidArgumentException $e)
                {
                    
    // category has no URL yet
                
    }
            }
          
            
    $html '<div class="grid control-group span6 remove-border">
                        <div class="span6">
                            <label>URL</label>
                        </div>
                        <div class="span6">
                            <input name="url" type="text" value="' 
    $url '" />
                        </div>
                    </div>'
    ;
          
            
    $this->v_output_buffer['left']['sample'] = array('title' => 'Url''content' => $html);
        }
    }
    Soll wieder außerhalb der addon_values_storage-Tabelle gespeichert werden, ist ein Overload der Klasse
    CategoryAddonValueStorage notwendig. Die Vorgehensweise ist beim Produkt abzuschauen.

    Im Anhang ein Bild, wie man im Forum Code einfügen kann.
     

    Anhänge:

  20. M. Zitzmann

    M. Zitzmann Erfahrener Benutzer

    Registriert seit:
    3. März 2016
    Beiträge:
    383
    Danke erhalten:
    125
    Danke vergeben:
    41
    #20 M. Zitzmann, 9. März 2016
    Zuletzt bearbeitet: 9. März 2016
    Danke Moritz,

    So ähnlich hab ich mir das heute Nacht selbst zusammen gepfrimelt.

    Allerdings geht der CategoryAddonValueStorage nur so:

    PHP:
      protected function _getExternalFieldsArray()
      {
         
    $externalFields parent::_getExternalFieldsArray();
         
    $externalFields = array();
         
    $externalFields['categories']['primary_key'] = 'categories_id';
         
    $externalFields['categories']['fields']  = array('section' => 'section');  
      
         return 
    $externalFields;
      }
    Wenn ich es analog zum Product mache kommt "sql error"

    Super Support....


    Gruß
    Mike