Include / require en relatieve paden

Status
Niet open voor verdere reacties.

XavierJeukens

Gebruiker
Lid geworden
7 jun 2007
Berichten
22
Hallo,

ik heb een regelmatig terugkerend probleem op mijn website dat telkens wel provisorisch is op te lossen, maar dat wacht op een échte oplossing. Ik heb de volgende bestanden:

inc/header.inc.php
inc/footer.inc.php
inc/symbols.inc.php

In de rootmap staan verschillende bestanden, en die roepen d.m.v. een require een header en een footer aan. De footer roept echter ook nog de symbols aan, op de volgende manier:

require "inc/symbols.inc.php";

Ik heb gemerkt dat de map ('inc/') erbij moet staan, ook al staan symbols.inc.php en footer.inc.php in dezelfde map. Ik ga er dus van uit dat php 'kijkt' vanuit het hoofdbestand, en dan ligt alles in de map 'inc/'. Maar het gaat mis wanneer ik een bestand in een submap heb staan, zoals '/verhaaltjes'. Als ik dan in het bestand 'verhaaltjes/verhaaltje1.php' de verwijzingen naar de header en footer voorzie van het prefix '../' dan gaat dat goed, maar symbols.inc.php (aangeroepen vanuit de footer) wordt dan natuurlijk niet meer gevonden.

Mijn vraag: hoe kan ik in php-bestanden op een absolute manier verwijzen naar andere php-bestanden, zonder dat dit gevoelig is voor de plaats waarop dat php-bestand vervolgens zelf weer wordt aangeroepen?

Ik maak op dit moment géén gebruik van templates, maar ga hier de komende dagen aan werken. Wellicht zit hier al een oplossing in verwerkt? Aangezien het vooral gaat om telkens terugkerende elementen, zoals de header en de footer.

Alvast bedankt voor uw hulp!
 
Gewoon een variabele aanmaken in de trend van $root (Het handigste is om die in een bestand te zetten welke je vaak include. Het bestand met je SQL gegevens bijvoorbeeld) en dan het volgende doen.
PHP:
$root = "http://www.jouwwebsite.nl/";

require($root ."inc/symbols.inc.php");
 
@ThaDevil: door een http:// te verwerken in je include, zorg je ervoor dat de include remote opgehaald wordt. (er wordt een complete http request gemaakt). Daarnaast moet je server ingesteld staan op remote connections. Dus met http:// ervoor is minder handig. Verder werkt de $root methode overigens prima. Gewoon in ieder PHP bestand waarin je een include maakt, even specificeren waar je root zit (../../../) of een functie schrijven die de root bepaald op basis van het opgevraagde adres.

In plaats van $root zou je ook set_include_path() kunnen gebruiken. Dit is dezelfde methode als $root, alleen hoef je niet overal meer include($root . "..."); te doen. Reference: http://www.php.net/set_include_path.

Wout
 
Hartelijk dank voor de hulp!

Echter, deze twee oplossingen heb ik al her en der gebruikt, en ik twijfel nog of dit degelijke oplossingen zijn.

In het geval van Tha Devil was mijn kritiek ook, dat dit via de http-header gaat met de nodige overhead.

In het geval van sickman, blijft het probleem eigenlijk bestaan. Wellicht begrijp ik het als PHP-newbie niet helemaal goed, maar als ik een $root definiëer heb ik volgens mij twee opties:
- of ik doe dat in elk bestand, en dan moet ik dus bij een domeinverhuizing overal alles gaan zitten aanpassen
- of ik doe het in een config-bestand, maar daar moet naar verwezen worden en dan blijf ik hetzelfde probleem houden: het config-bestand staat vanuit de overige bestanden gezien in wisselende mappen (soms in '/inc' en soms in '../inc').

Dan zou je dus kunnen zeggen dat je in elk bestand absoluut verwijst naar het config-bestand, en daar m.b.v. de methodes aangereikt door sickman de paden instelt naar de header en footer, correct? Het enige dat je dan dus niet centraal 'afspreekt', maar lokaal, is waar je config-bestand te vinden is. Dat definieer je dus in elk php-bestand opnieuw.

Is dit echt de meest ideale optie? Of is er een manier om je root op te vragen, daar het pad naar de header en footer achter te zetten, en daar altijd op een universele manier naar te verwijzen zonder dat je http daarvoor gebruikt? Een manier, die blijft werken ook als je het bestand in kwestie een map dieper plaatst, of juist een map hoger plaatst?
 
Beste Xavier,

PHP heeft, afhankelijk van hoe je je config instelt natuurlijk, ingesteld dat hij in twéé mappen kijkt om te includen. Map 1 is in de root van het bestand dat door de browser is aangevraagd. Map 2 is in de root van het document dat de include aanroept. Voorbeeld:

folder/file1.php ==> include("file4.php");
folder/file2.php ==> include("file3.php");
folder/file3.php
file4.php ==> include("file5.php");
file5.php ==> include("folder/file1.php");

resultaat nadat je de pagina op vraagt met de browser:
file1: include niet gevonden
file2: include prima
file3: niks relevants
file4: opent file5.php, opent file1.php
file5: opent file1.php

In de file die je opvraagt moet je dus even de goede relatieve URL in. Vervolgens kun je in alle sub includes gewoon relatief tot zijn eigen include linken.

Dit is een vrij ingewikkelde methode die, wanneer je een goede structuur hebt voor je website, niet gebruikt hoeft te worden. De antwoorden in die vermeld staan in de vorige antwoorden zijn wat efficienter.

Als je wilt kun je je structuur posten zodat we hem misschien kom kunnen buigen naar een structuur die niet zulke ingewikkelde includes vereist.

Wout
 
Hartstikke bedankt Wout! Nu komen we ergens :D

Ik heb pas amper een jaar ervaring met php en sql, dus of mijn structuur oké is weet ik eigenlijk niet. Na de nodige overweging heb ik 'm als volgt opgezet:

In de root staan al mijn hoofdpagina's, zoals een mailpagina, een hoofdpagina, pagina's met informatie die zich beperkt tot één pagina, etc. Alle pagina's maken gebruik van twee includes: header.inc.php en footer.inc.php.

Alle in te voegen bestanden zijn in de map /inc geplaatst. Daarin staan dus bijvoorbeeld:
  • header.inc.php
  • footer.inc.php
  • meta.inc.php (met een uitgebreide lijst aan meta informatie, die wordt ge-include in de header)
  • config.inc.php (met een hele reeks aan constanten, zoals paden naar directories met images e.d. of de datum van vandaag in een gewenste notatie)
  • en nog een reeks aan bestanden met code die veel terugkeert, zo is er ook een bestand functies.inc.php die ook door de header wordt aangeroepen

In de root bevinden zich meerdere mappen die te maken hebben met onderdelen van de site. Bijvoorbeeld: /fotoalbum. Ik neem deze even als voorbeeld, want de andere onderdelen werken net zo.

Om het probleem met de includes te omzeilen, heb ik nu in mijn root een bestand fotoalbum.php. Deze roept nu allerlei bestanden aan in de map /fotoalbum, zo blijf ik altijd 'in de root werken'.

Liever wilde ik het bestand fotoalbum.php omdopen tot index.php en in de map /fotoalbum plaatsen. Maar als ik daar dus de includes herschreef tot bijvoorbeeld: '../inc/header.inc.php' dan gingen de includes in het header-bestand vervolgens dus fout.

Ik hoop dat ik zo een beetje duidelijk heb gemaakt hoe mijn indeling op het moment is. Is dit zo'n beetje de standaard wijze van werken, of kan het beter?
 
Beste Xavier,

Dé standaard manier staat eigenlijk nergens beschreven. Ik ben van mening dat er ook niet één manier is, maar dat er een aantal manieren zijn die zeer goed werken.

Als ik spreek uit mijn ervaringen is het bij PHP het makkelijkste om naar de root toe te werken, en dat is precies wat je nu doet. Wanneer je al je bestanden die je oproept in de / map zet heb je oa de volgende voordelen:
- je includes werken altijd
- je css/js/flash en wat er ook op je pagina staat werkt
- je links werken ook altijd.
Die twee boven vereisen wel dat je absoluut linkt. Dus een link maak je niet als "bestand.php" maar als "/bestand.php".

Je kunt natuurlijk op meerdere manieren naar je _root toe werken. De methode die jij gebruikt is in principe prima, totdat je een grote website krijgt. Dan wil je niet honderden bestanden in je _root map hebben staan. Persoonlijk vind ik het heel prettig om alles in de index.php te laden. In dat geval link je bijvoorbeeld naar index.php?pg=1 en zorg je dat wanneer pg==1, de index.php netjes je fotoalbum inlaad. Als je dat een beetje doorvoert kun je het gemakkelijk uit je database tappen. Een andere mogelijkheid zou index.php?pg=fotoalbum/fotoalbum.php zijn. In dat geval laat je gewoon $pg in je index.php in. Opgesomd heb je dan dus de keuze uit:
- index.php?pg=1 (1 komt terug in een Array in index.php, of in je database)
- index.php?pg=fotoalbum.php (laad gewoon in wat er bij $pg staat)

De eerste optie werkt opzich prima, maar pg=1 zegt je gebruiker helemaal niks. Dat is op te lossen via de methode die ik dadelijk noem.

De tweede optie werkt wel, maar het ziet er #1 niet uit en #2 ziet iedereen je structuur en een gezellige bos uien typt die url los in in de browser en krijgt een lekkere reeks aan foutmeldingen.

De oplossing voor beide problemen is .htaccess. In .htaccess kun je de opgevraagde URL ombuigen naar een andere URL. Je kunt er bijvoorbeeld in schrijven dat wanneer ik /appels-schillen/ open, je het document index.php?pg=1 moet openen. In dat geval ziet de gebruiker appels-schillen en open je index.php?pg=1. Ziet er al een heel stuk duidelijker uit. Mocht je nog niet bekend zijn met .htaccess, zoek dan even wat documentatie op op internet. Teveel om hier uit te leggen. De code die je uiteindlejk nodig gaat hebben is:
RewriteEngine On, eenmalig om de .htaccess duidelijk te maken dat je URLs wilt herschrijven
en RewriteRule ^appels-schillen/$ index.php?pg=1.

Het klinkt als het eitje, dat is het ook, alleen kost het even tijd om hem te koken. Kortom: even proberen en je komt er gaandeweg achter.

Het perfecte framework vind je pas door veel te stuntelen en veel te doen. Een framework moet passen bij je werkwijze, en die verschilt helaas danwel gelukkig per persoon.

Mocht je vastlopen dat hoort ik het wel.

Wout
 
Superbedankt! Deze methode, met .htacces en het inladen via de index, lijkt mij zeker een hele goede. Ik ga erin duiken. Heel fijn dat ik me met vragen nog even mag melden.
 
Is het niet zo dat je met mod_rewrite zeker met absolute URL's moet werken?

Ik heb het eens geprobeerd (lang geleden) en hikte steeds tegen de afbeeldingen e.d. aan m.b.t. de url's.

Als je met index.php?pg=1 bijvoorbeeld appels-schillen.php include is het logisch dat je de afbeeldingen vanaf appels-schillen.php benaderd, dus als je die in een map img hebt staan zul je in appels-schillen.php de url naar een afbeelding zo maken: img/plaatje.gif.

Gebruik je dus mod_rewrite en je houdt het zo maar je heb als link geen /?pg=1 maar /appels-schillen dan werd bij mij steeds naar een afbeelding gezocht in de map appels-schillen/img...

Wellicht dat dit op te lossen is door die / voor de url's van afbeeldingen te zetten maar dat heb ik dus nooit geprobeerd. Is dat daadwerkelijk de oplossing?
 
@Tha_Devil: in het geval dat jij beschrijft is / inderdaad "de" oplossing.

Wout
 
Opgelost

Mensen, hartelijk dank! We zijn nu enige tijd verder en ik heb de oplossing die uit deze discussie naar voren kwam inmiddels gebruikt. Het werkt echt prima, dus vraag = opgelost!
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan