Archive

Nachtrag: Rezepthitparade als Joomla-Modul

Ich bin gefragt worden, ob ich die Erstellung eines Moduls für die Rezepthitparade in Joomla noch einmal exemplarisch darstellen könnte – OK, machen wir, es ist wirklich nicht sehr kompliziert. Zuerst möchte ich euch aber diesen Artikel zur Erstellung eines einfachen Hallo-Welt-Moduls ans Herz legen, das nehmen wir nämlich als Ausgangsbasis.

Die Anforderung

Das Modul soll die X beliebtesten Beiträge ausgeben, wobei X eine vom Benutzer eingebbare Zahl ist. Die Daten holen wir aus der #__content, da steht ja die Anzahl der Hits praktischerweise drin. Ein weiteres Kriterium ist state=1, da wir nur die veröffentlichten Beiträge ausgeben wollen. (Man könnte auch noch eine Auswahl der Kategorie einbauen, aber das lass ich jetzt mal)

Die Anpassung der XML-Datei

Für das Eingabefeld brauchen wir ein Fieldset, das sieht so aus:

...

    <config>
    <fields name="params">
        <fieldset name="basic">
            <field name="param1" type="number" default="" label="Bitte Anzahl eingeben" description="Anzahl der auszugebenden Beiträge"></field>
            
        </fieldset>
    </fields>
    </config>
</extension>

Wichtig ist hier der Name des fields-Tags (params) und der Name unseres einzelnen Feldes (param1), damit holen wir uns die Benutzereingabe ab. Das passiert in der mod_[modulname].php und sieht so aus:

...
// No direct access
defined('_JEXEC') or die;
// Include the syndicate functions only once
require_once dirname(__FILE__) . '/helper.php';

//Anzahl aus dem Fieldset abholen
$data = $params->get('param1');
        
$hello = modHelloWorldHelper::getHello($data);
require JModuleHelper::getLayoutPath('mod_helloworld');

In der helper.php können wir die in der übergebenen Variable $data steckende Anzahl dann direkt weiterverarbeiten, erstmal nur eine Testausgabe:

class ModHelloWorldHelper
{
    /**
     * Retrieves the hello message
     *
     * @param   variable  $params containing the module parameter
     *
     * @access public
          */    
    public static function getHello($params)
    {
        
              
        echo "<h2>Die ".$params." beliebtesten Beiträge</h2>";
       
}

Jetzt packen wir noch die SQL-Abfrage rein und füttern sie mit der übergebenen Anzahl als Limit:

public static function getHello($params)
    {
        
        $db = JFactory::getDBO();
        $query = "SELECT * FROM #__content where state = 1 
                  order by hits desc limit ".$params."";
        $db->setQuery($query);
        $results = $db->loadObjectList();
        
        echo "<h2>Die ".$params." beliebtesten Beiträge</h2>";
        echo "<ul>";

            foreach ($results as $rec){

                $url = JRoute::_('index.php?option=com_content&view=article&id='.
                $rec->id);
                echo "<li><a href = '".$url."'>".$rec->title." (".$rec->hits.")</a></li>";

            }
        echo "</ul>";
        
    }

Und das war auch schon alles! Der Benutzer kriegt bei der Modulerstellung ein Eingabefeld für die Anzahl:

modul_eingabe

modul_eingabe

… und die z.B. 5 beliebtesten Beiträge werden als Liste mit Links ausgegeben:

5beliebteste

5beliebteste

That’s all, mehr ist nicht dran.

Der Rezeptecounter bei Joomla: fast alles schon da

Joomla hat schon einen eingebauten Hit-Counter, der per default bei jedem Beitrag angezeigt wird. Und es gibt ein konfigurierbares Modul Beiträge-beliebte, das einem die Beiträge mit den meisten Hits anzeigt, die Anzahl der angezeigten Beiträge und die Kategorien kann man einstellen. Was ich allerdings bislang nicht gefunden habe: eine Möglichkeit, auch die Anzahl der Hits zu jedem Beitrag auszugeben. Dabei bunkert Joomla die Hits zu jedem Beitrag in der Tabelle #__content, es wäre also ein leichtes, die mit auszugeben.

Ich hab mir dafür eine Mini-Lösung mit dem Sourcerer gebastelt, eine eigene Modul-Lösung ist mir für das bisschen Code zuviel Aufwand. Eigentlich braucht es dazu nur die ensprechend formulierte SQL-Query. Ich setze mal den Where auf die Kategorie Rezepte, die anderen interessieren mich eigentlich nicht.

$db = JFactory::getDBO();
$query = "SELECT * FROM #__content where catid = 8 and state = 1 order by hits desc limit 10";
$db->setQuery($query);
$results = $db->loadObjectList();

echo "<ul>";

foreach ($results as $rec){

echo "<li>".$rec->title." (".$rec->hits.")</li>";

}
echo "</ul>";

Das wars schon! Bittesehr, die Top Ten Rezepte mit Anzahl der Hits, (inclusive aller Tippfehler und Testbeiträge in der Testumgebung):

top_ten

top_ten

Nachtrag: die Links zu den Rezepten

Die wollen wir natürlich auch noch haben. Da ich in Joomla leider kein Äquivalent zu get_the_permalink() gefunden habe, gehts anders, da kommt JROUTE ins Spiel, das wird mit der ID des Artikels bedient. Ich leg mir die URL auf eine Variable, damits nicht so unübersichtlich wird. Die Ausgabe innerhalb des Foreach sieht dann so aus:

$url = JRoute::_('index.php?option=com_content&view=article&id='.$rec->id);
echo "<li><a href = '".$url."'>".$rec->title." (".$rec->hits.")</a></li>";

Damit erzeugen wir die Links zu den Rezepten, und das ist jetzt hübsch genug, dabei lass ich es.

Gehts auch in Joomla? Bewertungsformular mit Ajax

Was in WordPress und Drupal so reibungslos geklappt hat, sollte doch euch in Joomla zu realisieren sein: ein kleines Bewertungsformular mit Notenvergabe am Ende jedes Artikels, das sich beim Abschicken einer neuen Benotung automatisch aktualisiert. Aussehen soll das Ganze in etwa so:

bewertungformular1

bewertungformular1

Wie kriegt man so etwas ans Ende jedes Artikels?

Mit einem Override, und der ist in Joomla 3 nicht weiter schwierig zu erstellen. Man geht zu Erweiterungen/Templates/Templates und klickt beim aktiven Template auf Details und Dateien, dann auf den Reiter Overrides erstellen. Unter Komponenten/com_content article anklicken, dann sollte eine solche Nachricht erscheinen:

Nachricht

Es wurde ein Override erstellt in \templates\protostar\html\com_content\article
Ein neuer Override wurde erstellt.

Man kann den Override jetzt direkt im eingebauten Editor bearbeiten, ich nehme lieber den Notepad++. Um die richtige Position für das Formular zu ermitteln, sucht man nach folgender Div und klemmt danach einen Platzhalter rein:

<div itemprop="articleBody">
 <?php echo $this->item->text; ?>
 </div>
<h1>Hier kommt das Formular hin</h1>

Dann sollte in jedem Artikel so etwas auftauchen:

override_formularposition

override_formularposition

OK, die richtige Position hätten wir jetzt. Aber was genau soll da hin? Das einzig senkrechte wäre natürlich ein eigenes Modul, das die gesamte Logik für die Benotung enthält, und dafür müssen wir ein bisschen ausholen.

Wie man ein einfaches Joomla-Modul erstellt

habe ich in diesem Artikel ausführlich beschrieben, da halten wir uns mal dran und basteln ein eigenes Modul mit Namen mod_el_bewertung. Das soll erstmal nichts machen ausser einen Platzhaltertext ausgeben, dafür sieht die helper.php anfangs so aus:

<?php
/**
 * Helper class for EL Bewertung! module
 * 
 * @package Joomla.Tutorials
 * @subpackage Modules
 * @link http://docs.joomla.org/J3.x:Creating_a_simple_module/Developing_a_Basic_Module
 * @license GNU/GPL, see LICENSE.php
 * mod_helloworld is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 */
class ModHelloWorldHelper
{
 /**

 * Retrieves the hello message
 *
 * @param array $params An object containing the module parameters
 *
 * @access public
 */ 
 public static function getHello($params)
 {
 return 'Hier soll das Formular hin!';
 
 }

Wenn alles geklappt hat, kann man das neue Modul jetzt aktivieren. Dazu unter Erweiterungen/Verwalten/überprüfen das richtige Modul suchen und installieren, dann unter Erweiterungen/Module/neu den eigenen Modultyp anwählen und einen Titel vergeben.

Modul im Override platzieren

 Dafür fügt man im Override der default.php folgende Zeile ein:

<?php echo JHtml::_('content.prepare', '{loadposition bewertungsformular}'); ?>

Nochmal zurück ins neuerstellte Modul, bei Modulposition bewertungsformular eingeben, Schreibweise beachten! Jetzt sollte die Modulüberschrift und der Platzhaltertext am Ende jedes Artikels auftauchen:

platzhalter

platzhalter

So, das waren mal die Vorarbeiten. Jetzt gehts zur Sache.

Der Code für das Formular

kommt in die helper.php in die public static function getHello() (ich war hier bloß zu faul um die Funktions- und Klassenbezeichnungen anzupassen). Wichtig ist am Anfang, dass wir uns die ID des aktuellen Beitrags holen und in die Div mit der ID ‚beitragsid‘ packen.

public static function getHello($params)
 {
 //ID des aktuellen Artikels bestimmen';
 $id = JRequest::getVar('id');
 echo 'ID dieses Beitrags: <span id = "beitragsid">'.$id.'</span>';
 
 echo '<div style="border:1px dotted #000; text-align:center; padding:10px;">';
 echo '<h4>Dir gefällt dieser Beitrag?</h4>';
 echo '<p>Dann bewerte ihn!</p>';
 echo '</div>';
 
 echo " <form action = '' method='post'>";
 
 echo "<fieldset>
 <div id = 'noten' class = 'noten' style = 'border:2px solid blue; padding :4px;'>
 <input type='radio' name='note' value='1'>sehr gut
 <input type='radio' name='note' value='2'>gut
 <input type='radio' name='note' value='3'>befriedigend<br>
 <input type='radio' name='note' value='4'>ausreichend
 <input type='radio' name='note' value='5'>mangelhaft
 <input type='radio' name='note' value='6'>ungenügend
 
 <input type ='button' name = 'absenden' class = 'bew-button' value = 'abschicken' onclick='el_bew_ajax()'/>
 
 </div>
 </fieldset>";
 echo "</form>";
 
 
 }

Das Javascript für den onclick-Aufruf packen wir der Einfachheit halber an den Anfang der  helper.php in Script-Tags, dazu gleich mehr. Jetzt brauchen wir erst noch die Tabelle für die Bewertungen, die sieht genauso aus wie in WordPress oder Drupal und hat genau drei Felder:

bewertungentabelle

bewertungentabelle

id ist Autowert, beitragsid und note schreiben wir dann gleich rein. Jetzt lesen wir erst einmal die schon vorhandenen Benotungen aus.

Bereits vorhandene Anzahl Bewertungen und Durchschnitt ermitteln

Dabei kommt uns JDatabase zu Hilfe, das geht so:

//Bereits vorhandene Benotungen abholen
 $db = JFactory::getDBO();
 $query = "SELECT * FROM bewertungen where beitragsid = ".$id."";
 $db->setQuery($query);
 $result = $db->execute();
 $anzahl = $db->getNumRows();
 //echo $anzahl." Bewertungen gefunden";
 
 $results = $db->loadObjectList();
 $durchschnitt = 0;
 foreach ($results as $zeile) :
 $durchschnitt = $durchschnitt+ intval($zeile->note);
 endforeach;
 
 if ($anzahl != 0){ 
 $durchschnitt = $durchschnitt / $anzahl;
 }
 echo "<span id = 'ausgabe'>".$anzahl." Bewertungen gefunden, Durchschnitt: ".$durchschnitt."<span>";

Wichtig ist hier, dass man sich mit dem $db->loadObjectList(); die Ergebnisliste der SQL-Abfrage holt, über die kann man dann mit dem Foreach iterieren. So, aber jetzt endlich:

Das Javascript

Das kann man nahezu unverändert aus der WordPress-Lösung übernehmen, man stellt es einfach an den Anfang der helper.php, zunächst mal nur mit Debug-Ausgabe von Beitragsid und Note:

<script>
 function el_bew_ajax(){
 
 
 //Beitragsid aus span holen
 var akt_id = document.getElementById("beitragsid").innerHTML;
 
 //Note aus den Radiobuttons holen
 var akt_note = jQuery("input:radio[name=note]:checked").val();
 
 Debug-Ausgabe
 alert(akt_note + ' ' + akt_id);
 
 //Check ob keine Note angewählt, Abbruch
 if (typeof akt_note === 'undefined'){
 alert('Bitte eine Note wählen!');
 return;}
 
 //***********************Hier kommt der ajax-call hin
 
</script>

Die Callback-Funktion

Für den Ajax brauchen wir natürlich erstmal die Callback-Funktion, die stecken wir in eine separate PHP-Datei.

<?php

$id = '';
if ( isset($_GET['id']) )
{
  $id = $_GET['id'];
}
$note = '';
if ( isset($_GET['note']) )
{
  $note = $_GET['note'];
}

$pdo = new PDO('mysql:host=localhost;dbname=joomla', '*****', '*******');

//neue Note erstmal einfügen
$sql = "INSERT INTO bewertungen (beitragsid, note) VALUES (".$id.",".$note.")";
$neu = $pdo->query($sql);

//Suche nach aktueller id
$sql = "SELECT * FROM bewertungen where beitragsid = ".$id."";
$records = $pdo->query($sql);
$gefunden = $records->rowcount();

$durchschnitt = 0;
foreach ($records as $row) {
        
        $durchschnitt = $durchschnitt + $row['note'];
    }
if ($gefunden != 0){        
    $durchschnitt = $durchschnitt / $gefunden;
    }
echo $gefunden." Bewertungen vorhanden, Durchschnittsnote = ".$durchschnitt;

?>

Das ist genau das selbe straighte PHP, das ich auch in der Drupal-Lösung schon verwendet habe, man muss nur die Login-Informationen im PDO anpassen. Jetzt fehlt nur noch:

Das Script mit dem Ajax-Call

Ich hab mir dafür noch den Pfad zum Modulverzeichnis in eine versteckte Span geschrieben, das passiert in der helper.php vor dem Formular:

//Pfad zum Modulverzeichnis abholen
        $pfad = JURI::base().'modules/'.'mod_el_bewertung/';
        echo '<span id = "pfad" style = "display:none;">'.$pfad.'</span>';

Dann kann unser Script marschieren:

<script>
 function el_bew_ajax(){
            
            //Pfad zum Modulverzeichnis abholen
            var modulpfad = document.getElementById("pfad").innerHTML;
            
            //Beitragsid holen
            var akt_id = document.getElementById("beitragsid").innerHTML;
                        
            //Note aus den Radiobuttons holen
            var akt_note = jQuery("input:radio[name=note]:checked").val();
            
            //Debug-Ausgabe
            //alert(akt_note + ' ' + akt_id);
                        
            //Check ob keine Note angewählt, Abbruch
            if (typeof akt_note === 'undefined'){
            alert('Bitte eine Note wählen!');
            return;}
            
            //***********************ajax-call
            if (window.XMLHttpRequest)
             {
              // AJAX nutzen mit IE7+, Chrome, Firefox, Safari, Opera
              xmlhttp=new XMLHttpRequest();
             }
             else
             {
              // AJAX mit IE6, IE5
              xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
             }
             xmlhttp.onreadystatechange=function()
             {
              if (xmlhttp.readyState==4 && xmlhttp.status==200)
              {
               document.getElementById("ausgabe").innerHTML = xmlhttp.responseText;
               //alert(xmlhttp.responseText);
              }
             }
             xmlhttp.open("GET",""+modulpfad+"callback_ajax_el.php?id="+akt_id+"&note="+akt_note,true);
             
             xmlhttp.send();
            
            
            
            //**********************end ajax call
}//end function el_bew_ajax

</script>

Fertig! Der Call ist scharfgeschaltet, beim abschicken einer neuen Bewertung aktualisiert sich die Anzeige.

anzeige

anzeige

Fazit

In Joomla eine einfaches Modul zu erstellen ist erstmal gewöhnungsbedürftig, aber wenn man die Logik einmal überrissen hat, kann man viel damit machen. Was mir nicht besonders gefällt, ist dass ich noch keine einfache Möglichkeit gefunden habe, einen Override nur für eine bestimmte Kategorie anzulegen, ich hätte zum Beispiel das Bewertungsformular gerne nur in der Kategorie ‚Rezepte‘. Ich hab mir da schonmal damit beholfen, in die Override-Datei eine Datenbankabfrage einzubauen, die zur aktuellen Beitragsid die Kategorie abholt, die ging so:

<?php
    $db=JFactory::getDbo();
    $article_id = JFactory::getApplication()->input->get(‚id‘);
    echo „aktuelle Artikelid= „.$article_id;
    
    $db->setQuery(’select catid from #__content where id= ‚.$article_id.“);
    $catid=$db->loadResult();
    echo „aktuelle catid= „.$catid;
    
    if ($catid == 8){
        echo JHtml::_(‚content.prepare‘, ‚{loadposition bewertungsformular}‘);
    }
    else {
        echo „Dies ist kein Rezept, Kategorie: „.$catid;
        }
    ?>

Aber das ist meiner Ansicht nach eine ziemliche Krücke. Ich muss mal ein bisschen forschen, ob das nicht eleganter geht.

Autocomplete mit AJAX in Joomla

Was mit WordPress und mit Drupal geht, das sollte sich doch auch mit Joomla hinkriegen lassen: eine Artikelsuche mit Autovervollständigen per AJAX. Ich habe dafür mal die Joomla 3 Standard-SampleSite genommen, die kann man bei der Installation als Option anwählen und sie hat schön viel Content.

Mein Arbeitspferd: die PHP-Bridge

Die geniale PHP-Bridge von Henry Schorradt ist wie immer mein Mittel der Wahl, wenn es darum geht Joomla eigenen PHP-Code unterzuschieben. Erster Schritt also: einen eigenen Menüeintrag erstellen, bei Modulzuweisung die PHP-Bridge auswählen und entsprechend anpassen. Doku hierzu im obigen Link auf Henrys Seite.

Was wir alles brauchen:

  • das Formular für die Texteingabe
  • das JavaScript für das Handling des AJAX-Requests mit den aus dem Formular übergebenen Daten
  • die PHP-Datei, die uns die Ergebnisse des Calls zurückliefert

Das Formular und das JavaScript stecken wir beide in die PHP-Datei, die mit unserer PHP-Bridge verknüpft ist. Das Formular steht dann innerhalb der Switch und sieht zum Beispiel so aus:

<?php
//$mode = Scripthandler

switch($mode){ case 'autocom':

echo     "<h1>Beispiel Artikelsuche mit AJAX in Joomla</h1>";
echo "<form action='#' method='post'>";
echo "<input type='text' size='80' name = 'ausgesucht' value='' autocomplete='off'
 onkeyup='rezepte_suche(this.value)' list = 'suchliste'>";

echo "<datalist id='suchliste'>";
 
 echo "<div id =liste>";
 echo "</div>";

 echo "</datalist>";

echo "</form>";

break;}//switch
?>

Eigentlich ein ganz normales Formular mit einem Eingabefeld vom Typ Text. Aber hier passieren noch vier eminent wichtige Dinge:

  1. onkeyup = ruft die js-Funktion rezepte_suche() auf, die steckt in der rezepte_suche.js, die wir nachher noch laden. Die Funktion kriegt als Parameter this.value mit, also den aktuellen Wert des Textfeldes. Onkeyup feuert, wenn der Benutzer eine Taste gedrückt und wieder losgelassen hat.
  2. Der Parameter list = ‚suchliste‚ des Textfeldes definiert, aus welchem HTML-Element die Datenliste für das Dropdownfeld genommen werden soll, nämlich aus der Datalist mit der id = „suchliste“
  3. Innerhalb der Datalist steckt eine Div mit der id= ‚liste‘, in die schreibt nachher unser AJAX-Call sein Ergebnis, dazu gleich mehr.
  4. Wichtige Ergänzung: das Texteingabefeld sollte unbedingt den Parameter autocomplete = ‚off‘ mitkriegen,  sonst pfuscht der Browser mit Einträgen hinein, die er aus anderen Formularen gecached hat.

Das Formular sollte jetzt in etwa so aussehen:

joomla_form

joomla_form

Das JavaScript

…packen wir mit in die PHP-Datei der Bridge, das kommt vor den Switch und sieht so aus:

<script type="text/javascript">


function rezepte_suche(inhalt)
{
 if (inhalt=="")
 {
  //Hinweis wenn der Feldinhalt leer ist;
  //document.getElementById("ausgabe").innerHTML="keine Eingabe";
  return;
 }
 if (window.XMLHttpRequest)
 {
  // AJAX nutzen mit IE7+, Chrome, Firefox, Safari, Opera
  xmlhttp=new XMLHttpRequest();
 }
 else
 {
  // AJAX mit IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }
 xmlhttp.onreadystatechange=function()
 {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
  {
   
   document.getElementById("liste").innerHTML=xmlhttp.responseText;
  
  }
 }

 xmlhttp.open("GET","http://localhost/joomla30/templates/protostar/php/rezeptesuche.php?q="+inhalt,true);
 xmlhttp.send();
}
</script>

Die ist nicht auf meinem Mist gewachsen, das ist eine Standardprozedur für einen AJAX-Call die ich mir zusammengegooglet und nach meinen Bedürfnissen angepaßt habe. Sie enthält genau eine Funktion, nämlich die rezepte_suche mit dem Parameter inhalt, in dem steckt der vom Benutzer eingegebene Inhalt des Textfeldes aus dem Formular.

Was passiert hier? Zuerst wird abgefragt, ob inhalt leer ist und in dem Fall nur ein return ausgelöst.

Wenn inhalt nicht leer ist, greifen zwei IF-Abfragen, die Browserabhängig die Variable xmlhttp unterschiedlich belegen. Wir schauen mal nur den ersten Zweig an:

xmlhttp=new XMLHttpRequest();

Hier wird ein neues Objekt vom Typ XMLHttpRequest angelegt, das wird im Folgenden weiterverarbeitet. Wer dazu Genaueres wissen möchte dem sei diese Seite der wikibooks empfohlen.

Wenn sich am Status des Formularfeldes etwas ändert, feuert folgende Funktion:

xmlhttp.onreadystatechange=function()
 {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
  {
   
   document.getElementById("liste").innerHTML=xmlhttp.responseText;
  }
 }

Die div mit der id liste kriegt einen neuen Inhalt, nämlich den Rückgabewert des Requests. Wir der aussieht, wird in unserer PHP-Datei geregelt, dazu gleich mehr.

Wichtig ist jetzt noch der open-Aufruf:

 xmlhttp.open("GET","http://localhost/joomla30/templates/protostar/php/rezeptesuche.php?q="+inhalt,true);

Ich hab hier den Pfad zur PHP-Datei  fest verdrahtet, das läßt sich sicher auch eleganter lösen, aber für Testzwecke tuts das. Die PHP-Datei kriegt als Parameter unseren inhalt mit, das ist immer noch der Inhalt des Formularfeldes so wie ihn der Benutzer eingegeben hat. Fehlt nur noch der Auslöser:

xmlhttp.send();

Und Schuß! Das setzt den Request ab.

Die aufgrufene PHP-Datei

Die benimmt sich nicht anders, als wenn sie von einem Formular aus aufgerufen würde, und sie übernimmt den Parameter inhalt in der Variablen q. Ansonsten ist sie recht übersichtlich:

<?php

$rezept = '';
if ( isset($_GET['q']) )
{
  $rezept = $_GET['q'];
}

$pdo = new PDO('mysql:host=localhost;dbname=joomla', '*******', '******');

//Suche nach enthaltenem String %suchstring%
$sql = "SELECT * FROM rrzol_content where title like '%".$rezept."%' order by title";
$records = $pdo->query($sql);

foreach ($records as $row) {
        
        echo "<option>".$row['title']." #".$row['id']."</option><br>";
        
    }


?>

Ich hole mir erstmal den Inhalt von q auf die Variable $rezept. Dann verbinde ich mich mit der Joomla-Datenbank und hole mir aus der content-Tabelle mit dem Select alle Datensätze die den Inhalt von $rezept im Titel enthalten. Innerhalb der Foreach-Schleife wirds dann nochmal interessant, ich klemme vor und nach dem Titel des Beitrags die <option>-Tags dran, die brauchen wir nachher im Formular für die Datalist. Ausserdem nehme ich noch die id mit, die brauchen wir dann für die Ausgabe des Beitrags. Das wars dann aber auch schon.

Das Formular ist jetzt scharfgeschaltet

Wenn der Benutzer jetzt zum Beispiel con in das Textfeld eingibt, erhält er eine Liste aller Beitragstitel, in denen der String con vorkommt:

auswahl_con

auswahl_con

Jetzt muss nur noch etwas passieren, wenn er einen der Einträge auswählt und auf Return drückt. Ich hab das so gelöst: in der PHP Bridge kommt nach dem Formular noch folgender Code:

if (isset($_POST['ausgesucht'])){
    
    $suchtitel = substr($_POST['ausgesucht'], 0, strpos($_POST['ausgesucht'], '#', 0));
    //echo $suchtitel;
    echo "Vielen Dank! Ihre Auswahl: <h2>".$suchtitel."</h2><br>";

    $text = strstr($_POST['ausgesucht'], '#');
    $text=substr($text,1);
        
    $url = JRoute::_('index.php?option=com_content&view=article&id='.$text);
    
    echo "<h2><a href = '".$url."'>Link zum Artikel</a></h2>";
    
    
} //ende von if isset

Ich zerlege zunächst einmal die Eingabe aus dem Textfeld und klemme für die Ausgabe des Titels alles vor dem # ab. Dann hole ich mir die Zahl nach dem #, das ist die ID des Beitrags. Zu dem hole ich mir mit dem JRoute::… die URL, aus der bastle ich mir den Link zum Beitrag. Fertig!

contacts

contacts

Das Ganze hat natürlich noch Optimierungspotential, zum Beispiel hält niemand den Benutzer davon ab, einfach irgendeinen String einzugeben und dann auf Return zu drücken, dann läuft natürlich der Link auf einen häßlichen Fehler. Aber das sind Details, die man noch verfeinern kann wenn man möchte, das sollte nicht allzu schwierig sein. Viel Spaß jedenfalls beim Nachbauen!

Joomla: ein einfaches Modul erstellen

Was für WordPress die Widgets (und zum Teil auch die Plugins), das sind für Joomla die Module. Und sogar noch ein bisschen mehr, denn man kann Module an jede beliebige Template-Position laden und ist nicht an eine oder mehrere widgetfähige Sidebar gebunden. Die Joomla-Doku zum Thema Ein einfaches Modul erstellen ist recht gut, es fehlt allerdings die Anleitung, wie man sein Modul dann auch tatsächlich in Joomla einbindet. Deswegen erkläre ich es hier mal Step by Step.

Wohin kommt das Ganze?

Um die Installation zu vereinfachen, geht man gleich in den Ordner [joomla]\modules und legt dort einen neuen Unterordner an, der den Namen mod_[meinmodul] bekommt, in meinem Fall ist das mod_helloworld.

modulordner

modulordner

Unterhalb sieht es so aus:

unterordner_modul

unterordner_modul

Im Ordner tmpl liegen noch zwei Dateien:

ordner_tmpl

ordner_tmpl

Woher kriegen wir die Dateien?

Aus der Joomla-Doku, die sind hier https://docs.joomla.org/J3.x:Creating_a_simple_module/Developing_a_Basic_Module/de fertig zum Rauskopieren angeboten.

Wer macht hier was?

Gehen wir es mal der Reihe nach durch.

Die index.html tut in beiden Fällen nichts anderes als eine leere Seite ausgeben und soll einen direkten böswilligen Zugriff auf das Verzeichnis verhindern.

Die default.php steuert die Ausgabe unseres Moduls, die sieht so aus:

<?php 
// No direct access
defined('_JEXEC') or die; ?>
<?php echo $hello; ?>

Die Variable $hello wurde in der Datei mod_helloworld.php definiert, das sieht so aus:

$hello = modHelloWorldHelper::getHello($params);

Dies wiederum ist der Aufruf der Funktion getHello() aus der Klasse modHelloWorldHelper aus der Helper-Datei, die wurde dort so definiert:

class ModHelloWorldHelper
{
    /**
     * Retrieves the hello message
     *
     * @param   array  $params An object containing the module parameters
     *
     * @access public
     */    
    public static function getHello($params)
    {
        return 'Hello, World!';
    }
}

That’s where the Action is!  Zugegeben, es ist ein bisschen von hinten durch die Brust ins Auge, aber so gehts. Es ist auch vorgesehen, dass man der Funktion getHello() Parameter mitgibt, das kann in der mod_helloworld.php z.B. so aussehen:

$hello = modHelloWorldHelper::getHello("Evi Silvia");

Dann müssen wir nur noch die Ausgabe in der helper.php modifizieren:

public static function getHello($params)
    {
        return 'Hallo, liebe '.$params."!";
    }

Was kommt dabei heraus? Nicht weiter überraschend: Hallo, liebe Evi Silvia! Aber ich greife vor.

Wie man Joomla das neue Modul jetzt bekannt macht

Über Erweiterungen->Verwalten->Überprüfen sollte das neue Modul jetzt gefunden werden, und wenn man die Dateien richtig zusammenkopiert hat, kann man es auch installieren.

Dann läßt sich unter Erweiterungen->Module->Neu das neue Hello World Modul auswählen:

helloworld_auswaehlen

helloworld_auswaehlen

Wie gewohnt Titel vergeben und Modulposition auswählen, und schon sollte die Ausgabe an der gewählten Position zu sehen sein:

modul_anzeige

modul_anzeige

Ich hoffe, ich konnte damit etwas Klarheit in die Sache bringen, bei der Vorlage aus der Joomla-Doku fehlte einfach noch der Teil mit der Installation. Aber so sollte es jeder hinkriegen!

 

Kontaktformular in Joomla mit Bordmitteln

Ich liebe ja mein Contact Form 7 und benutze es auf nahezu jeder WordPress-Webseite, und jetzt wollen wir mal sehen ob Joomla da Vergleichbares zu bieten hat. Wir brauchen ja zumindest auf der Kontakt/Impressum-Seite ein kleines Kontaktformular mit den relevanten Daten und der Möglichkeit, mir eine E-Mail zu schicken.

Die Joomla-eigene Kontaktverwaltung

Über Komponenten->Kontakte->Kontakte hat man die Möglichkeit, aus den vorhandenen Benutzern eine beliebig umfangreiche Liste mit Kontakten zu generieren. Das ist für meine Zwecke mit Kanonen auf Spatzen geschossen, hier gibt es nur einen Benutzer (mich, den Super User) und eine einzige Kontaktperson, nämlich die Evi S. Leu. Macht aber nix, lege ich halt den einen einzigen Kontakt an und fülle ihn mit den korrekten Informationen, essentiell ist hier die Zuordnung des verknüpften Benutzers:

kontakt_evi

kontakt_evi

Ein Bild kann man auch noch hinzufügen, dann speichern und schliessen.

Kontakt in Beitrag einfügen

Für den Menüpunkt Kontakt/Impressum hatte ich einen einzelnen Beitrag verknüpft, den geh ich jetzt bearbeiten. Über die Option „Kontakte“ kann ich jetzt den soeben erstellten Kontakt in den Beitrag einfügen.

kontakt_einfuegen

kontakt_einfuegen

Ich formatiere mir den Kontakt schön groß (36pt) und unterstrichen, damit er auch ins Auge fällt, der Default ist nämlich in meinem Template zu winzig und unauffällig. Speichern, und jetzt gehen wir uns die Seite Kontakt/Impressum mal ansehen:

kontaktimpressum

kontaktimpressum

Zugegeben, man muss jetzt erstmal auf die Idee kommen, den Kontakt auch anzuklicken, aber so abwegig ist das nicht, oder?

Klick auf „Kontakt Evi S. Leu“ ergibt:

kontakt_screenshot

kontakt_screenshot

Juppidu, und da versteckt sich auch die Option „Kontaktformular“! Das sieht dann so aus:

kontaktformular

kontaktformular

Na, da haben wir doch alles was wir brauchen. Zugegeben, das Nachricht-Feld hätte ein wenig grösser ausfallen können (man kann es aufziehen), aber sonst ist alles in Butter, wir haben unser eigenes Kontaktformular mit wenigen Klicks mit Bordmitteln zusammengebastelt.

Jetzt wollen wir mal sehen, ob es uns auch gelingt ein wirklich benutzerdefiniertes Formular zusammenzubasteln, aber dafür gibt es einen neuen Beitrag. Sobald ich dazugekommen bin, mir das Breezing Forms mal näher anzuschauen, das scheint der Formulareditor der Wahl für Joomla zu sein. Kann ein Weilchen dauern!

Da ist Joomla stark: ein bisschen Feintuning

Bevor ich hier in die Details gehe, noch ein kleiner Nachtrag: ich habe glatt die Anzeige der neuesten Beiträge vergessen!

Liste der neuesten Beiträge anzeigen

Auch hierfür gibt es ein Modul, es ist zu finden unter Erweiterungen->Module->Neu-> Beiträge-Neueste. Titel vergeben, Kategorie einstellen, ggf. Anzahl und gewünschte Sortierung einstellen, rechts die gewünschte Modulposition wählen, fertig. Jetzt sieht das so aus:

neueste_beitraege

neueste_beitraege

Man könnte natürlich auch noch eine Liste der neuesten Kochbücher (oder jeder anderen Kategorie) ebenso erstellen, aber darauf verzichte ich mal, jetzt gehts ans Feintuning.

Autor der Beiträge ausblenden

Wie bereits erwähnt ist der Autor der Beiträge ggf. immer ich, der Admin, daher ist die Anzeige völlig überflüssig. Man kann sie auf Beitragsebene einzeln oder global für ein Menü ausblenden, ich nehme mal letzteren Weg:

Menüs->Main Menu->Optionen (rechts oben)->Beiträge

Hier kann man den Autor verbergen, und ich stelle mal die Position der Beitragsinfos auch gleich auf „darunter“, weil mir das besser gefällt.

menue_beitragsoptionen

menue_beitragsoptionen

Autor in Blogliste ausblenden

In unserem Inhaltsverzeichnis wird der Autor immer noch angezeigt, dem kommen wir so bei:

Menüs->Main Menü->Rezepteliste A-Z->Listenlayout->Autor in Liste verbergen

Ich habe hier auch den Anzeigefilter auf verbergen gestellt, den brauche ich nicht. Die Zugriffsstatistik (steckt unter Seitenaufrufe) lass ich mal drin, das ist vielleicht für den Besucher ganz interessant.

Anzahl der Schlagworte in der Liste anzeigen

Erweiterungen->Module->Rezeptkategorien (oder wie ihr Modul heisst)->Anzahl Einträge anzeigen

Layout der Blogseiten anpassen

Menüs->Main Menü-> z.B. Alle Rezepte->Blog-Layout

Defaultmäßig wird hier der neueste Beitrag als führender Beitrag auf voller Breite dargestellt, die restlichen folgen mehrspaltig, letzteres ist abhängig vom gewählten Template. Damit es aussieht wie in WordPress, stellt man Führende auf 0 und Spalten auf 1, ich finde aber die mehrspaltige Anzeige recht ansprechend.

In den Blog-Seiten das Pin-Icon ausblenden

Erweiterungen->Templates->Stile-> Template auswählen, unter dem Reiter „Blog“ Show Icon auf No stellen.

Sticky Header ausschalten

Ich finde Sticky Headers extrem irritierend, deswegen mach ich da kurzen Prozess:

Erweiterungen->Templates->Stile->pixel (oder ihrer) -> Sticky Header „No“.

Die Option ist Template-abhängig.

Suche einfügen

Erweiterungen->Module->Neu, Suche

Titel vergeben, Position wählen, fertig.

Die Darstellung der Suchergebnis-Seite kann über Komponenten->Suche->Optionen bis zu einem gewissen Grad gesteuert werden, das kann sich jeder selber anschauen, die Joomla-Suche bietet erheblich mehr Optionen als die WordPress-Suche.

suchergebnis_feineinstellungen

suchergebnis_feineinstellungen

Mehr Feintuning der Suchergebnis-Seite geht offenbar noch über eine Anpassung der Template-Dateien, einen Ansatz findet man hier im Deutschen Joomla-Forum, aber das führt mir hier wesentlich zu weit.

Layoutmodifikationen ohne Ende – übers Kontrollzentrum

Sie sehen schon, es gibt in Joomla nahezu unendlich viele Möglichkeiten, das Aussehen der Seitenkomponenten den eigenen Wünschen anzupassen. Und das alles, ohne in den Templates herumfuhrwerken zu müssen! Das finde ich wirklich eine sehr grosse Stärke gegenüber WordPress, wo man doch meistens nicht darum herumkommt, in den Theme-Templates herumzupfuschen. Denn die sind ja meistens gar nicht bis grottenschlecht dokumentiert, da betreibt man meistens Trial&Error in grossem Stil. Es enthebt einen auch der Notwendigkeit, gleich ein Child-Theme anlegen zu müssen, wenn man eigene Anpassungen am Layout sauber vom Eltern-Theme trennen will.

Child Themes

Die gibt es in Joomla übrigens auch, eine kurze Einführung finden sie hier , Details zur Anwendung der sogenannten Overrides und sonstige Informationen zur Templateentwicklung kann man in der Joomla Documentation nachlesen, ich werde hier nicht näher darauf eingehen, weil es a) den Rahmen dieser kurzen Einführungsserie sprengen würde und b) zur Erstellung einer vernünftigen Webseite mit Joomla nicht wirklich notwendig ist.

Jetzt schauen wir aber mal, was bei unserem neuen Kochbuch auf Joomla-Basis noch fehlt, und dazu gibt es einen neuen Beitrag.

Von Rezeptkategorien zur Schlagwortliste

Da fehlt doch noch was – wo sind meine Rezeptkategorien geblieben? Die hätte ich natürlich auch in Joomla gern als Liste in der Sidebar. Ich hab da getrickst und meine WordPress- Kategorien auf Joomla-Schlagwörter abgebildet, nur mal kurz zur Erinnerung:

schlagwoerter

schlagwoerter

Das klappt auch nur deswegen, weil ich in WordPress auf die Verschachtelung der Kategorien verzichtet habe und das alles nur auf einer Ebene stattfindet. Beim Erstellen der Rezepte habe ich brav jeweils ein oder mehrere Schlagwörter zugeordnet, und diie wollen wir jetzt auch sehen.

Darf ich vorstellen: die Module

Unter Erweiterungen/Module findet sich eine ganze Latte von Funktionalitäten, die in etwa dem entsprechen, was wir aus WordPress als Widgets kennen. Dazu später mehr, wir machen das hier jetzt im Schnelldurchgang. Voraussetzung ist wie gesagt, dass sie ihre Rezepte mit Schlagwörtern versehen haben – und zwar nur die Rezepte, sonst klappt das hier nicht. Auf die Verwendung von Schlagwörtern bei den anderen Beitragstypen (Kochbücher, Zutaten) habe ich bewusst verszichtet, weil ich es a) nicht brauche und das b) die Schlagwortliste verfälschen würde. Also, los gehts:

  1. Erweiterungen->Module->Neu,
  2. „Schlagwörter – Beliebte“, Maximale Anzahl nach Bedarf erhöhen, leider ist hier bei 20 Schluss. Das würde „im richtigen Leben“ eng werden, ich hab im Inselfisch-Kochbuch fast 30 Kategorien, aber für Demo-Zwecke tuts das.
  3. Titel vergeben, rechts gewünschte Position auswählen, hier macht sich die Positionsvorschau wieder sehr nützlich. Dabei aufpassen, dass man auch das richtige Template gewählt hat, es werden alle in der Auswahlliste aufgeführt.
  4. Man kann hier auch gleich noch die gewünschte Reihenfolge, z.B. nach Titel aufsteigend anwählen.
  5. Speichern und schliessen.

Ergebnis:

schlagwortliste

schlagwortliste

Das ist voll OK für meine Zwecke, da ich hier keine Verschachtelung brauche.

Damit haben wir schon eine ganz respektable Seite stehen, die dem Original schon recht ähnlich sieht.

ifkb_joomla

ifkb_joomla

Jetzt gehts ans etwas Feintuning, aber dazu gibt es einen neuen Beitrag.

 

 

 

Das erste Menü

Modifikation eines vorhandenen Menüs

Ich habe das Template pixel free gewählt, das kommt mit einem vordefinierten Menü oben waagerecht. Zu finden ist es im Kontrollzentrum unter Menüs-> Main Menu, und das lässt sich leicht modifizieren.Man kann die vorhandenen Menüpunkte umbenennen und herumschieben, und neue Menüpunkte dazu anlegen.

Ein Beitrag = ein Menüpunkt

Wir wollen jetzt einen (einen einzelnen!) vorhandenen Beitrag einem Menüpunkt zuweisen. Es sind auch noch viele andere Inhalte für Menüeinträge möglich, aber jetzt erstmal der Reihe nach.

  1. wir haben einen Beitrag, der heisst „Über den Inselfisch“ und enthält den Text dazu.
  2. im Menüs->Main Menü „Neu“ anwählen und den Namen des Menüpunktes eintragen, auch der heißt „Über den Inselfisch“
  3. Bei Menüeintragstyp auf Auswählen klicken, gleich den ersten Eintrag Beiträge aufklappen
  4. Option Einzelner Beitrag anwählen
  5. Unter Beitrag auswählen den bestehenden Beitrag wählen (oder hier einen neuen erstellen)
  6. alle anderen Optionen so lassen wie sie sind, Speichern und Schliessen.

Voliá, wenn wir unsere Seite jetzt anschauen, ist der neue Menüeintrag schon  sichtbar!

Die Reihenfolge der Menüpunkte läßt sich übrigens mit den „Anfassern“ in der ersten Spalte verschieben, das kann man leicht übersehen.

menuepunkte_verschieben

menuepunkte_verschieben

Ein Kategorieblog = ein Menüpunkt

Wir haben hoffentlich einige Beiträge die alle zur selben Kategorie gehören. Dann geht das mit dem Kategorieblog so:

  1. Neuen Menüpunkt anlegen und Namen vergeben
  2. Menüeintragstyp-> Beiträge-> Kategorieblog wählen
  3. gewünschte Kategorie auswählen, fertig.

Das Ergebnis ist eine Seite, auf der alle Beiträge der gewählten Kategorie in Blogform angezeigt werden. Das für alle gewünschten Kategorien wiederholen, und fertig ist die Multiblog-Seite – schicke Sache!

Weils so schön ist: wir machen gleich mal ein Rezeptverzeichnis A-Z

Wir nehmen uns die Kategorie Rezepte noch einmal vor, die wollen wir jetzt als Inhaltsverzeichnis sehen.

  1. Neuen Menüpunkt anlegen und z.B. „Rezepteliste A-Z“ nennen
  2. Menüeintragstyp->Beiträge->Kategorieliste wählen
  3. Kategorie „Rezepte“ auswählen
  4. Unter „Listenlayout“ Beitragssortierung die Option „Titel von A-Z“ wählen
  5. Speichern und fertig.

Ergebnis:

rezepte-a-z

rezepte-a-z

Also, ganz so schön wie in meinem selbstprogrammierten Inhaltsverzeichnis im Inselfisch-Kochbuch ist es nicht, aber für den Anfang doch schon mal sehr brauchbar.

 

Joomla-Beiträge: alles ist Content

Links oben im Joomla-Kontrollzentrum kann man einen Block von Einträgen sehen, die einem gleich bekannt vorkommen: es geht um Beiträge und Kategorien. Also klickt man mal auf „Neuer Beitrag“ – und landet im bekannten Editor, das ist der TinyMCE, mit ein bißchen erweiterter Funktionalität. Aber gemach, gemach, bevor wir da loslegen ist zuerst ein bisschen Theorie vonnöten.

Beitrag oder Seite – alles ist Content

Im Gegensatz zu WordPress unterscheidet Joomla nicht zwischen Blog-Beiträgen und Seiten, es wird jede Art von Webseiteninhalt unter der Bezeichnung Beitrag verfaßt. In der Datenbank landet das auch alles in der selben Tabelle, nämlich der (prefix)_content, aber dazu später mehr. Das kommt einem zunächst ein bißchen strange vor, aber wir werden nachher beim Aufbau unseres ersten Menüs sehen, dass es völlig wurst ist, dass da alles unter dem selben Etikett Beitrag abgelegt wird. Man muss nämlich erstmal einen Blick auf das Joomla-Kategorienmodell werfen, das wollen wir hiermit tun, denn hier lauert die erste Stolperfalle für alte WordPressler.

Ein Beitrag = eine Kategorie

Wenn man im Kontrollzentrum den Menüpunkt Kategorien anklickt, landet man in einem übersichtlichen Editor, in dem Kategorien angelegt und verwaltet werden können. Joomla bietet auch die Möglichkeit der Verschachtelung von Kategorien, aber dazu später mehr. wie lassen es fürs erste mal bei Kategorien ohne übergeordnete Kategorie. Der Knackpunkt ist nämlich: in Joomla ist pro Beitrag genau eine Kategorie zuzuordnen, (oder der Beitrag bleibt in der Default-Kategorie „Uncategorised“).  Die Kategorien in Joomla dienen nicht der thematischen Unterteilung der Beiträge, sondern der Zusammenfassung von Beiträgen gleichen Typs. Ich mach mal ein Beispiel, dann wirds gleich klarer.

Verschiedene Beitragskategorien erlauben mehrere Blogseiten

Im Inselfisch-Kochbuch habe ich zuallererst mal die Rezepte, die sind die Seele des Blogs. Um dies in Joomla abzubilden, lege ich eine Kategorie Rezepte an. Wenn ich dann einen neuen Beitrag für ein Rezept erstelle, ordne ich ihm logo die Kategorie Rezept zu. Ich habe aber auch noch andere Inhalte, wo mehrere Entitäten des gleichen Typs vorliegen: die Kochbücher zum Beispiel, und die Zutaten. Dafür erstelle ich mir in Joomla flugs die passenden Kategorien „Kochbücher“ und „Zutaten“, und warum das so praktisch ist sieht man gleich. Man hat nämlich die Möglichkeit, mithilfe der Kategorien pro Beitragstyp eine Blogseite anzulegen. Das habe ich mir in WordPress schon oft gewünscht! Und es wäre jetzt besonders hier im schwarzen Pinguin verdammt praktisch, dann könnte ich die Joomla-Serie in einen eigenen Blog packen, und es wäre wesentlich übersichtlicher. Aber das nur am Rande vermerkt.

Legen sie sich zunächst mal einige Testbeiträge und zwei oder drei sinnvolle Kategorien an und ordnen sie diese entsprechend zu, dabei kann man sich schon mal mit dem Beitragseditor ein bißchen näher anfreunden.

Was fehlt noch? Die statischen Seiten!

Keine Bange, auch die sind nur Beiträge, and man kann sie für den Anfang ruhig auf „Uncategorized“ lassen. Ich brauche am Anfang nur wenige statische Seiten, einmal die Startseite unter dem Titel „Willkommen“ und die Infoseite „Über den Inselfisch“, und das Impressum nehmen wir auch gleich noch mit. Das wars fürs erste.

Und wo bleiben die Rezeptkategorien aus WordPress?

Da hab ich mir eine einfache Lösung ausgeguckt, die realisiere ich über die Schlagwörter. Da ich mit einer kleinen Ausnahme (dem Backwerk) in WordPress keine geschachtelten Beitragskategorien verwende, kann ich die Struktur so gut wie 1:1 abbilden. Schlagwörter verwalten kann man im Kontrollzentrum unter Komponenten-> Schlagwörter, und ich hab hier einfach ein paar der Kategoriebezeichnungen aus dem Inselfisch-Kochbuch übernommen:

schlagwoerter

schlagwoerter

Man kann einem Beitrag mehrere Schlagwörter zuordnen, und damit kriege ich die Abbildung der WordPress-Kategorien locker hin. Wie gesagt, ich verwende keine geschachtelten Kategorien in WordPress, deswegen klappt das hier.

Aber genug der Vorarbeit, wie wollen unsere Inhalte jetzt auch Online sehen! Dafür brauchen wir ein Menü, und dazu gibt es einen neuen Beitrag.