Dateizugriff im PHP Destruktor

Beim proggen heute morgen bin ich auf folgendes Problem in der PHP Destruktor Funktion gestoßen. Ich weiss nicht ob es sich hierbei um einen Bug handelt auf jeden Fall hat es mich unnötig viel Zeit gekostet. Aber nun zum Problem. Wenn man im Destruktor einer PHP Klasse eine Funktion aufruft, die auf das Dateisystem zugreift, z.B file_get_contents(), muss der Pfad der Datei immer absolut bezüglich des Server Root angegeben werden und nicht relativ zum Wurzelverzeichnis des Servers!! Dies ist in sofern sehr verwirrend, weil es innerhalb eines PHP Skriptes keine Probleme beim aufrufen von file_get_contents() mit einem relativen Pfad gibt. Um das ganze zu illustrieren ein kurzes Code Snippet:

<?php
 
$rootpath = str_replace(DIRECTORY_SEPARATOR.'thisFile.php','',__FILE__);
define('ROOTPATH',$rootpath);
 
class foo
{
    //save Flag
    protected $_save = FALSE;
 
    protected $Object = null;
 
    private $file = '/var/dat/foo.dat';
 
    public function __construct()
    {
      $this->init();
    }
 
    private function init()
    {
      // Überprüfen ob Datei im Filesystem existiert.
      if(file_exists($this->file) && (file_get_contents($this->file) !== '')) 
      {
        //zuvor serialisiertes Objekt
        $this->Object = unserialize(file_get_contents($this->file));
      }
    }
 
    public function __destruct()
    {
      if ($this->_save === TRUE)
      {
        $contents = serialize($this); 
        file_put_contents(ROOTPATH.$this->file,$contents); 
      }
    }
}
?>

Hier kann man das ganze sehr schön sehen während ich im Konstruktor bzw. in dessen init() Funktion ohne Probleme den relativen Pfad benutzen kann, führt das weglassen der ROOTPATH Konstante im Destruktor zu folgender Fehlermeldung:

public function __destruct()
    {
      if ($this->_save === TRUE)
      {
        $contents = serialize($this); 
        file_put_contents($this->file,$contents); 
      }
    }
 
 
Warning: file_put_contents() [function.file-put-contents]: Unable to access /var/dat/foo.dat in C:\Programme\xampp\htdocs\Ilimitado\iEngine\thisFile.php on line 42
 
Warning: file_put_contents(/var/dat/iacl.dat) [function.file-put-contents]: failed to open stream: No such file or directory in C:\Programme\xampp\htdocs\Ilimitado\iEngine\thisFile.php on line 42

Also einfach merken, beim zugreifen aufs Dateisystem im Destruktor den absoluten Pfad verwenden!

Wenn dir dieser Beitrag gefällt, lade den Autor doch mal zu einem Drink ein ;-)

Broadcast us
  • Yigg
  • Webnews.de
  • Digg
  • MisterWong
  • del.icio.us
  • Technorati
  • DZone
  • Facebook
  • Google Bookmarks
  • Reddit
  • StumbleUpon
  • TwitThis

Tags: , ,

One Response

  1. Soweit ich weiß, ist das kein Bug, sondern “nur” ein wenig gemein.
    Das dürfte daran liegen, das der Destruktor schon im Apache-Umfeld läuft und nicht mehr den aktuellen Script-Pfad nutzt (je nachdem, wann das Objekt “aufgeräumt” wird). Du wirst wahrscheinlich(!) auch unterschiedliches Verhalten feststellen, wenn du mehrer Objekte der Klasse instanzierst und mittels unset() an unterschiedlichen Stellen zum aufräumen freigibst (mal wird es mittels relativen Angaben klappen, mal nicht). Mittels getcwd() etc. kann man das aber ggf. abfangen. Oder eben den absoluten Pfad nutzen, wie du es getan hast (IMHO best practise in diesem Fall).

    Das Gleiche kann dir auch an anderen Stellen passieren, so z.B. auch beim Aufrufen einer ggf. angegeben Callback-Funktion von ob_start(), die (warum auch immer) mit Pfadangaben arbeitet, denn dort wird das working directory ebenfalls zurückgesetzt.

    Bei all diesen Vorgängen spielt aber auch die Server-Software ein Rolle, kann sein das beim IIS andere Gemeinheiten versteckt sind und sich auf dem Apachen mod_php und die CGI-Version evtl. auch noch unterscheiden.

    By the way: nettes Blog, muss wohl öfter vorbeischauen :-D

Leave a Reply