1. Attribute anlegen
Zuerst müssen wir ein einfaches Attribute anlegen. Dazu wählen wir Catalog/ Attributes/ Manage Attributes. Ich gehe bei dem neuen Attribute davon aus das als Code “datenblatt” gewählt wurde. Der Einfachhalt halber verzichte ich darauf die Datenblätter in einer separaten Kreuztabelle zu speichern – stattdessen werden die Zuordnungen direkt in das Datenbankfeld geschrieben. Aus diesem Grund sollte der Typ des Attributes auf “TextArea” stehen. Zusätzlich muss das neue Attribute, damit es sichtbar ist, noch dem Default-Set zugeordnet werden.
2. Datenbank anpassen
Magento baut die Formulare teilweise anhand der Felder in der Datenbank zusammen. Es nutzt dafür ein sogenanntes EAV-Model. Dieses Model sorgt salopp gesagt dafür das wir fast beliebig viele neue Felder schaffen können ohne unser Datenbank-Layout zu verändern. Zudem haben wir die Möglichkeit anzugeben wie die Formularfelder erstellt und gespeichert werden. Hierzu gibt es den Frontend-Input-Renderer (Feldname: . Dieser kümmert sich vollständig um die Darstellung der Formularelemente. Das Gegenstück hierzu ist das Backend-Model (Feldname: ) welches sich um die Speicherung und Validierung der Eingaben kümmert.
Um nun unser Feld “datenblatt” optisch und funktional anzupassen gehen wir wie folgt vor:
Zuerst Datenbank z.B. im phpMyAdmin öffnen. Dann zur Tabelle eav_attribute wechseln und dort den Datensatz mit attribute_code = “datenblatt” heraussuchen und bearbeiten:
backend_model: | test/product_backend_datenblatt |
frontend_input_renderer: | Test_Test_Renderer_Datenblatt |
In diesem Fall weisen wir Magento an das Model Product/Backend/Datenblatt aus dem Modul Test zum Speichern unserer Daten zu verwenden. Im zweiten geben wir an das die Darstellung über die Class Test_Test_Renderer_Datenblatt erfolgt. Wichtig ist das, warum auch immer, das Backend-Model auf ein Model verweist – es muss also vor dem Slash das Modul stehen. Der Frontend-Input-Renderer dagegen erwartet direkt eine Class!
3. Frontend-Input-Renderer erstellen
Hierzu erstellen wir in app/code/local/Test/Test/Renderer die Datei Datenblatt.php mit folgendem Inhalt:
Datei: app/code/local/Test/Test/Renderer/Datenblatt.php
<?php
class Test_Test_Renderer_Datenblatt extends Varien_Data_Form_Element_File
{
/**
* Retrieve Element HTML fragment
*
* @return string
*/
public function getElementHtml()
{
$html = '';
// Value lesen und Zeilenweise trennen
$data = $this->getData('value');
$lines = explode("\n", $data);
$html .= '<table>';
$html .= '<col width="110" /> ';
$html .= '<col width="150" /> ';
$html .= '<col /> ';
$html .= ' <thead> <tr> <th>Datenblatt-Nr.</th> <th>Aktuelle Datei</th> <th>Neue Datei</th> </tr> </thead> ';
$html .= ' <tbody>';
$i = 0;
foreach( $lines AS $cur ) {
$i++;
// pro Zeile wird genau ein Datensatz getrennt mit einem Gleich-Zeichen erwartet
$tmp = explode('=', $cur);
if ( count($tmp) != 2 ) {
continue;
}
list($nr, $file) = $tmp;
$nr = trim($nr);
$file = trim($file);
// Eine leere Datenblatt-Nummer akzeptieren wir nicht
if ( $nr == '' ) {
continue;
}
// HTML-Table aufbauen
$html .= ' <tr>';
$html .= ' <td> <input type="text" name="'.$this->getName().'[nr]['.$i.']" style="width: 100px" value="'.$this->_escape( $nr ).'" /> </td> ';
$html .= ' <td> '.$file;
$html .= ' <input type="hidden" name="'.$this->getName().'[filename]['.$i.']" value="'.$this->_escape($file).'" />';
$html .= ' </td> ';
$html .= ' <td> <input type="file" name="datenblatt_file_'.$i.'" style="width: 100px" /> </td> ';
$html .= ' </tr>';
}
$html .= ' </tbody>';
$html .= ' <tr>';
$html .= ' <td> <input type="text" name="'.$this->getName().'[nr][new]" style="width: 100px" /> </td> ';
$html .= ' <td> Neues Datenblatt </td>';
$html .= ' <td> <input type="file" name="datenblatt_file_new" style="width: 100px" /> </td> ';
$html .= ' </tr>';
$html .= '</table>';
// und ein kleiner Hinweis wie man Datenblätter löschen kann
$html .= '<small>Entfernen Sie die Datenblatt-Nr. um das Datenblatt zu löschen.</small>';
return $html;
}
}
4. Backend-Model zum Speichern der Daten
Wie sich unschwer erkenne lässt können wir unsere Daten nun hübsch darstellen. Was fehlt ist der Teil unserer Anwendung der sich darum kümmert das die Daten in Datenbank bzw. Dateisystem abgelegt werden. Hier kommt das Backend-Model ins Spiel: Datei: app/code/local/Test/Test/Renderer/Datenblatt.php
<?php
class Test_Test_Model_Product_Backend_Datenblatt extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
{
public function beforeSave($object)
{
$path = Mage::getBaseDir('media') . DS . 'catalog' . DS . 'datenblatt';
$name = $this->getAttribute()->getName();
$inputs = $object->getData( $name );
if ( !is_array($inputs['nr']) ) {
return;
}
$res = array();
foreach( $inputs['nr'] AS $i => $nr ) {
if ( $nr == '' ) {
continue;
}
try {
$uploader = new Varien_File_Uploader( 'datenblatt_file_'.$i );
//$uploader->setAllowedExtensions(array('pdf'));
$uploader->setAllowRenameFiles(true);
$uploader->save($path);
$res[] = $nr.'='.$uploader->getUploadedFileName();
} catch (Exception $e) {
if( isset($inputs['filename'][$i]) ) {
$res[] = $nr.'='.$inputs['filename'][$i];
}
}
}
$object->setData($this->getAttribute()->getName(), join("\n", $res) );
return;
}
}
Fazit
In Magento ist es sehr einfach Produkte um weitere Standard-Eingabefelder zu erweitern. Sollen diese Eingaben jedoch besondere Eigenschaften bzw. Features aufweisen wird die Aufgabe ein wenig komplexer ist jedoch durchaus zu bewältigen. Der Aufwand lohnt sich in der Regel jedoch: das Pflegen von Produkten wird durch spezialisierte Eingaben deutlich einfacher und ist weniger fehleranfällig.