Archiv der Kategorie: Datenbank (Joomla)

Joomla Modul für alfabetische Pagination

Weil es doch ein bißchen anders geht als in WordPress, hab ich hier nochmal die alfabetische Pagination von Beiträgen aufgegriffen und in ein Joomla-Modul gepackt. Nur mal kurz zur Erinnerung, das Ganze soll so aussehen:

alfabetisch

alfabetisch

Eigentlich selbsterklärend… wenn man auf einen Buchstaben klickt, werden alle Beiträge mit diesem Anfangsbuchstaben aufgelistet, natürlich als Links. Interessant ist hier, dass der Joomla-Datenbanktreiber die Sortierung aus dem „order by title“ ohne weitere Kunstgriffe auch mit deutschen Umlauten und Accents richtig macht, in WordPress musste man da etwas tricksen. Aber das nur als Randnotiz.

Da in Joomla die Beitragskategorien so elementar wichtig sind, habe ich ins Modul eine Auswahl der Kategorie mit aufgenommen. Hier wurde die Kategorie „Rezepte“ gewählt, es geht aber auch jede andere Kategorie, da kommt das Standardformularfeld vom Type „category“ gerade recht.

Und hiermit fangen wir auch an, die XML-Datei für unser Modul sieht so aus:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1.0" client="site" method="upgrade">
    <name>Alfapage Modul</name>
    <author>Evi Leu</author>
    <version>1.0.0</version>
    <description>Alfabetische Pagination</description>
    <files>
        <filename>mod_alfapage.xml</filename>
        <filename module="mod_alfapage">mod_alfapage.php</filename>
        <filename>index.html</filename>
        <filename>helper.php</filename>
        <filename>tmpl/default.php</filename>
        <filename>tmpl/index.html</filename>
    </files>
    <config>
    <fields name="params">
        <fieldset name="basic">
            <field name="mycategory" type="category" extension="com_content" label="Kategorie auswählen" description="" />
        </fieldset>
    </fields>
    </config>
</extension>

Die XML-Defi enthält genau ein Feld für Benutzereingaben (grün markiert), hier kann man aus den vorhandenen Kategorien eine auswählen.

alfapage_modul

alfapage_modul

Das Modul habe ich mod_alfapage genannt, bitte Dateinamen entsprechend anpassen nicht vergessen.

Dann gehts auch schon zur Sache. Die mod_alfapage.php sieht so aus:

<?php
/**
 * Basic Module Entry Point
 */

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

//Werte aus dem Fieldset abholen
$kategorie = $params->get('mycategory');


$data = new stdClass();
//Objekt füllen
$data->kategorie = $kategorie;

        
$basic_ausgabe = modBasicHelper::getAusgabe($data);
require JModuleHelper::getLayoutPath('mod_alfapage');

Hier wird genau ein Parameter an die Helper-Klasse übergeben, nämlich die ID der gewählten Kategorie aus dem Dropdown-Feld im Modul. Nicht vergessen: in der default.php den Variablennamen anpassen!

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

Weiter geht es in der helper.php, hier kann man einiges vom WordPress-Plugincode übernehmen, aber eben nicht alles. Erster Stolperstein: ich möchte den Namen (nicht die numerische ID) der gewählten Kategorie ausgeben. Dafür behelfe ich mir so:

<?php
/**
 * Helper class für Basic Modul
 
 */
class ModBasicHelper
{
    /*
     * @param   variable  $params containing the module parameter
     *
     * @access public          */    
          
          
    
    public static function getAusgabe($params)
    {
        $akt_kat = $params->kategorie;
        
        //Kategorietitel holen
        $db = JFactory::getDbo();
        //get current category id
        $id = $akt_kat; 
        //match id to cat.id from _categories set to variable $id
        $db->setQuery("SELECT cat.title FROM #__categories cat WHERE cat.id='$id'"); 
        $category_title = $db->loadResult();
        
        echo "<h2>Alfabetisches Verzeichnis der Kategorie ".$category_title."</h2>";

Ich hab keine schönere Methode gefunden, also gehe ich mit dem Select auf die categories-Tabelle und hole mir den Kategorienamen zur übergebenen ID.

Dann konstruiere ich mir genau wie in WordPress Submit-Buttons von a-z und frage mit einem if isset() ab, welcher denn geklickt wurde.

//***************************************
        //Buchstaben a-z in Array schreiben
            $letters = array();
            for ($i = 'a', $j = 1; $j <= 26; $i++, $j++) {
                $letters[$j] = $i;    
            }
            //Formular mit Buttons
            echo "<form action = '#' method = 'post'>";
            
            for ($i=1; $i <=26; $i++){
                echo "<input type='submit' name='".$letters[$i]."' value='".$letters[$i]."'>";
            }
                echo "</form>";
               
        for ($j = 1; $j <= 26; $j++){    
        if (isset($_POST[''.$letters[$j].''])){
            
            return el_aufruf("".$letters[$j]."",$akt_kat);
            
        }

Der angeklickte Buchstabe und die aktuelle Kategorie-ID werden an eine Hilfsfunktion zur Ausgabe übergeben, die steht in der helper.php nach der Klassendefinition (Wenn man sie innerhalb der Klassendefinition mit reinpackt, Aufruf mit modBasicHelper::el_aufruf()).

Hier hole ich mir zunächst aus der Tabelle #__content alle Einträge, die mit dem übergebenen Buchstaben anfangen. Ausserdem filtere ich nach state = 1 (published) und der übergebenen Kategorie-ID:

function el_aufruf($stabe, $kat){
    $db =JFactory::getDBO();
    $suchstabe = $stabe."%";
    $query = "SELECT * FROM #__content where title like '".$suchstabe."' and state = 1 and catid = ".$kat." order by title";
    $db->setQuery($query);
    $db->execute();
    $gefunden = $db->getNumRows();
    $results = $db->loadObjectList();   
     
        
        echo "<h3>".$gefunden." Beiträge zum Buchstaben ".strtoupper($stabe)."</h3>";

Durch die auf der Variable $results liegende Objektliste mit dem Abfrageergebnis steppen wir nun wie gewohnt mit einem foreach durch und geben alle Titel der gefundenen Beiträge aus. Um auch einen Link zum Beitrag konstruieren zu können, muss man in Joomla ein bißchen umständlich operieren, das geht so:

foreach ($results as $einpost){
            
            $article = JControllerLegacy::getInstance('Content')
            ->getModel('Article')->getItem($einpost->id);

            $url =  JRoute::_(ContentHelperRoute::getArticleRoute($einpost->id, 
                      $article->catid, 
                      $article->language));
            
            echo "<a href = '".$url."'>".$einpost->title."</a><br>";
            
        }
    
} //end function el_aufruf

Damit wird eine Linkliste zu den gefundenen Beiträgen ausgegeben. Das wars – alfabetische Pagination in Joomla für Beiträge einer frei wählbaren Kategorie.

buchstabe_k

buchstabe_k

Pedanten werden anmerken, das die Sortierung nicht ganz Telefonbuch-konform ist, die Umlaute werden nicht nach ihren Diphtongen einsortiert (ä als ae), sondern nach ihrem Basis-Buchstaben (ä als a). Aber damit kann ich leben, da mach ich jetzt nix.

Von Joomla nach WordPress umziehen – der Vollständigkeit halber

Ich habe drüben im Drupal-Blog ausführlich beschrieben, wie man Inhalte aus Drupal in WordPress-Beiträge überführt, nachzulesen hier. Das selbe machen wir jetzt noch mit Joomla, und zwar möchte ich die Beiträge aus einer bestimmten Kategorie nach WordPress exportieren. Meine ausgewählte Kategorie sind natürlich die Rezepte, mit der Kategorie-ID 8 (im Zweifelsfall nachschlagen in der Tabelle #__categories).

Wie kommen wir an Titel und Inhalt der Rezepte?

Aus der Tabelle #__content. Die holen wir uns nach Access rüber und schauen sie mal näher an.

content

content

Die id und den title nehmen wir mit, den alias lassen wir aus. Dann brauchen wir noch den introtext und den fulltext (beide!), weil Joomla den Beitragstext in diese beiden Felder aufteilt, sobald man einen Weiterlesen-Tag eingefügt hat. Das sieht man hier im Screenshot oben bei den ids 4 bis 8, so sieht das dann aus.

Den state müssen wir filtern, -2 bedeutet „marked for deletion“, 1 ist veröffentlicht, wir nehmen nur die 1er. Und die catid filtern wir auch, auf die 8 für Rezepte. (Bei mir ist noch ein Haufen Schrott vom Testen mit drin, ich nehm mal noch die Datensätze 9-47 raus). Übrig bleibt die folgende Tabelle:

content_gefiltert

content_gefiltert

Die specken wir noch ab, die Felder introtext und fulltext werden zu einem Feld namens bodytext zusammengefügt, die catid und der state fliegen raus.

Jetzt fehlen noch die Tags für die Kategorien

Kleine Erinnerung: ich hatte die Rezeptkategorien aus WordPress auf Joomla-Tags ohne Schachtelung abgebildet. Die holen wir uns jetzt wieder zurück, und zwar aus der Tabelle #__tags.

tags

tags

Der erste Eintrag für root fliegt raus, vom Rest übernehmen wir id und title. Parent_id ist überall leer, weil nicht geschachtelt, published = 1 passt auch. Um jetzt die Tags den Rezepten (hier in der Tabelle id_title_bodytext) zuzuordnen, verknüpfen wir über die Tabelle contentitem_tag_map. Beim Importieren nach Access darauf achten, dass content_item_id und tag_id als Integer rüberkommen! Das sieht dann so aus:

tags_beziehungen

tags_beziehungen

Darüber basteln wir uns eine Abfrage, in der zunächst mal jedes Rezept so oft vorkommt, wie es Tags zugeordnet hat:

abfrage_tags

abfrage_tags

Kurzer Blick über die Tabelle: ich habe zu keinem Rezept mehr als 2 Tags zugeordnet, aber das passt schon, ist korrekt.

Zuordnen der Tags zu WordPress-Kategorien

Dafür zieht man sich alle gültigen Tags aus der #–tags ab und importiert sie als Kategorien nach WordPress, wie das geht habe ich in diesem Artikel unter Schritt 1: Anlegen der Kategorien in WordPress im Drupal-Blog ausführlich beschrieben.

Dann habe ich mir die entstandene Tabelle wp_terms nach Access rübergeholt:

wp_terms

wp_terms

Hier kann ich jetzt über den name des Terms auf den title des tags verknüpfen, weil die Schreibweise identisch ist:

join_term_name

join_term_name

Damit bekomme ich die WordPress-Kategorie-IDs zu den Rezepten.

term_id

term_id

Das hatten wir so ähnlich schonmal, jedes Rezept taucht jetzt so oft auf, wie es Kategorien/Tags hat. Jetzt Gruppieren wir noch, und nehmen den ersten und letzten Wert der Term-ID. Diese sind bei den Datensätzen gleich, die nur eine Kategorie zugeordnet haben, das ist schon richtig so.

ersterwert_letzterwert

ersterwert_letzterwert

So, das wars. Diese Tabelle kann man nach WordPress importieren, und zwar genau so wie ich es in diesem Artikel beschrieben habe:

DRUPAL NACH WORDPRESS: BEITRÄGE MIT KATEGORIEN ERZEUGEN

Dabei muss man wahrscheinlich noch eine kleine Abfrage einbauen, was passieren soll wenn erster und letzte Wert der term_id gleich sind, aber prinzipiell funktioniert die Sache so einwandfrei, die Beiträge werden in WordPress angelegt und mit Kategorien versehen.

Rezepte mit 2 Tags importieren, so gehts

Ich hab mir mal eine kleine Export-Tabelle mit 11 Datensätzen gebaut, die sieht so aus:

11_export

11_export

id, titel und content kommen wie gehabt aus WordPress, kat_1 und kat_2 sind die passenden Schlagwort-IDs aus Joomla, die wir im letzten Beitrag via Access zugeordnet haben. Jetzt wird noch das Import-Skript umgebaut, da kommt die Logik für die Tag-Zuordnung innerhalb der Foreach-Schleife nach dem Erzeugen des neuen Artikelobjekts mit rein. Das Ganze sieht dann so aus:

//**************Tags zuordnen
           $roh1 = $zeile->kat_1;
           $roh2 = $zeile->kat_2; 
           
            $tag1 =strval($roh1);
            $tag2 =strval($roh2);
            $neue_id= $article->id;
            
            // Das ist einen Versuch wert!
                $basePath = JPATH_ADMINISTRATOR.'/components/com_content';
                require_once $basePath.'/models/article.php';
                $articlemodel = new ContentModelArticle(array('table_path' => $basePath . '/tables'));

                $params = array(
                    'id' => $neue_id,                // Article being tagged 
                    'tags' => array($tag1, $tag2)   // Tag IDs from #__tags to tag article with
                );
                
                if($articlemodel->save($params)){
                    echo 'Success!';
                }
                    
                    
                    
                    
                    
                    //**************Ende Tags zuordnen

Der Import der Rezepte bleibt genau wie gehabt, nur findet jetzt noch die Tag-Zuordnung statt. Damit erhalten wir nach dem Import eine wohlgefüllte Tagliste:

tagliste_screenshot

tagliste_screenshot

Was, wenn ich mehr als 2 Kategorien übernehmen will?

Dann muss das Tagmapping in Access aufgebohrt werden, wo ich jetzt mit erster Wert/letzter Wert operiert habe, muss eine Kreuztabelle rein, damit sollten auch beliebig viele Kategorien pro Rezept abgebildet werden können. Die Export-Tabelle wird dann halt ziemlich breit, und das Script braucht eine Logik, mit der alle Tag-Felder (kat_1.. kat_n) berücksichtigt werden. Aber das führt mir jetzt entschieden zu weit, da darf jeder selber experimentieren. Ich mach hier einen Break, und eine Denkpause für den nächsten Beitrag.

So schnell geb ich nicht auf: Joomla-Artikel importieren, eine heisse Spur

Ich sitze ja hier immer noch auf über 300 Rezepten aus dem Inselfisch-Kochbuch und habe keine Lust, die per Copy&Paste nach Joomla reinzuschubsen, mehr zu dem Thema habe ich bereits in diesem Artikel erzählt. Jetzt bin ich bei Stackexchange auf einen vielversprechenden Ansatz gestossen, wie man einen Joomla-Artikel programmatisch erzeugen kann, mehr Infos hier:

https://stackoverflow.com/questions/12643725/create-a-joomla-article-programatically?lq=1

Im letzten Beitrag des Threads (Support Joomla 2.5 and Joomla 3.0) findet sich ein Sourcecode, der ohne weitere Modifikationen funktioniert. Ich zitier den mal hier rein:

if (version_compare(JVERSION, '3.0', 'lt')) {
    JTable::addIncludePath(JPATH_PLATFORM . 'joomla/database/table');        
}   
$article = JTable::getInstance('content');
$article->title            = 'This is my super cool title!';
$article->alias            = JFilterOutput::stringURLSafe('This is my super cool title!');
$article->introtext        = '<p>This is my super cool article!</p>';
$article->catid            = 9;
$article->created          = JFactory::getDate()->toSQL();
$article->created_by_alias = 'Super User';
$article->state            = 1;
$article->access           = 1;
$article->metadata         = '{"page_title":"","author":"","robots":""}';
$article->language         = '*';

// Check to make sure our data is valid, raise notice if it's not.

if (!$article->check()) {
    JError::raiseNotice(500, $article->getError());

    return FALSE;
}

// Now store the article, raise notice if it doesn't get stored.

if (!$article->store(TRUE)) {
    JError::raiseNotice(500, $article->getError());

    return FALSE;
}

(Quelle: https://stackoverflow.com/questions/12643725/create-a-joomla-article-programatically?lq=1)

Das sieht soweit gut aus, fehlt höchstens noch ein Eintrag für das Feld created_by (bei mir 839), und die metadata sehen bei mir in der Datenbank auch einen Hauch anders aus, aber das ist Kleinkram. Die catid wäre eigentlich immer 8 für Rezepte, das kann man fest verdrahten. Ich habs mal in den Sourcerer reingeschubst und ein paar mal laufen lassen, die neuen Artikel sind einwandfrei erzeugt worden.

So, jetzt gilts: wie kriegen wir unsere WordPress-Datensätze hier rein?

Eigentlich müssen wir nur diese drei Felder ordentlich füllen:

$article->title            = 'This is my super cool title!';
$article->alias            = JFilterOutput::stringURLSafe('This is my super cool title!');
$article->introtext        = '<p>This is my super cool article!</p>';

Schön wärs natürlich, wenn wir die WordPress-Kategorien als Tags mit übernehmen könnten, aber das wär nur ein extra-Zuckerl, jetzt kümmere ich mich erstmal um den Überbau, und der erfordert etwas Planung. Ich geh mal mein Denkmützerl aufsetzen und melde mich dann wieder mit einem neuen Beitrag.

 

Hätt ich doch beinah übersehen: das Bewertungsformular

Das wär mir doch beinah durch die Lappen gegangen, wir brauchen natürlich noch das Feedback-Formular bei den Rezepten. Im Original-Inselfischkochbuch sieht das so aus:

bewertungsformular_screenshot

bewertungsformular_screenshot

Ich habs in WordPress natürlich mit dem Contact Form 7 angelegt, und dann das Plugin WP Post Signature genutzt, um das Formular automatisch am Ende jedes Beitrags einzufügen. Wollen mal sehen, was sich in Joomla daraus machen läßt. Ich hab mal einen ersten Versuch mit BreezingForms gestartet, schauen wir mal wie weit wir kommen.

Die Anforderungen im Klartext:

  1. das Formular soll am Ende jedes Rezeptes automatisch angehängt werden
  2. damit ich weiß, welches Rezept bewertet wurde, muss der Titel (oder wenigstens die ID) aus der E-Mail hervorgehen

Zu 1.: das hört sich einfacher an als es ist, denn eigentlich sind es zwei Anforderungen, wenn nicht sogar drei.

Das BreezingForms-Plugin

Um ein BreezingForms-Formular überhaupt in einem Artikel anzeigen zu können, muss man das BreezingForms-Plugin installieren. Das findet man, wenn man das BreezingForms-ZIP entpackt hat, unter plg_breezingforms.zip . Nach der Installation muss es noch aktiviert werden, das geht unter Erweiterunge->Module-> Suche nach „breezing“, Pluginname BreezingForms aktivieren. Erst jetzt hat man die Möglichkeit, ein BreezingForms Formular auch in einen Artikel einbinden zu können, und zwar  mit der Syntax:

{ BreezingForms : formularname }

Das fett markierte ist der Name des Formulars. Aber damit haben wir noch nicht viel gewonnen, schließlich müßte man diesen Code am Ende jedes Rezeptes manuell einfügen, und das war nicht die Anforderung.

Wie wärs stattdessen mit einem Modul?

Dafür braucht man laut crosstec noch das extra-Modul, mod_breezingforms.zip. Nach der Installation freigeben nicht vergessen! Dann kann man ein neues Modul vom Typ „BreezingForms“ anlegen und das gewünschte Formular angeben. Falls es nicht angezeigt wird kann es sein dass in den Moduloptionen in der Menüzuweisung „auf keinen Seiten“ steht, das muss man natürlich auf „auf allen Seiten“ ändern.

So, und was hat uns das gebracht?

Auch das Modul muss man erstmal per Hand am Ende jedes Rezeptes einfügen, das ist noch kein grosser Fortschritt aber gemach, gemach, das wird schon noch.

Warum nicht einen Override anlegen?

Weil bei einer Änderung der default.php das Bewertungsformular unter allen Artikeln angezeigt werden würde, nicht nur unter den Rezepten. Wir machen stattdessen mal ein alternatives Layout, das ist mir sympathischer.  Dafür kopiert man sich in den Ordner /templates/dein-templates/dein-template/html/com_content/article die Datei default.php unter einem eigenen Namen, ich nenns mal meins.php. In dieser Datei sucht man dann nach dem Eintrag

<?php echo $this->item->text; ?>

Darunter kopiert man die folgende Zeile:

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

Jetzt geht man nochmal in das Modul für das Bewertungsformular zurück und ändert die Modulposition in bewertungsformular – Schreibweise genau einhalten!

Daraufhin muss man noch in einem beliebigen Rezept unter dem Reiter Optionen das Layout auf „meins“ stellen, dann wird das Formular nach dem Rezepttext auch angezeigt.

Das war jetzt aber auch noch nicht der Bringer?

Schließlich muss man auch das alternative Layout per Hand anwählen, ich geb zu, da ist noch nicht viel gewonnen, genauso schnell hat man ein Modul eingefügt. Das hängt jetzt alles daran, dass ich keinen Weg gefunden habe, ein Modul nur für eine Kategorie anzeigen zu lassen, und ich hab ein paar Stunden lang danach gesucht, bislang ohne Erfolg.

Ich hätte da noch so’ne Idee

Man könnte ja einen Override auf die default.php anlegen und abfragen, welche Kategorie der aktuelle Artikel hat, und abhängig vom Ergebnis das Modul anzeigen lassen oder nicht. Mal sehen, wie weit wir damit kommen.

In unserem Override der default.php für den Artikel suchen wir nach der Stelle:

<div itemprop=“articleBody“>
<?php echo $this->item->text; ?>
</div>

Danach schubsen wir eine Datenbankabfrage rein:

<?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;
        }
    ?>

Was hab ich gemacht? Mir die ID des aktuellen Artikels geholt, diese in den Select auf die #__content reingeschubst und mir so die ID der Kategorie geholt. Rezepte sind bei mir Kategorie 8, das frage ich mit dem If ab und zeige das Formular nur an, wenn dies zutrifft. Das wars schon! Die Debug-Ausgaben kann man noch rausschmeissen, aber so funktionierts. Endlich wieder mal ein bisschen Spaß auf der Datenbank!

Was jetzt noch fehlt: die Übermittlung der Rezept-ID oder des Titels

Weil mir die ganze Menage nichts hilft, wenn ich nicht weiss zu welchem Rezept die Bewertung abgeschickt wurde. Da hilft nur Nachforschen beim BreezingForms-Support, aber dazu gibts einen neuen Beitrag.

Benutzerdefinierte Felder – im Beitrag anzeigen

Analog zu den Custom Fields in WordPress kann man auch in Joomla selbstdefinierte Felder zu den Artikeln anlegen. Ich bin da gleich mal reingerasselt, weil ich zu den Kochbüchern ein Feld „Unverbindliche Preisempfehlung“ haben wollte. Schauen sie mal unter Inhalte/Felder/Neu die Liste der Feldtypen an – da ist alles dabei, bloß keine Währung, der einzige verfügbare Zahlentyp ist Integer. Ein Datumsfeld sucht man auch erstmal, es versteckt sich hinter dem Feldtyp „Kalender“. Ansonsten stecken in den Feldtypen jede Menge Angaben, die ich für Spielerei halte, unter anderem auch ein Feldtyp „Farbe“, man sehe und staune:

rgb_feld

rgb_feld

Damit kann man sich im Frontend den RGB-Code der gewählten Farbe anzeigen lassen, wofür das auch immer gut sein soll.

Wenigstens kann man beim Anlegen der Felder angeben ob es sich um ein Pflichtfeld handelt, dann kriegt man beim Ausfüllen der Beiträge einen Hinweis, wenn was fehlt. Wo sich die Felder und die Feldinhalte wiederfinden lassen, dazu gibts einen:

Blick auf die Datenbank

Man kann auch noch Feldgruppen anlegen, aber das lassen wir mal aussen vor, sonst wirds zu kompliziert. Ich möchte jetzt einfach in einem Artikel den Wert eines benutzerdefinierten Feldes anzeigen, und zwar an beliebiger Stelle im Inhalt. Und – da bin ich ein bißchen eigen – ich möchte das auf relativ einfachen Weg in einem Sourcerer Codesnippet tun, ohne Overrides  und ohne eigens programmierte Module. Kann ja wohl nicht so schwer sein!

Dafür tun wir mal einen beherzten Griff in die Datenbank. Die relevanten Tabellen sind die #__contents, aus der brauchen wir die ID des Artikels, die Tabelle #__fields, aus der holen wir uns den Feldnamen und nach Belieben auch die Feld-ID, und schliesslich die #__fields_values, in der stecken schlussendlich die Werte der Felder. Ich habs mal kurz nach Access reingeschubst, da stellen sich die Beziehungen so dar:

fields_beziehungen

fields_beziehungen

Also, frisch auf, einen Join über alle drei Tabellen gebastelt, wichtig ist hier die item_id, die identifiziert unseren Artikel:

felder_join_alle_drei

felder_join_alle_drei

Der Select dazu sieht so aus und ist relativ straightforward:

SELECT Fields_values.field_id, Fields.name, Fields_values.item_id, Fields_values.value
FROM Fields INNER JOIN (Content INNER JOIN Fields_values ON Content.[id] = Fields_values.[item_id]) ON Fields.[id] = Fields_values.[field_id];

Wir wollen aber nur die Feldinhalte zum aktuellen Artikel ausgeben, ich nehm mal den mit der ID 22 und klemm noch eine Where-Klausel dran. Dann können wir uns auch den Join auf die #__contents noch sparen, die ID des Artikels ist ja erstmal fest.

SELECT Fields_values.field_id, Fields.name, Fields_values.item_id, Fields_values.value
FROM Fields INNER JOIN Fields_values ON Fields.[id] = Fields_values.[field_id]
WHERE (((Fields_values.item_id)=“22″));

Ergebnis wie erwartet:

felder_nur22

felder_nur22

Und jetzt kann man sich anhand der field_id oder dem field name ein benutzerdefiniertes Feld herauspicken, ich nehm mal den Namen:

SELECT Fields_values.field_id, Fields.name, Fields_values.item_id, Fields_values.value
FROM Fields INNER JOIN Fields_values ON Fields.[id] = Fields_values.[field_id]
WHERE (((Fields.name) Like „farbtest“) AND ((Fields_values.item_id)=“22„));

Schon haben wir den Datensatz mit dem richtigen Feldwert eingekreist:

felder_nurfarbtest

felder_nurfarbtest

Na bitte, geht doch!

Und wo kriegen wir jetzt die aktuelle Artikel-ID her?

Das ist eine berechtigte Frage, man kommt ihr aber mit folgender Konstruktion bei:

$article_id = JFactory::getApplication()->input->get('id');

Jetzt basteln wir uns wie gehabt ein neues Datenzugriffsobjekt in der Variablen $db, dazu muss man noch ein bisschen bei den doppelten und einfachen Hochkommata aufpassen und das Präfix #__ nicht vergessen, aber das sollte eigentlich problemlos klappen.:

$db = JFactory::getDBO();

$query = „SELECT #__fields_values.field_id, #__fields.name, #__fields_values.item_id, #__fields_values.value
FROM #__fields INNER JOIN #__fields_values ON #__fields.id = #__fields_values.field_id
WHERE (#__fields_values.item_id = „.$article_id.“ ) and (#__fields.name like ‚farbtest‚);“;

Die Variable $article_id schubsen wir in unsere Where-Klausel rein, den Namen des benutzerdefinierten Feldes auch, das kann man auch auf eine Variable legen, oder man verdrahtet es fest wie ich es getan habe. Das war schon der ganze Zauber!

Query zuweisen und ausführen:

$db->setQuery($query);
$result = $db->execute();

Objektliste laden, auch wenn wir nur 1 Zeile im result haben:

$results = $db->loadObjectList();

Ausgabe des Wertes aus dem Feld value mit foreach(), :

foreach ($results as $zeile) :
echo $zeile->value;
endforeach;

Das wars, da haben wir den Wert unseres benutzerdefinierten Feldes, und der kann an beliebiger Stelle im Artikel positioniert werden. Die anderen benutzerdefinierten Felder kann man natürlich auch mit dem Namen ansprechen, das geht ganz genau so wie hier vorgeführt.

Kleine Spielerei am Schluss: wenn wir schon einen RGB-Farbwert haben, möchten wir die Farbe auch sehen, ich mach mal ein Quadrat von 300 px Kantenlänge. Dann kommt in der foreach-Schleife noch eine Variablenzuweisung mit:

foreach ($results as $zeile) :
$aktuelle_farbe = $zeile->value;
echo $zeile->value.“<br>“;
endforeach;

Die verwenden wir jetzt in einer Div für das Farbquadrat:

echo „<div style=’background-color:“.$aktuelle_farbe.“; width: 300px; height: 300px;‘><h2>Aktuelle Farbe</h2></div>“;

farbquadrat

farbquadrat

Na siehste, haben wir doch noch eine Anwendung für den Feldtyp „Farbe“ gefunden!

Nachtrag

Ich bin gefragt worden, warum ich denn nicht ein alternatives Layout für die Anzeige der Felder angelegt habe und dann einfach dort an der richtigen Stelle mit:

<?php echo $this->item->jcfields[x]->value; ?>

das Feld mit der Nummer x einfüge. Ganz einfach: ich wollte den Feldinhalt innerhalb des Beitragstextes ausgeben, das ist der ganze Witz an der Sache. Das geht im Template nicht, da dort der Beitragstext als Ganzes mit <?php echo $this->item->text; ?> hereingeholt wird, und man keine Chance hat da innerhalb etwas zu positionieren. Ist der Sinn und Zweck der Übung jetzt etwas klarer?

Ein Blick auf die Datenbank: Content und Konsorten

Einen Überblick über die in Joomla enthaltenen Tabellen kann man hier in der Joomla Documentation zum Thema Tables finden. Da werden allerdings nur die Tabellenstruktur und die Felddefinitionen aus der Datenbank zusammengefasst und keine weitere Erklärung dazu geliefert – das meiste davon könnte man auch im phpmyadmin herausfinden. Zur Tabelle contents heißt es zum Beispiel nur lapidar: „This table is used to store the content of your Joomla! core articles.“ Ah ja. Das hätte man sich evtl. selber denken können.

Also ist es vielleicht ganz interessant, mal ein bißchen hinter die Kulissen zu gucken, aber mit über 70 Tabellen macht es einem Joomla da nicht gerade einfach. Trotzdem, fangen wir mal an.

Die Tabelle contents

Wie wir am Anfang schon gesehen haben, macht Joomla im Gegensatz zu WordPress keinen Unterschied zwischen Beiträgen und Seiten, es ist zunächst mal alles Content. Das ist auch völlig legitim, da sehr fein gesteuert werden kann, ob ein Element einen Kategorieblog, einen einzelnen Artikel, ein Modul oder sonst etwas enthalten soll.

Fangen wir mal von vorne an:

id klar, AutoIncrement und Primärschlüssel

asset_id Fremdschlüssel auf die assets-Tabelle, dazu später mehr

title auch klar, der Titel des Artikels, wie er im Frontend angezeigt wird

alias sanitized Form des Titels für die sprechende URL

introtext und fulltext: da machen wir mal einen kleinen Break und eine Erklärung.

Introtext und Fulltext

Joomla bietet eine sehr komfortable Möglichkeit, im Artikeleditor ein „Weiterlesen“-Tag an beliebiger Stelle im Text einzufügen:

weiterlesen

weiterlesen

Das hat den Effekt, dass in der Blog-Ansicht nur der Text vor dem Tag angezeigt wird und ein Button zum (eben!) weiterlesen angezeigt wird:

weiterlesen_screenshot

weiterlesen_screenshot

Was da im Hintergrund auf der Datenbank passiert, ist recht kurios. Sobald man das Weiterlesen-Tag eingefügt hat, landet der Text vor dem Tag im Feld introtext, der Rest im Feld fulltext, der Artikeltext wird also auf zwei Datenbankfelder aufgeteilt. Nimmt man das Tag wieder heraus (Editor auf Textmodus umschalten und das Tag <hr id=“system-readmore“ /> löschen), wird wieder der gesamte Text im Feld introtext gespeichert, das Feld fulltext ist dann wieder leer.

Weiter gehts mit den Feldern der Tabelle content:

state entspricht dem post_status von WordPress, hier gilt für Joomla 3.x, soweit ich das eruieren konnte:

  • 0 = unpublished
  • 1 = published
  • 2 = archived
  • -2 = marked for deletion

catid ist die ID der Kategorie und ein Fremdschlüssel auf die categories-Tabelle.

created_by ist die UserID und ein Fremdschlüssel aus der #__users-Tabelle

Dann folgen noch ein paar Timestamps, deren Feldnamen recht selbsterklärend sind, und weiter hinten als kleines Zuckerl für SEOler ein  Feld hits, in dem die Anzahl der Zugriffe auf den betreffenden Artikel hochgezählt wird.

Lassen sie sich vom Feld images nicht aufs Glatteis führen, da steht nichts weiter drin, wenn sie kein Einleitungsbild oder komplettes Beitragsbild ausgewählt haben. Bilder, die sie im Artikeleditor eingefügt haben, stehen wie in WordPress gehabt als img-tag im Beitragstext, default Pfad ist das images-Verzeichnis: <img src=“images/avocado.jpg“ alt=““ />

Na, und was seh ich da? Der alt-Text ist leer, Schlamperei! Aber das ist eine andere Baustelle, und ich wette, das Verwirrspiel um die alt-Texte ist derselbe systemimmanente Bug wie in WordPress. Aber zur Bilderverwaltung in Joomla gibts ein andermal mehr!

Haben sie auch ein Deja vu?

Mit den hier vorgestellten Feldern aus der contents wäre es schon mal ein leichtes Spiel, einen einfachen WordPress-Beitrags-Datensatz zusammenzubauen. Vielleicht ist das der Grund, warum es eine Menge Konverter von Joomla nach WordPress schon gibt, googlen sie mal nach „joomla to wordpress converter“. Der Weg von WordPress nach Joomla ist da schon steiniger, weil die Joomla-Artikel wesentlich komplexer aufgebaut sind, aber darüber habe ich mich bereits in diesem Artikel ausgelassen. Ich bleibe dran…

Damit lassen wir es mal gut sein mit der Contents-Tabelle, und werfen als nächstes einen Blick auf die Bilderverwaltung in Joomla.