Runonce

Aus Contao Community Documentation


betrifft
TYPOlight Version ab 2.7
Contao Version ab 2.9

Live Update nutzt diese, die Extensions nutzen diese auch: die Datei TL_ROOT/system/runonce.php

Diese Datei tut genau das, was der Name schon vermuten lässt. Sie wird nur einmal ausgeführt und anschließend gelöscht.
Bei jedem Seitenaufruf wird dazu geprüft, ob diese vorhanden ist und ggf. ausgeführt.

In der Extension legt man diese Datei dann im Pfad wie oben bereits angegeben ab.


Anwendungsbeispiele

Löschen einer Datei

<?php @error_reporting(0); @ini_set("display_errors", 0); 
try { 
    // Datei relativ zu TL_ROOT
    $file = 'system/modules/demo/delete_me.gif'; 
    $objFiles = Files::getInstance();
    $objFiles->delete($file);
} catch (Exception $e) { $errors[] = $e->getMessage(); }
?>

Die Fehlerausgaben, sollte es welche geben, werden in diesem Beispiel unterdrückt.

Datenbank Insert / Update

<?php @error_reporting(0); @ini_set("display_errors", 0); 
$objDatabase = Database::getInstance();
//
// Update database
try { 
    $objDatabase->execute("UPDATE `tl_demo_table` SET `demo_counter`=0 WHERE `demo_browser`='Unknown'");
} catch (Exception $e) { $errors[] = $e->getMessage(); }
//
// Insert database
try { 
    $objDatabase->execute("INSERT INTO `tl_demo_table` (`id`, `demo_counter`) VALUES (0, '10')"); 
} catch (Exception $e) { $errors[] = $e->getMessage(); }
?>

Datenbank Insert, OOP Variante

Quelle: Forum.

<?php
class RunonceJob extends Frontend
{
   public function __construct()
   {
       parent::__construct();
   }
   public function run()
   {
       $arrInsert=array(
           'action'    => 'runonce',
           'text'      => 'runonce'
       );
       $this->Database->prepare("INSERT INTO tl_log %s")->set($arrInsert)->execute();
   }
}
$objRunonceJob = new RunonceJob();
$objRunonceJob->run();
?>

Hinweis

Achtung.png Achtung: Vorsicht damit bei Extensions mit Abhängigkeiten zu weiteren Extensions.

Bringen 2 Extensions jeweils eine runonce.php mit, wird nur eine ausgeführt!

Hier ist der Author nicht sicher, ob die erste oder die letzte davon.


Modulbasierte runonce.php

Den nachfolgenden Code in die config.php des eigenen Modules einfügen. Den Pfad anpassen, "MODULNAME" durch den Verzeichnisnamen des eigenen Moduls ersetzen und eine runonce.php im config Verzeichnis erstellen.
Diese runonce.php wird beim nächsten Seitenaufruf einmalig ausgeführt und danach gelöscht.

$runonceFile = '/system/modules/MODULNAME/config/runonce.php';
if (file_exists(TL_ROOT . $runonceFile))
{
 include(TL_ROOT . $runonceFile);
 $objFiles = Files::getInstance();
 $objFiles->delete($runonceFile);
}

Nachteil dieser Variante: Die ER Verwaltung meckert, dass das Modul unvollständig sei, da nun eine Datei fehlt.
Eine Idee wäre, die Datei nicht zu löschen, sondern zu überschreiben:

$runonceFile = 'system/modules/MODULNAME/config/runonce.php'; // relativ zu TL_ROOT
if (file_exists(TL_ROOT . '/' . $runonceFile))
{
   $GLOBALS['runonce']['MODULNAME'] = false;
   include(TL_ROOT . '/' . $runonceFile);
   if ($GLOBALS['runonce']['MODULNAME'] === false) 
   {
       $objFiles = Files::getInstance();
       $objFiles->delete($runonceFile); // hier wird intern ein "TL_ROOT/" vorgesetzt
       //nun wieder neu anlegen mit neuem Inhalt
       $objFile = new File($runonceFile); // hier wird intern ein "TL_ROOT/" vorgesetzt
       $objFile->write("<?php \$GLOBALS['runonce']['MODULNAME'] = true; ?>");
       $objFile->close();
   }
}

Wobei man nun die file_exists Prüfung weglassen könnte.
Andererseits könnte man diesen Abschnitt immer im Modul lassen und nur durch Setzen der Variablen $runonceFile bestimmen, ob es was zu tun gibt oder nicht.

Probleme

Einen kleinen Nebeneffekt hat die ganze Sache. Es kommt öfters zu einer Fehlermeldung, sobald man die Datenbank Instanz nutzt; egal ob die funktions- oder objektorientierte Variante verwendet wird.
Am Ende der Seite erscheint die Meldung:

Fatal error: Exception thrown without a stack frame in Unknown  on line 0

Das Script selbst wird dabei ohne Probleme abgearbeitet, auch das Backend selbst wird dadurch nicht gestört.

Durch langes Experimentieren ist der Autor auf eine Lösung gekommen, die zumindest bei ihm funktioniert.
Dazu wird der include der runonce Datei mittels try - catch gekapselt. Wichtig dabei ist mit getMessage die Nachrichten auszulesen.
Hier nun der geänderte Code:

$runonceFile = 'system/modules/MODULNAME/config/runonce.php'; // relativ zu TL_ROOT
if (file_exists(TL_ROOT . '/' . $runonceFile))
{
  $GLOBALS['runonce']['MODULNAME'] = false;

  try
  {
    include(TL_ROOT . '/' . $runonceFile);
  }
  catch (Exception $e) { $errors[] = $e->getMessage(); }

  if ($GLOBALS['runonce']['MODULNAME'] === false) 
  {
     $objFiles = Files::getInstance();
     $objFiles->delete($runonceFile); // hier wird intern ein "TL_ROOT/" vorgesetzt
     //nun wieder neu anlegen mit neuem Inhalt
     $objFile = new File($runonceFile); // hier wird intern ein "TL_ROOT/" vorgesetzt
     $objFile->write("<?php \$GLOBALS['runonce']['MODULNAME'] = true; ?>");
     $objFile->close();
  }
}
Achtung.png Achtung: Leider hilft das nicht immer. Lösung gesucht!



--BugBuster 22:49, 17. Jul. 2010 (CEST)

Ansichten
Meine Werkzeuge

Contao Community Documentation

was passiert eigentlich, wenn man per zip alle gezippten cache-css cached, bevor der cache vom apache gezippt wird?

Christian de la Haye
Navigation
Verstehen
Verwenden
Entwickeln
Verschiedenes
Werkzeuge