Das Frontend zur Knowledgebase

Die Knowlegdebase wird nun über das Backend komplett gepflegt. Wie wird ein Webseitenbesucher die Knowledgebase vermutlich nutzen? Der Nutzer, der nicht weiß wonach er suchen soll, wird mit der Auswahl einer Kategorie näher an sein Ziel gelockt. Der versierte Nutzer weiß was er will und gibt über die Suche das entsprechende Suchwort ein. Damit dies etwas moderner wirkt, soll der Nutzer nicht mit jeder Suchanfrage einen Button "Suche" klicken. Vielmehr soll die Suche in Echtzeit erfolgen. Los gehts...

Das Frontend wird im Verzeichnis conf/frontend/ angelegt. Dazu wird der Ordner knowledgebase angelegt. Wie auch im Backend werden auch bestimmte Verzeichnisse im Frontend benötigt: configuration, controller, etc, lang, model, template und view. Im Verzeichnis configuration wird die Datei Configuration.php mit dem folgenden Inhalt angelegt.

?php
/**
 * memyc.org, © 2014-2018. All rights reserved.
 *
 * Memyc - Me and my content. The Frontend / Backend framework
 *
 * @author  Andreas Lehmann
 */
namespace memyc\feuser\knowledgebase {
    defined('SEC_VAR') or die('Direct access to this location is not allowed');
    /**
     * Class Configuration
     *
     * Configuration for knowledgebase
     *
     * @package memyc\feuser\knowledgebase
     */
    class Configuration
    {
        const DEPENDENCIES = 'memyc\frontend\content,memyc\feuser\jquery';
        /**
         * @var array Call this extension for given content type
         */
        public $aContentPluginFor = array('search');
        /**
         * @var array JS files to load on demand
         */
        public $jsBottomPageOnDemandFileList = array(
            'etc/js/default.js',
        );
    }
}

Als Abhängigkeiten gibt es hier jQuery, damit AJAX-Anfragen nicht händisch programmiert werden müssen. Neu ist hier das Array jsBottomPageOnDemandFileList. Dieses sorgt dafür, dass die Javascriptdatei default.js an das Ende der Frontendausgabe gehangen wird. Und zwar immer nur dann, wenn auch die Knowledgebase geladen wird. Dies hat den Vorteil, dass die JS-Datei nur dann geladen wird wenn sie benötigt wird.

Die Datei Controller.php in controller hat den folgenden Aufbau:

?php
/**
 * memyc.org, © 2014-2018. All rights reserved.
 *
 * Memyc - Me and my content. The Frontend / Backend framework
 *
 * @author  Andreas Lehmann
 */
namespace memyc\feuser\knowledgebase{
    defined('SEC_VAR') or die('Direct access to this location is not allowed');
    /**
     * Class Controller
     *
     * @package memyc\feuser\knowledgebase
     */
    final class Controller
    {
        /**
         * Controller constructor.
         *
         * @param \memyc\interfaces\Request $oRequest
         * @param \memyc\interfaces\Response $oResponse
         */
        public function __construct(\memyc\interfaces\Request $oRequest, \memyc\interfaces\Response $oResponse)
        {
            $this->oRequest = $oRequest;
            $this->oResponse = $oResponse;
            $this->oRegistry = \memyc\resources\Registry::getInstance();
            $this->oMycTools = new MycTools($this->oRequest, $this->oResponse);
        }
        /**
         * Routing
         *
         * @return array
         */
        public function init()
        {
            $init[] = array();
            return $init;
        }

Im Verzeichnis etc wird das Verzeichnis js angelegt. Darin wird die Datei default.js benötigt, die bei Bedarf geladen wird. Dazu gleich noch mehr. Im Verzeichnis model wird die Datei Model.php mit dem folgenden Inhalt benötigt:

?php
/**
 * memyc.org, © 2014-2018. All rights reserved.
 *
 * Memyc - Me and my content. The Frontend / Backend framework
 *
 * @author  Andreas Lehmann
 */
namespace memyc\feuser\knowledgebase{
    /**
     * Class Model
     *
     * @package memyc\feuser\knowledgebase
     */
    class Model extends \memyc\bootstrap\mycbase\Model
    {
    }
}

Und zu guter letzt im Verzeichnis view die Datei View.php mit folgendem Inhalt:

?php
/**
 * memyc.org, © 2014-2018. All rights reserved.
 *
 * Memyc - Me and my content. The Frontend / Backend framework
 *
 * @author  Andreas Lehmann
 */
namespace memyc\feuser\knowledgebase {
    defined('SEC_VAR') or die('Direct access to this location is not allowed');
    /**
     * Class View
     *
     * View for knowledgebase
     *
     * @package memyc\feuser\knowledgebase
     */
    class View extends \memyc\bootstrap\mycbase\View
    {
    }
}

Wird nun wieder das Frontend mit dem Plugin aufgerufen wird immer noch die Meldung "Type knowledgebase is not defined." angezeigt. Dies soll sich nun ändern.

Die Ausgabe im Frontend

Wir legen die Datei ControllerContentKnowledgebase.php im Verzeichnis controller an.

?php
/**
 * memyc.org, © 2014-2018. All rights reserved.
 *
 * Memyc - Me and my content. The Frontend / Backend framework
 *
 * @author  Andreas Lehmann
 */
namespace memyc\feuser\knowledgebase{
    use memyc\resources\MycTools;
    defined('SEC_VAR') or die('Direct access to this location is not allowed');
    /**
     * Class ControllerContentKnowledgebase
     *
     * @package memyc\feuser\knowledgebase
     */
    final class ControllerContentKnowledgebase extends \memyc\bootstrap\mycbase\ControllerFrontend
    {
        /**
         * ControllerContentKnowledgebase constructor.
         *
         * @param \memyc\interfaces\Request $oRequest
         * @param \memyc\interfaces\Response $oResponse
         */
        public function __construct(\memyc\interfaces\Request $oRequest, \memyc\interfaces\Response $oResponse)
        {
            $this->oRequest = $oRequest;
            $this->oResponse = $oResponse;
            $this->oRegistry = \memyc\resources\Registry::getInstance();
        }
        /**
         * Init function for route calls
         *
         * @return array
         */
        public function init()
        {
            $init[] = array();
            return $init;
        }
        /**
         * Set Configuration for this type
         *
         * @param $oContentData
         */
        public function setContentData($oContentData)
        {
            $this->oContentData = $oContentData;
        }
        /**
         * Get Configuration for this type
         *
         * @return mixed
         */
        public function getContentData()
        {
            return $this->oContentData;
        }
        /**
         * Set Content type
         *
         * @param $sContentType
         */
        public function setType($sContentType)
        {
            $this->sContentType = $sContentType;
        }
        /**
         * Get Content type
         *
         * @return mixed
         */
        public function getType()
        {
            return $this->sContentType;
        }
        /**
         * The default class to show page content
         *
         * @return mixed|string
         * @throws \Exception
         *
         */
        public function show()
        {
                return "Hier kommt bald eine Ausgabe.";
        }
    }
}

DIe Methoden in dieser Klasse sind Standardmethoden, um mit dem Frontend zu arbeiten. Interessant ist im Konstruktur lediglich das Laden der Registry, die den Pfad zu unserem Templatepfad unseres Frontends enthält.

Wird nun das Frontend aufgerufen sehen wir erstmalig die Ausgabe "Hier kommt bald eine Ausgabe." Innerhalb der Methode show() müssen wir nun die Daten aus dem Backend hier im Frontend sichtbar machen.

Suchmaske erstellen

Die Kategorien sollen alle ausgelesen und in einer Auswahlliste sortiert dargestellt werden. Wir legen die Methode showCategory() in der Klasse ControllerContentKnowledgebase.php an. Die Kategorien werden über das Model über die Methode findAll() als Array ausgegeben. In jeder Arrayzelle befindet sich ein Objekt der Kategorie. Dieses Array muss nun an ein Template übergeben werden, welches die Ausgabe generiert. Damit die Ausgabe an einer bestimmten Stelle ausgegeben wird, können innerhalb der Templatedateien Platzhalter verwendet werden in die die Daten eingelesen werden. Die Zuweisung von Variablen an Platzhalter geschieht mit der Methode assign(), die von der Klasse View.php bereitgestellt wird. Damit die Ausgabe erfolgen kann, muss zu guter letzt die Templatedatei mit render() generiert und mit view() ausgegeben werden. Der komplette Codeblock sieht dann so aus:

private function showCategory()
{
    $oMycTools = new MycTools($this->oRequest, $this->oResponse);
    $sCSRFToken = $oMycTools->getCsrfToken();

    $sTemplateFile = 'template/categoryselect.html';
    $oCategory = new \memyc\feuser\minishop\Model('memyc\beuser\knowledgebase\entity\category');
    $oCategory->orderby('title', 'ASC');
    $oCategoryData = $oCategory->findAll();
    $oView = new View($this->oRequest, $this->oResponse);
    $oView->assign('listcategories', $oCategoryData);
    $oView->assign('CSRFToken', $sCSRFToken);
    $oView->render($this->sPath, $sTemplateFile);
    return $oView->view();
}

Erstelle nun im Verzeichnis template die Datei categoryselect.html mit dem folgenden Inhalt:

   


       
       

           
       

       

   

Hier wird in der Schleife {foreach ...} der Platzhalter listcategories befüllt. Platzhalter haben immer die Form { #PLATZERHALTER}. Den Iteratornamen könnt ihr frei vergeben. In diesem Beispiel ist es: iteration. Mit dieser Variable könnt ihr nun auf alle Eigenschaften der Kategorien zugreifen. In dem Fall benötigen wir die ID, {iteration.id} und den Titel, {iteration.title}. Schreiben wir in die Methode show() noch return $this->showCategory(); sehen wir im Frontend eine Auswahlliste aller Kategorien.

Wir legen die Datei knowledgebase.html an. Diese hat den folgenden Inhalt:

Die Templatedatei für die Suche
Die Templatedatei für die Suche

Die gerade erstellte Auswahlliste wird gleich in den Platzhalter category geladen. Neu ist hier ebenfalls der Platzhalter {translate key="searchfor" /}. Dieser sorgt dafür, dass statische Wörter in der Templatedatei je nach Ländereinstellung übersetzt werden. Der Schlüssel ist hier "searchfor". Statische Wörter
angezeigt und übersetzt werden, muss im Verzeichnis zum einen die Datei en.json und de.json angelegt werden. Diese Dateien sehen wie folgt aus:

Für en.json

{
  "meta": {
    "version": "1.0",
    "file": {
      "source-language": "en",
      "target-language": "en"
    }
  },
  "translation": {
    "category": {
      "source": "Category",
      "target": "Category"
    },
    "noresults": {
      "source": "No results found.",
      "target": "No results found."
    },
    "searchfor": {
      "source": "Search for",
      "target": "Suche nach"
    }
  }
}

Für de.json

{
  "meta": {
    "version": "1.0",
    "file": {
      "source-language": "en",
      "target-language": "de"
    }
  },
  "translation": {
    "category": {
      "source": "Category",
      "target": "Kategorie"
    },
    "noresults": {
      "source": "No results found.",
      "target": "Keine Suchergebnisse gefunden."
    },
    "searchfor": {
      "source": "Search for",
      "target": "Suche nach"
    }
  }
}

Es wird in der Datei nach dem Schlüssel "searchfor" gesucht und das Wort "Suche nach" entsprechend in die Templatedatei eingesetzt. Ausgangssprache, also source, ist immer Englisch. Es können beliebig weitere Sprachen ergänzt werden, wir beschränken uns aber auf Englisch und Deutsch.

Die finalen Methoden show() und getCategory() in ControllerContentKnowledgebase.php sehen wie folgt aus:
/**
 * The default class to show page content
 *
 * @return mixed|string
 * @throws \Exception
 *
 */
public function show()
{
    if (!empty($_POST)) {
return print_r($_POST);
    } else {
$this->sPath = $this->oRegistry->EXTENSIONS['memyc\feuser\knowledgebase']['relativePath'];
$sTemplateFile = 'template/knowledgebase.html';
$oView = new View($this->oRequest, $this->oResponse);
$oView->assign('category', $this->showCategory());
$oView->render($this->sPath, $sTemplateFile);
return $oView->view();
    }
}
/**
 * Show the list of all categories
 *
 * @return string
 * @throws \Exception
 */
private function showCategory()
{
    $oMycTools = new MycTools($this->oRequest, $this->oResponse);
    $sCSRFToken = $oMycTools->getCsrfToken();
    $sTemplateFile = 'template/categoryselect.html';
    $oCategory = new \memyc\feuser\minishop\Model('memyc\beuser\knowledgebase\entity\category');
    $oCategory->orderby('title', 'ASC');
    $oCategoryData = $oCategory->findAll();
    $oView = new View($this->oRequest, $this->oResponse);
    $oView->assign('listcategories', $oCategoryData);
    $oView->assign('CSRFToken', $sCSRFToken);
    $oView->render($this->sPath, $sTemplateFile);
    return $oView->view();
}

Asynchroner Abruf der Suchergebnisse

Wir nähern uns dem Ziel. Nun ist die Suchmaske fertig, doch noch muss das entsprechende Javascript erstellt werden, damit die geführten Eingaben auch Suchergebnisse ausgeben. Das Javascript wird als default.js unter etc/js erstellt und hat den folgenden Aufbau:

$(document).ready(function(){
    $('.form-control').bind("change keyup select",function(){
        // show that something is loading
        $('#response').html("Loading response...");
        var select = $( "#knowledgebase-select" ).val();
        var search = $( "#knowledgebase-search" ).val();
        var CSRFToken = $( "#knowledgebase-csrfToken" ).val();
        /*
         * 'mycservices/knowledgebase' - where you will pass the form data
         * $(this).serialize() - to easily read form data
         * function(data){... - data contains the response from mycservices/knowledgebase
         */
        $.post('mycservices/knowledgebase', { searchword: search, type: select, CSRFToken: CSRFToken }, function(data){
            // show the response
            $('#knowledgebaseresults').html(data);
        }).fail(function() {
            // just in case posting your form failed
            //alert( "Posting failed." );
        });
        // to prevent refreshing the whole page page
        return false;
    });
});

Es werden die Eingaben des Auswahlfeldes und des Eingabefeldes genommen und an die URL mycservices/knowledgebase geschickt. Diese Formulardaten müssen nun entgegebengenommen, ausgewertet und deren Rückgabewerte entsprechend zurückgeschickt werden.

Die finale Suchmaske

Die finale Suchmaske
Die finale Suchmaske

Der Kurs zur Entwicklung eigener Backend- und Frontenderweiterungen ist fertig. Sie haben in dem Kurs die wichtigsten Merkmale von Memyc kennengelernt und angewandt. Wenn Sie sich weiter vertiefen, werden Sie noch Möglichkeiten finden, um bestehende Inhaltstypen um Plugins zu erweitern.

Ich wünsche Ihnen viel Spaß beim Entdecken und Entwickeln.