TEE-10 Frontend Feinschliff

Aus Contao Community Documentation

Version vom 5. Februar 2011, 19:46 Uhr von Stefan.sl (Diskussion | Beiträge)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
MsgError.png Unvollständiger Artikel: dieser Artikel ist noch nicht sauber bearbeitet.

Bitte erweitere ihn und entferne erst anschliessend diesen Hinweis.

Tagebuch einer Extension-Entwicklung

betrifft
TYPOlight Version ab TL 2.8
Extensions Extension Creator


Etwas Feinschliff

Einige Details will ich noch verbessern, bevor es endlich an die noch fehlenden Turniermeldungen geht. Insgesamt ist es ein Mischmasch von vielen Kleinigkeiten, die aber teilweise in mehreren Dateien Auswirkungen haben. Es könnte also chaotisch werden :-).

Beginnen wir wir mit /system/modules/gw_turnierpaare/geTurnierpaarliste.php, der Klasse in der die Frontendtemplates gefüllt werden.

class gwTurnierpaarliste extends Module 
{ 
    /** 
     * Template 
     * @var string 
     */ 
    protected $strTemplate = 'gw_turnierpaarliste'; 
    protected $strDetailTemplate = 'gw_turnierpaarliste_detail'; 
    protected $strDetailErrorTemplate = 'gw_turnierpaarliste_error'; 
    public static $strDetailKey = 'info'; 
    public static $StartGruppen = array('KIN I','KIN II', 'JUN I', 'JUN II', 'JUG', 'HGR', 'HGR II', 'SEN I', 'SEN II', 'SEN III', 'SEN IV'); 
    public static $StartKlassen = array('-', 'E','D', 'C', 'B', 'A', 'S', 'PRO', 'LL', 'OL', 'RL', '2. BL', '1. BL');

Zunächst definiere ich mir neben meinem "Defaulttemplate" noch einen Templatenamen für die Detailansicht, und ein "Error-Template", das angezeigt wird, wenn das für die Detailansicht gewünschte Tanzpaar nicht gefunden wird.

Dann folgen 3 statische Variablendeklarationen, dies sind also Klassenvariablen. Die werde ich Klassen übergreifend nutzen, weil die entsprechenden Einträge in mehreren Files genutzt werden, und ich sie nur an einer Stelle editieren möchte. $strDetailKey benötigen wir im Listentemplate, die beiden anderen Variablen im DCA-Record für die Tabelle tl_gw_turnierpaare und für die sortierte Ausgabe nach Startgruppe und -klasse.

Hier verwenden wir sie dann auch (Funktion compileListTemplate()):

... 
      // Nach Altersgruppen sortieren 
      $fieldstartgruppe="''"; 
       foreach(gwTurnierpaarliste::$StartGruppen as $gruppe) 
      { 
        $fieldstartgruppe .= ",'".$gruppe."'"; 
      } 
      $fieldstartklasse="''"; 
      foreach(gwTurnierpaarliste::$StartKlassen as $klasse) 
      {
        $fieldstartklasse .= ",'".$klasse."'"; 
      } 
...

Und auch die Verwendung von $strDetailKey wird angepasst:

... 
        if ( strlen($this->Input->get(gwTurnierpaarliste::$strDetailKey)) ) 
...

Im DCA-Record für die Felder startgruppe, startklasselatein und startklassestandard sinngemäß (Datei /system/modules/gw_turnierpaare/dca/tl_gw_turnierpaare.php):

... 
        'startgruppe' => array 
        ( 
            'label'                   => &$GLOBALS['TL_LANG']['tl_gw_turnierpaare']['startgruppe'], 
            'inputType'               => 'select', 
            'sorting'                 => true, 
            'options'                 => gwTurnierpaarliste::$StartGruppen, 
            'eval'                    => array('mandatory'=>false, 'includeBlankOption' => true) 
        ), 
        'startklasselatein' => array 
        (
            'label'                   => &$GLOBALS['TL_LANG']['tl_gw_turnierpaare']['startklasselatein'], 
            'inputType'               => 'select', 
            'sorting'                 => true, 
            'options'                 => gwTurnierpaarliste::$StartKlassen, 
            'eval'                    => array('mandatory'=>true, 'tl_class' => 'w50') 
        ), 
        'startklassestandard' => array 
        ( 
            'label'                   => &$GLOBALS['TL_LANG']['tl_gw_turnierpaare']['startklassestandard'], 
            'inputType'               => 'select', 
            'sorting'                 => true, 
            'options'                 => gwTurnierpaarliste::$StartKlassen, 
            'eval'                    => array('mandatory'=>true) 
        ), 
...

und schließlich noch im Template für die Übersichtsliste /system/modules/gw_turnierpaare/templates/gw_turnierpaarliste.tpl:

... 
  <td><?php echo '<a href="/{{env::page_alias}}/'.gwTurnierpaarliste::
$strDetailKey.'/'.$paar['alias'].'.html">Detail</a>'; ?> 
...

Hier benutzen wir auch das Insert-Tag {{env::page_alias}}, um den Seitenalias nicht wie bisher hart im Template kodiert zu haben. Das funktioniert jetzt auf jeder Seite, auf der das Frontendmodul eingebunden ist, egal wie diese heißt.

Hier sieht man auch noch eine andere Änderung: $paar['alias']. Ich möchte die Detailseite nicht nur über die numerische ID des Paares aufrufen können, sondern eleganter über einen Seitenalias, z.b. /turnierpaarliste/info/mueller.html.

Dafür definiere ich ein neues varchar(128)-Feld in der tl_gw_turnierpaare-Tabelle (/system/modules/gw_turnierpaare/config/database.sql):

...
  `partnerinvorname` varchar(64) NULL default NULL,
  `alias` varchar(128) NOT NULL default '',
  `startgruppe` varchar(32) NOT NULL default '',
...

Die Definitionen für den DCA-Record klaue ich mir bei tl_article.php aus dem Backend (/system/modules/gw_turnierpaare/dca/tl_gw_turnierpaare.php):

... 
        'alias' => array 
        ( 
            'label'                   => &$GLOBALS['TL_LANG']['tl_gw_turnierpaare']['alias'], 
            'exclude'                 => true, 
            'inputType'               => 'text', 
            'eval'                    => array
            (
                 'rgxp'=>'alnum', 
                 'doNotCopy'=>true, 
                 'spaceToUnderscore'=>true, 
                 'maxlength'=>128, 
                 'tl_class'=>'w50'
            ), 
            'save_callback' => array 
            ( 
                array('tl_gw_turnierpaare', 'generateAlias') 
            ) 
    ), 
...

In die Palette tragen wir das Feld auch noch ein, damit es manuell editierbar bleibt:

    // Palettes 
    'palettes' => array 
    ( 
        '__selector__'                => array('resetpassword'), 
        'default'                     => '{name_legend},partnernachname,partnervorname,partnerinnachname,partnerinvorname,alias;' 
                                      .'{classes_legend},startgruppe,startklasselatein,startklassestandard;' 
...

Und wir müssen den Callback schreiben

  /** 
   * Generate alias from couples names 
   */ 
    public function generateAlias($varValue, DataContainer $dc) 
    { 
        $autoAlias = false; 
        // Generate alias if there is none 
        if (!strlen($varValue)) 
        { 
            $autoAlias = true; 
            $key = $dc->activeRecord->partnernachname; 
            if (strlen($dc->activeRecord->partnerinnachname) > 0 && strcmp($dc->activeRecord->partnernachname, $dc->activeRecord->partnerinnachname)) 
            { 
                $key = $key.'_'.$dc->activeRecord->partnerinnachname; 
            } 
            $varValue = standardize($key); 
        } 
        $objAlias = $this->Database->prepare("SELECT id FROM tl_gw_turnierpaare WHERE id=? OR alias=?") 
                                   ->execute($dc->id, $varValue); 
        // Check whether the page alias exists 
        if ($objAlias->numRows > 1) 
        { 
            if (!$autoAlias) 
            { 
                throw new Exception(sprintf($GLOBALS['TL_LANG']['ERR']['aliasExists'], $varValue)); 
            } 
            $varValue .= '-' . $dc->id; 
        } 
        return $varValue; 
    }

Der Seitenalias ist nachnameherr_nachnamedame, wenn die Nachnamen verschieden sind. Falls sie gleich sind nur nachname. Ein Paar Müller/Schulze wäre also mueller_schulze, ein Ehepaar Maier nur maier. Das ganze wird mit einer eingebauten TL-Funktion standardisiert. Sollte der Alias schon existieren (eher unwahrscheinlich), dann wird die ID hintenan gehängt. Das ist 1:1 so wie bei Seitenaliasen in TL auch.

Im Frontendmodul /system/modules/gw_turnierpaare/gwTurnierpaarliste.php erfolgen dafür nun auch noch Anpassungen. Zunächst in der Funktion obj2Arr, damit das neue Feld auch im Template zur Verfügung steht:

... 
        'id' => $objPaar->id, 
        'alias' => $objPaar->alias, 
        'beschreibung' => $objPaar->beschreibung, 
...

und schließlich in compileDetailTemplate:

  // Compiles the data for the turnierparliste_detail template 
  protected function compileDetailTemplate() 
  { 
    $coupleRow = $this->Database->prepare("SELECT * FROM tl_gw_turnierpaare WHERE id=? OR alias=?") 		  
            ->limit(1) 
            ->execute($this->Input->get(self::$strDetailKey),$this->Input->get(self::$strDetailKey)); 
    if($coupleRow->numRows == 0) 
    { 
          $this->Template = new FrontendTemplate($this->strDetailErrorTemplate); 
    } 
    else 
    { 
      $this->Template = new FrontendTemplate($this->strDetailTemplate); 
      $newArr = $this->obj2Arr($coupleRow); 
      if(strlen($coupleRow->bild) == 0) 
      { 
        $newArr['bild'] = '/system/modules/gw_turnierpaare/icons/default.png'; 
      } 
      else 
      { 
        $newArr['bild'] = $this->getImage($coupleRow->bild, '180', ''); 
        $newArr['bildfullsize'] = $coupleRow->bild; 
      } 
      $this->Template->paar = $newArr; 
    } 
  }

Hier wird entweder nach ID oder nach Alias gesucht. Aufruf der Detailseite würde also sowohl über /info/12.html als auch info/mueller.html funktionieren. Wird kein Datensatz mit dieser ID gefunden, wird das Error-Template ausgegeben, ansonsten wie üblich der Detail-Datensatz.

Schließlich noch das sehr simple neue Template system/modules/gw_turnierpaare/templates/gw_turnierpaarliste_error.tpl:

<div class="<?php echo $this->class; ?> block paarvisitenkarte"<?php echo $this->cssID; ?> 
<?php if ($this->style): ?> style="<?php echo $this->style; ?>"<?php endif; ?>> 
<h3>Dieses Paar existiert leider nicht!</h3>

Da sich rein optisch außer einem Extra Feld im Backend für den Alias nichts getan hat, verzichte ich in diesem Schritt auf Screenshots. Leider ging es auch etwas kreuz und quer mit kleinen Änderungen in mehreren Dateien. Ich hoffe trotzdem man konnte noch folgen...

Diskussion

user: Jürgen

Eine Frage zu der Demoanwendung am Anfang. Diese habe ich installiert und das Backend funktioniert auch gut. Nur das erstellen eines Moduls macht mir Schwierigkeiten. Da scheint Typolight sich aufzuhängen. Der Bildschirm bleibt einfach weiß.

Ich hab es local unter winxp pro oder win7 pro unter xampp laufen. Ich hab mal displayErrors aktiviert und als erstes kommt die Fehlermeldung

Warning: Cannot modify header information - headers already sent by (output started at  
G:\xampplite\htdocs\test\system\modules\gw_turnier paare\dca\tl_module.php:32) in  
G:\xampplite\htdocs\test\system\libraries\Template .php on line 174

user: dl1ely

bitte öffne /system/modules/gw_turnierpaare/dca/tl_module.php in einem Editor. Zeilen 31 und 32 sind Leerzeilen, bitte entferne die. Die letzte Zeile muss Zeile 30 mit "?>" sein.

Ich denke, daran wird es liegen. Ich vermute, das hängt mit den unterschiedlichen Zeilenumbrüchen bei Linux/Windows zusammen, bei mir tritt das Problem zumindest nicht auf. Dadurch werden wohl zwei Leerzeilen ausgegeben, bevor dann in Zeile 174 von system/libraries/Template.php der Header für die Seite gesetzt wird. Das schlägt dann natürlich fehl. In Zukunft werde ich mehr auf die Leerzeilen-Problematik achten. In der nächsten "Version" des Quelltexts wird das behoben sein.

Ansichten
Meine Werkzeuge

Contao Community Documentation

Toflar hat mich gestern entjungfert! ... er hat meinen ersten PR gemerged.

Kim Wormer
Navigation
Verstehen
Verwenden
Entwickeln
Verschiedenes
Werkzeuge