Elementtyp Inhaltselement zu langsam? Einfach kürzen!
Ich include auf einer meiner Webseiten öfter Inhaltselemente. Mit der Zeit braucht Contao aber immer länger, um die Auswahlliste mit den Inhaltselementen aufzulisten. Dabei kommt es natürlich auch darauf an, vor welchem Computer man gerade selbst sitzt. Während der Listenaufbau bei meinem PC gerade noch so erträglich ist, braucht (dasselbe) Contao auf meinem langsamen Laptop schon mal 1-2 Minuten für mehrere Tausend Einträge.
Doch braucht man wirklich alle Inhaltselemente? Wahrscheinlich selten. Was lag also näher, als die Anzahl der Elemente drastisch zu verkleinern.
Dazu legt man sich im system/modules-Ordner einen Unterordner z.B. zz_meins an und darin einen Unterordner dca mit einer Datei tl_content.php.
system/modules/zz_meins/dca/tl_content.php:
PHP-Code:
$GLOBALS['TL_DCA']['tl_content']['fields']['cteAlias']['options_callback'] = array('tl_mycontent', 'getAlias');
class tl_mycontent extends Backend
{
/**
* Import the back end user object
*/
public function __construct()
{
parent::__construct();
$this->import('BackendUser', 'User');
}
/**
* Get all content elements and return them as array (content element alias)
*
* @return array
*/
public function getAlias()
{
$arrPids = array();
$arrAlias = array();
$alter = time() - 86400 * 30; // Nur Inhaltselemente der letzten 30 Tage anzeigen
if (!$this->User->isAdmin)
{
foreach ($this->User->pagemounts as $id)
{
$arrPids[] = $id;
$arrPids = array_merge($arrPids, $this->Database->getChildRecords($id, 'tl_page'));
}
if (empty($arrPids))
{
return $arrAlias;
}
$objAlias = $this->Database->prepare("SELECT c.id, c.pid, c.type, (CASE c.type WHEN 'module' THEN m.name WHEN 'form' THEN f.title WHEN 'table' THEN c.summary ELSE c.headline END) AS headline, c.text, a.title FROM tl_content c LEFT JOIN tl_article a ON a.id=c.pid LEFT JOIN tl_module m ON m.id=c.module LEFT JOIN tl_form f on f.id=c.form WHERE a.pid IN(". implode(',', array_map('intval', array_unique($arrPids))) .") AND (c.ptable='tl_article' OR c.ptable='') AND c.id!=? AND c.tstamp >= ? ORDER BY a.title, c.sorting")
->execute(Input::get('id'), $alter);
}
else
{
$objAlias = $this->Database->prepare("SELECT c.id, c.pid, c.type, (CASE c.type WHEN 'module' THEN m.name WHEN 'form' THEN f.title WHEN 'table' THEN c.summary ELSE c.headline END) AS headline, c.text, a.title FROM tl_content c LEFT JOIN tl_article a ON a.id=c.pid LEFT JOIN tl_module m ON m.id=c.module LEFT JOIN tl_form f on f.id=c.form WHERE (c.ptable='tl_article' OR c.ptable='') AND c.id!=? AND c.tstamp >= ? ORDER BY a.title, c.sorting")
->execute(Input::get('id'), $alter);
}
while ($objAlias->next())
{
$arrHeadline = deserialize($objAlias->headline, true);
if (isset($arrHeadline['value']))
{
$headline = StringUtil::substr($arrHeadline['value'], 32);
}
else
{
$headline = StringUtil::substr(preg_replace('/[\n\r\t]+/', ' ', $arrHeadline[0]), 32);
}
$text = StringUtil::substr(strip_tags(preg_replace('/[\n\r\t]+/', ' ', $objAlias->text)), 32);
$strText = $GLOBALS['TL_LANG']['CTE'][$objAlias->type][0] . ' (';
if ($headline != '')
{
$strText .= $headline . ', ';
}
elseif ($text != '')
{
$strText .= $text . ', ';
}
$key = $objAlias->title . ' (ID ' . $objAlias->pid . ')';
$arrAlias[$key][$objAlias->id] = $strText . 'ID ' . $objAlias->id . ')';
}
return $arrAlias;
}
}
Zuerst wird im GLOBALS-Array der options_callback von Contao mit einer eigenen Funktion überschrieben. Und zwar mit einer Kopie der Funktion getAlias aus system/core/dca/tl_content.php (bei mir Contao 3.5.6).
Am Anfang der neuen getAlias-Funktion habe ich ein maximales Alter von 30 Tagen festgelegt. In den beiden Datenbankabfragen wird im Query " AND c.tstamp >= ?" hinzugefügt und beim execute die Variable $alter. Fertig!
Die beiden Querys ließen sich natürlich auch so noch abändern um alle Inhaltselemente von [news] zu berücksichtigen. Das überlasse ich aber den MySQL-Experten.