Problem mit relativen Pfadangaben in PHP



  • Hallo zusammen
    Ich habe ein riesen Problem mit relativen Pfadangaben in meinen PHP Scripten. Ich muss teilweise dieselben Scripte in mehreren anderen Scripten includen, welche sich an unterschiedlichen Positionen im Dateisystem befinden. Das währe an sich noch kein Problem, jedoch inlcuden jene includeten Dateien selbst wieder Daten mit include und dann funktionieren die relativen Pfadangaben teilweise nicht mehr. Die einzige Lösung, die ich im Moment sehe währen absolute Pfadangaben, doch dafür müsste ich irgendwie den absoluten Pfad bis hin zum root Directory von meinem Webspace bekommen...

    Wie macht ihr das?

    Gruss Samuel



  • Hallo,

    ich verstehe das Problem nicht?

    Wenn du z.B. folgende Dateistruktur hast:

    folder include
    -> file core.php
    -> folder lib
      -> file functions.php
      -> file classes.php
    

    Wenn du jetzt in core.php die Dateien "./lib/functions.php" und "./lib/classes.php" inkludierst, funktioniert das, unabhängig davon, von wo die core.php inkludiert wurde!



  • Ja aber sobald nun core.php auch noch was includiert funktionierts nicht mehr, wenn core.php von zwei verschiedenen Verzeichnissen aus includiert wird.



  • Ich weiss, was er meint: Wenn die Datei /var/www/inc/main.php per relativer Pfadangabe die Datei /var/www/inc/special/functions.php einbindet, diese wiederum per relativer Pfadangabe, weil sie selbst in manchen Unterseiten direkt eingebunden wird, wiederum die Datei /var/www/inc/other.php, funktioniert dieses Einbinden nicht ueber di erste Datei.

    Das Problem laesst sich nur ueber zwei Wege loesen:

    1. Absolute Pfadangaben
    2. Direkt (also jede Pfadangabenvariable beinhaltet den vollstaendigen Pfad)
    3. Indirekt (es gibt eine globale absolute Pfadangabe, andere Pfadangaben verwenden diese und ergaenzen sie lediglich)
    4. Vermeidung von vermischten Einbindungen, vor allem ueber unterschiedliche Ordner hinweg
    5. Alle Dateien, die eingebunden werden, in genau einem Pfad bewahren
    6. Korrekte Ausfuehrung - in der richtigen Reihenfolge - aller Einbindungen

    Um den absoluten Pfad zu erhalten, kannst du z.B. die Umgebungsvariable SERVERverwenden:DasisteineKettemitallenrelevantenServerAngaben,inkl.desaktuellenSkriptes.Z.B._SERVER** verwenden: Das ist eine Kette mit allen relevanten Server-Angaben, inkl. des aktuellen Skriptes. Z.B. **_SERVER['DOCUMENT_ROOT']:

    <a href= schrieb:

    php.net">Das Document Root-Verzeichnis, unter dem das aktuelle Skript ausgeführt wird, so wie es in der Konfiguration des Servers festgelegt wurde.



  • @heini
    Du hast mein Problem erkannt, danke! 😉
    Ich habe mittlerweile über 500 Scriptdateien und die möchte ich nicht alle in ein einziges Verzeichnis werfen, daher bevorzuge ich stattdessen die absolute Pfadangabe. Meine Frage ist nun, gibt es einge Möglichkeit, require und include anzuweisen, ein Prefix zu verwerden?



  • Ah, okay, verstanden.

    Das Problem lässt sich sehr einfach und elegant lösen.
    Du definierst in jeder Datei der 1. Ausführungsschicht (also jede Datei, die quasi als oberste Instanz vom User aufgerufen werden kann) eine Konstante, die den von dort relativen Pfad zum Hauptverzeichnis enthält.

    In sämtlichen Include-Anweisungen deiner Bibliotheken verwendest du nun diese Konstante + den vom Hauptverzeichnis aus betrachtet relativen Pfad zur Datei.

    Zur Verdeutlichung:

    folder htdocs: index.php

    define('root', './');
    

    folder htdocs/inc/special: functions.php

    include(root.'inc/other.php');
    

    Inkludierst du nun z.B. von der Datei htdocs/asubdir/test.php oder htdocs/inc/whatever.php aus, dann definierst in diesen Dateien einfach root := './../' und alles läuft weiter wie gewohnt. Es sieht auf den ersten Blick recht kompliziert aus, ist aber tatsächlich eine einfache und elegante Möglichkeit, das Problem komplett zu umgehen.



  • Noch eleganter, weil ohne Extra Konfigvariable, ist eine absolute Adressierung von der aktuellen Datei aus:

    require_once ( dirname(__FILE__)."/../lib/foo.php" );
    


  • Naja, ich habe die Erfahrung gemacht, dass man den Pfad zum Hauptverzeichnis immer wieder braucht, und sei es nur im Output irgendwelcher Graphiken, die an einer zentralen Stelle berechnet werden. Daher lässt sich das leicht kombinieren.

    An sich aber noch besser, stimmt.



  • Ishildur schrieb:

    gibt es einge Möglichkeit, require und include anzuweisen, ein Prefix zu verwerden?

    Soweit ich weiss gibt es einen solchen Luxus bisweilen noch nicht. Aber du koenntest - solltest du im Besitz eines Linux-, UNIX- oder BSD-aehnlichen Systems sein - per Anweisung einfach alle 'include('-Textbausteine durch 'include(root.' ersetzen. Genau fuer solche Zwecke wurden sie ja geschrieben. Am einfachsten macht sich das per Shell\1:

    #!/bin/bash
    D=/var/www/inc
    
    # Hauptordner nicht vergessen:
    # Alle PHP-Dateien auflisten
    FILES=$(find $D -type f -name "*.php")
    
    # Jede Datei durchgehen
    for file in $FILES
    do
    
        # Dateinamen ausgeben
        echo $file
    
        # Text ersetzen
        cat $D/$file | sed 's/include\(/include\(root\./g' > $D/$file
    
    done
    echo .
    
    # Ordner auflisten
    PATH=$(find $D -type d -name "*")
    
    # Jeden Unterordner durchgehen
    for path in $PATH
    do
    
        # Ordner ausgeben:
        echo $path
        echo ----------
    
        # Alle PHP-Dateien auflisten
        FILES=$(find $D/$path -type f -name "*.php")
    
        # Jede Datei durchgehen
        for file in $FILES
        do
    
            # Dateinamen ausgeben
            echo $file
    
            # Text ersetzen
            cat $D/$path/$file | sed 's/include\(/include\(root\./g' > $D/$path/$file
    
        done
    
        echo .
    
    done
    
    # Programmende
    exit 0
    

    Hinweis: Das habe ich nicht getestet. Habe mich nur grad kurz belesen, ein paar Zeilen Code kopiert, umgeschrieben und nach Logik weiterentwickelt. Ob das hinhaut, sollte nochmal ueberprueft werden.

    EDIT: Vergiss es. Du nutzt vermutlich einen Webhoster, der laesst dich vermutlich auch nicht auf seine Shell... Versuch's alternativ mit einer PHP-Datei:

    <?php
    
    function conv($f) {
        // Datei zum Lesen oeffnen
        if(($h=fopen($f,"r"))!==false) {
            // und auslesen
            $tmp=fread($h,sprintf("%u",@filesize($f)));
            fclose($h);
    
            // Datei zum Schreiben oeffnen
            if(($h=fopen($f,"w"))!==false) {
                fwrite($h,preg_replace("/([include\(|include_once\(|require\(|require_once\(])/",$1."root.",$tmp));
                fclose($h);
                return true;
            }
        }
        return false;
    }
    
    function start($p) {
        // Aktuellen Ordner oeffnen
        if(($h=opendir($p))!==false) {
    
            // Alle Dateien und Ordner auflisten
            while(($f=readdir($h))!==false) {
    
                // Dateien "konvertieren"
                if(!is_dir($p."/".$f)) conv($p."/".$f);
    
                // Und Ordner wieder durchsuchen
                else if($f!="." && $f!="..") start($p."/".$f);
            }
        }
        return true;
    }
    
    start("/var/www/inc");
    
    ?>
    

    Ebenfalls nicht getestet und auf der Schnelle getippt...


Anmelden zum Antworten