Die beste Lösung ist es, einen einzigen Einsprungspunkt für alle Pfade der Anwendung zu haben (Front-Controller-Prinzip). Damit arbeiten auch so ziemlich alle Frameworks.
Einfach erklärt: Der Webserver wird so konfiguriert, dass alle eingehenden Requests (die nicht auf bestehende statische Ressourcen wie Bilder/CSS/… zeigen) transparent/intern an eine einzige Indexseite weitergeleitet werden. Dort wird anhand des Request-Pfads der gewünschte Inhalt ausgewählt/generiert und zurückgeliefert. Auf den URL im Browser hat das keinen Einfluss. Der Client bekommt davon also nichts mit.
Für den Apache sieht die übliche Konfiguration dazu so aus (.htaccess):
Code:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /path/to/app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
Mehr zum Beispiel hier:
http://silex.sensiolabs.org/doc/master/web_servers.html
* * *
Vor allem bei bestehendem Code mit mehreren Einsprungspunkten ist es leider manchmal nicht praktikabel, so vorzugehen. Ein Beispiel für einen solchen Aufbau:
Code:
config
config.inc.php
nav.inc.php
include
header.php
sidebar_left.php
sidebar_right.php
profile
edit.php
view.php
index.php
login.php
register.php
Die möglichen Einsprungspunkte, die per URL im Browser angewählt werden können, sind hier: /index.php, /login.php, /register.php, /profile/edit.php und /profile/view.php.
Eine praktische Vorgehensweise der Pfadorganisation bei einem solchen Aufbau besteht darin, im Code jeder „Einsprungspunkt-Datei“ den Pfad zum Root-Verzeichnis der Anwendung zu definieren und alle weiteren Verzeichnissystem-Pfade damit zu beginnen.
Für index.php:
PHP:
$pathToRoot = __DIR__;
require $pathToRoot . '/config/config.inc.php';
require $pathToRoot . '/include/header.php';
Für profile/view.php:
PHP:
$pathToRoot = __DIR__ . '/..';
require $pathToRoot . '/config/config.inc.php';
require $pathToRoot . '/include/header.php';
Wichtig ist hierbei die „Verankerung“ des Pfads per __DIR__. Diese magische Konstante liefert den absoluten Verzeichnissystem-Pfad der Datei, in der das jeweilige __DIR__ steht. Ein
__DIR__ . '/..' bedeutet also immer „das Elternverzeichnis der aktuellen PHP-Datei“.
Als Faustregel dazu: Jeder Verzeichnissystem-Pfad innerhalb einer Anwendung (für Includes, für Datei-Funktionen, …) sollte absolut angegeben werden. Absolute Pfadangaben, die sich dennoch flexibel an die Position des Codes im Dateisystem anpassen, lassen sich mit __DIR__ erzeugen. So werden beispielsweise Probleme mit einem unerwarteten Wert für das aktuelle Arbeitsverzeichnis vermieden.
Das Arbeitsverzeichnis ist üblicherweise das Verzeichnis der zuerst aufgerufenen PHP-Datei. Stünde in /config/config.inc.php der Code…
PHP:
$config = parse_ini_file('config.ini');
…, der eine Config-Datei aus dem /config-Verzeichnis einlesen soll, und würde config.inc.php von /profile/view.php eingebunden, würde parse_ini_file versuchen, die Datei /profile/config.ini zu öffnen, da das das Arbeitsverzeichnis ist.
So funktioniert es dagegen wie beabsichtigt:
PHP:
$config = parse_ini_file(__DIR__ . '/config.ini');
Weitere Details zu den Vorteilen von __DIR__:
http://www.ermshaus.org/2012/09/php-includes-niemals-ohne-dir
* * *
Ist auch das nicht praktikabel, weil beispielsweise die bestehende Codebasis zu umfangreich ist, um jede Datei entsprechend anzupassen, kann möglicherweise noch der Weg über eine globale Konfigurationseinstellung gegangen werden. auto_prepend_file wurde genannt. Das zentrale Setzen eines passenden Include-Pfads, der als Grundlage für alle Includes gilt, die einen Pfad nachfragen, der weder absolut noch relativ ist, könnte eine andere Option sein. (Ein absoluter Pfad beginnt mit "/" oder einem Verzeichnisbuchstaben (Windows), ein relativer Pfad beginnt mit "./" oder "../".)
Diese Varianten haben jedoch den Nachteil, konkrete externe Konfiguration zu benötigen, während die anderen genannten Varianten an der Stelle ohne auskommen.