login  Naam:   Wachtwoord: 
Registreer je!
 Forum

OOP class files structuur (Opgelost)

Offline keesgerbers - 22/10/2013 22:18 (laatste wijziging 22/10/2013 22:48)
Avatar van keesgerbersLid Hallo,

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:
  1. $proj=new files('form','database','....');
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

Met vriendelijke groet,

Kees

7 antwoorden

Gesponsorde links
Offline WouterJ - 22/10/2013 23:59 (laatste wijziging 23/10/2013 00:00)
Avatar van WouterJ HTML gevorderde 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:

  1. src/
  2. +--Kees
  3. | +--Database
  4. | | +--Query
  5. | | | +--SelectQuery.php
  6. | | | +--UpdateQuery.php
  7. | | ` +--InsertQuery.php
  8. | +--Form
  9. | | +--Form.php
  10. | | +--Type
  11. | | | +--Input.php
  12. | | | +--Radio.php
  13. | | | +--CheckBox.php
  14. | | | +--Select.php
  15. | | `
  16. | `
  17. `
Bedankt door: Wijnand, keesgerbers, Abbas
Offline Wijnand - 25/10/2013 12:39
Avatar van Wijnand Moderator 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.
Offline keesgerbers - 28/10/2013 11:52 (laatste wijziging 28/10/2013 11:55)
Avatar van keesgerbers Lid Ik heb nu dit met namespaces, het werkt in ieder geval perfect tot nu toe.
Filestructuur:
  1. | - index.php
  2. | + lib
  3. | | + admin_panel
  4. | | + database
  5. | | + form
  6. | | | - checkbox.class.php
  7. | | | - form.class.php
  8. | | | - index.php
  9. | | | - input.class.php
  10. | | | - radio.class.php
  11. | | | - select.class.php
  12. | | | - text.class.php

index.php:
  1. function __autoload($classname){
  2. $classname = strtolower($classname);
  3. $classname = str_replace('\\', '/', $classname);
  4. include_once 'lib/'.$classname.'.class.php';
  5.  
  6. }
  7.  
  8. $form = new Form\Form();
  9. echo $form->display();
  10.  
  11. $input = new Form\Input();
  12. $input->_setVar('name','test');
  13. echo $input->display();


lib/form/form.class.php:
  1. namespace Form;
  2. class Form {
  3. private $option = array();
  4. private $name;
  5. private $value;
  6.  
  7. public function __construct(){
  8.  
  9. }
  10.  
  11. public function _setVar($name,$value){
  12. $this->option[$var] = $value;
  13. }
  14.  
  15. public function _getVar($name){
  16. return $this->option[$var];
  17. }
  18.  
  19.  
  20. public function __destruct(){
  21. unset($name,$option,$value);
  22. }
  23.  
  24.  
  25. public function display() {
  26.  
  27. $this->html = 'Hello Wrld';
  28. return $this->html;
  29. }
  30.  
  31.  
  32.  
  33.  
  34. }
Offline Wijnand - 28/10/2013 12:15 (laatste wijziging 28/10/2013 12:16)
Avatar van Wijnand Moderator Wat je trouwens nog kan doen is __set() en __get() toevoegen in je class.

Dan hoef je niet steeds '_setVar()' toe te voegen, maar doe je gewoon:

  1. $input->name = 'test'; // ipv $input->setVar('name','test');


De methods zullen dan zijn:

  1. public function __set($k,$v) {
  2. $this->option[$k] = $v;
  3. }
  4. public function __get($k) {
  5. return $this->option[$k];
  6. }
Bedankt door: keesgerbers
Offline keesgerbers - 28/10/2013 13:39
Avatar van keesgerbers Lid 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:
  1. spl_autoload_register(function($classname){
  2. $classname = strtolower($classname);
  3. $classname = str_replace('\\', '/', $classname);
  4. include_once 'lib/'.$classname.'.class.php';
  5.  
  6. });


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.
Offline WouterJ - 28/10/2013 16:30
Avatar van WouterJ HTML gevorderde >> 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.
Offline Thomas - 12/08/2014 12:36 (laatste wijziging 21/08/2014 20:25)
Avatar van Thomas 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:
  1. <?php
  2. // voeg het pad naar je classes toe ($myClassPath)
  3. // je kunt op deze manier meerdere paden toevoegen
  4. set_include_path(get_include_path().PATH_SEPARATOR.$myClassPath);
  5.  
  6. // de autoloader (indien je geen gebruik maakt van namespaces)
  7. // afhankelijk van je PHP versie zul je een aparte functie moeten maken
  8. // of kun je een anonieme functie gebruiker zoals hieronder
  9. spl_autoload_register(function($class) {
  10. spl_autoload(strtr($class, '_', DIRECTORY_SEPARATOR));
  11. });
  12. ?>


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.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.3s