Ik heb een vraagje,
Ik ben redelijk bekend met php maar net begonnen met OOP, nu heb ik elke class in een apart bestand gezet om zo in de toekomst bij projecten alleen de nodige class bestanden te kopieren en klaar.
Maar omdat ik vrij veel bestanden krijg, heb ik deze ingedeeld in mappen:
[classes]
-- [database]
-- -- select.class.php
-- -- update.class.php
-- -- insert.class.php
-- [form]
-- -- form.class.php
-- -- input.class.php
-- -- select.class.php
-- -- text.class.php
-- -- radio.class.php
En zo verder voor alle elementen, maar jullie krijgen een idee van mijn filestructuur.
Nu vraag ik mij af hoe ik dit het beste kan toevoegen aan mijn project?
Ideen van mij zijn:
1. Een __autoload() functie, maar deze komt in de war omdat de classes in verschillende mappen staan.
2. Een parent class (of gewone functie) die ik kan gebruiken om de classes aan te roepen:
waarbij de class 'files' voor elke class een functie heeft welke zorgen voor de juiste aanroeping, maar dit is niet OOP lijkt mij
3.alles handmatig includen, maar dan krijg ik bovenaan een lijst met includes waar je bang van wordt
4. Alle form classes in 1 bestand plaatsen, maar dan zit ik ook met mijn autoload functie want die weet niet dat de class input in form.class.php te vinden is omdat deze op classnaam zoekt
Mijn vraag is dan ook hoe jullir hier over denken en of ik het toch heel anders had moeten doen, de class bestanden zijn nu nog leeg dus kan nog alles wijzigen
Lees eens wat over namespaces en PSR-0 en gebruik een psr-0 classloader en je bent van alle problemen af en krijgt ook nog eens scopes!
De basis, elke klasse staat in een namespace: Kees\Form\Form (Form class in de Kees\Form namespace) en Kees\Form\Element\Input (Input class in de Kees\Form\Element namespace). Deze namespaces komen dan overeen met de directory structuur, waarbij alle \ omgezet wordt in een map en er .php achter wordt gezet:
Inderdaad moet je dat met namespaces doen, maar zou je 'selectQuery', 'updateQuery' en 'insertQuery' wel echt als losse files doen? ALs je dat met alles gaat doen, dan krijg je nogal een forse file-structuur volgens mij.
Je bent natuurlijk vrij om dat te doen, maar je zou ook deze in één class kunnen stoppen, en dat ze allemaal gebruik maken van de method 'query' (omdat alle 3 een zelfde basis hebben, met pdo bv: prepare/execute), zodat je niet 3 keer bijna hetzelfde hoeft te schrijven.
namespace Form;
class Form {
private $option = array();
private $name;
private $value;
public function __construct(){
}
public function _setVar($name,$value){
$this->option[$var] = $value;
}
public function _getVar($name){
return $this->option[$var];
}
public function __destruct(){
unset($name,$option,$value);
}
public function display() {
$this->html = 'Hello Wrld';
return $this->html;
}
}
Bedankt voor alle input WouterJ en Wijnand, ik heb de __SET() en __GET() toegevoegd ipv _setVar() en _getVar(), deze had ik extra weggelaten omdat ik dacht dat ik gelezen had dat deze functies gedr werden, maar dit bleek de __autoload() functie te zijn welke ik dan ook gelijk vervangen heb door de volgende:
met de database class ga ik pas aan de slag als ik de forms klaar heb, ook heb ik nog eens goed naar mijn input class gekeken en heb me gerealiseerd dat een radio button of checkbox gewoon een input veld is, welke dus nu ook gewoon onder input.class.php vallen
ps: viel me op als ik de php code knop gebruik([ PHP ]) dan werkt dit niet naar behoren, de [ code=php ] werkt wel goed.
>> ps: viel me op als ik de php code knop gebruik([ PHP ]) dan werkt dit niet naar behoren, de [ code=php ] werkt wel goed.
[.php] is voor links naar de php.net website, [.code=php] is voor php code blokken.
Thomas - 12/08/2014 12:36 (laatste wijziging 21/08/2014 20:25)
Moderator
Ik ben ook recent begonnen met het uitproberen van het automatisch laden van classes.
autoloading zonder namespacing
keesgerbers schreef:
1. Een __autoload() functie, maar deze komt in de war omdat de classes in verschillende mappen staan.
Dit probleem had ik ook. Gelukkig is daar de functie spl_autoload(). Deze heeft de volgende (standaard) eigenschap:
Citaat:
By default it checks all include paths to contain filenames built up by the lowercase class name appended by the filename extensions .inc and .php.
Je kunt dus directories toevoegen in je include_path waar de autoload-functionaliteit in kijkt (en de bestandsnamen kun je lowercase laten, wat ook wel fijn is).
Dan wil je nog structuur (subdirectories) op deze plaatsen hebben. Dit zul je ook op een of andere manier moeten verwerken in de naamgeving van je classes. Bijvoorbeeld door de gebruikmaking van underscores, elke underscore impliceert een subdirectory. Vervolgens pas je dit aan in de aanroep van spl_autoload(). Hiertoe kun je komen tot de volgende super simpele implementatie van een autoloader:
<?php
// voeg het pad naar je classes toe ($myClassPath)
// je kunt op deze manier meerdere paden toevoegen
set_include_path(get_include_path().PATH_SEPARATOR.$myClassPath);
// de autoloader (indien je geen gebruik maakt van namespaces)
// afhankelijk van je PHP versie zul je een aparte functie moeten maken
// of kun je een anonieme functie gebruiker zoals hieronder
spl_autoload_register(function($class) {
spl_autoload(strtr($class, '_', DIRECTORY_SEPARATOR));
});
?>
<?php
// voeg het pad naar je classes toe ($myClassPath)
// je kunt op deze manier meerdere paden toevoegen
Het bovenstaande is terug te vinden in (/te herleiden uit) de eerste twee comments op php.net. Hier staan af en toe zeer waardevolle reacties tussen.
Stel je hebt bijvoorbeeld de volgende directorystructuur:
/index.php
/classes/database.php (class Database)
/classes/database/mysqli.php (class Database_MySQLi extends Database)
Dan voeg je in index.php (waarin je de autoloader plaatst) de /classes directory toe aan je include path en kun je vervolgens in je index.php rechtstreeks een object van het type Database_MySQLi aanmaken (zonder require of include dus, dat is het hele punt van een autoloader).
EDIT: spl_autoload lijkt verder de fijne eigenschap te hebben dat deze de include paths controleert in de volgorde waarin deze geinclude zijn. Dit opent mogelijk een interessante toepassing: overriding. Stel dat je een application include path en een core include path hebt. In het eerstgenoemde pad zit je maatwerk en in het tweede pad je core functionaliteit. Stel nu dat je in een specifiek geval core functionaliteit wilt aanpassen voor een enkel project. Je zou dit kunnen doen door het aanpassen van de core file, maar je zou dit ook kunnen doen door de class te kopiëren naar je applicatie-directory en daar je aanpassingen te doen. Je moet er dan wel voor zorgen dat je applicatie-pad eerst toegevoegd wordt aan je include path. Als je dan een object van een (core) klasse wilt aanmaken zal eerst de applicatie-directory geïnspecteerd worden op het bestaan van de klasse. Natuurlijk kun je ook aan andere oplossingen denken zoals het extenden van een class (als dat mogelijk is!).
autoloading met namespacing
Met namespacing is het mogelijk nog simpeler (mits je PHP versie nieuw genoeg is en je geen conflicten hebt met gereserveerde woorden in de sterk verkorte namen van je classes lol). De enige twee dingen die je hoeft te doen (lijkt te hoeven doen?) zijn:
- het toevoegen van het pad / de paden waar classes te vinden zijn aan je include path
- het aanroepen van spl_autoload_register() (zonder argumenten of wat dan ook)
overige notities
spl_autoload_register() verdient overigens ook de voorkeur boven __autoload(), zie php.net.
Deze comment is goud waard. Het benadrukt (onder andere) het belang van het vermijden van operaties die gerelateerd zijn aan het filesystem (zoals het gebruik van _once, is_file en file_exists). Dit zijn (volgens mij) de "duurste" operaties die bestaan, vermijd deze dus indien mogelijk. Daarnaast heeft de auteur ook een punt door te zeggen dat je je autoload-functionaliteit zo simpel mogelijk zou moeten houden.
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.