[php] Class methods vs functions

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben al even bezig met het maken van een tamelijk uitgebreide website, deze bevat:
-Admins
-Klanten
-Producten
-Facturen
-...

Voor elke soort heb ik nu een class gemaakt
vb.
Admins bevat de methods nieuwAdmin(), wijzigAdmin(), verwijderAdmin(), getAdminById(),...
ook is er
Klanten bevar de methods nieuwKlant(), wijzigKlant(), verwijderKlant(), getKlantById(),...

Ook wordt er gebruik gemaakt van een database class (singleton)

Nu begon ik zo stilaan te twijfelen of ik het wel juist doe, want ik maak van elke class immers maar 1 instantie. Heb ik nu het OOP niet goed begrepen en moet ik hier een nieuwe visie over krijgen of is dit wel correct dat ik voor elk 'element' dat functies heeft een class aanmaak?

Want als dit zo is kan ik beter geen classes gebruiken en enkel gebruik maken met files met functies erin ipv classes met methods niet?

Acties:
  • 0 Henk 'm!

Verwijderd

Classes gebruiken is hier sowieso mooier/beter dan functies. Het is makkelijker te snappen als je de namen van de functies aanpast. Als je al in de class Admin zit, moet je niet de functie ook nog eens nieuwAdmin noemen, dan kun je 'm gewoon nieuw() noemen. En wat bijvoorbeeld als je wijzig() aanroept bij Admin en het nog niet opslaat in de database(om wat voor reden dan ook). Dan kun je de wijzigingen later altijd nog aanroepen, bij een bestand met alleen functies gaat dat zomaar niet.

Wat ik sowieso adviseer is gewoon een framework als kohana/codeigniter/cakephp te gebruiken. Dan kun je er Models van maken(admins, klanten, producten). Kijk hier bijvoorbeeld maar even naar: http://docs.kohanaphp.com/general/models .

Ik hoop dat dit je helpt

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt, heb echter nog een vraagje...

Situatie:
ik heb een class klanten;
Een admin maakt een nieuwe klant aan dmv de methode $klanten->nieuw($naam, $voornaam,...)
In deze class gebeurd de validatie, als er wat fout loopt wat is de beste manier dit door te geven?
Met een bool (True,False) weet je enkel of er iets foutgelopen is, of is het handiger een integer te returnen? (vb 100-> Succes, 200-> gebruikersnaam niet ingevuld, 201 -> Wachtwoord niet ingevuld,...)

Acties:
  • 0 Henk 'm!

  • Foamy
  • Registratie: November 2006
  • Laatst online: 10:31

Foamy

Fulltime prutser

In hoeverre komen de gegevens bij klasses overeen? Je kunt bijvoorbeeld een standaard 'user' class maken, en die vervolgens extenden als een admin en/of normale user. Kijk vooral ook goed naar je database ontwerp en pas daar (indien nodig) het ontwerp van je classes op aan..

blub


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Admins en Klanten hebben bijna niets gemeen, daarmee dat ze ook twee verschillende classes krijgen.
Het extenden van een user met admin of klanten is dus niet van toepassing.
Maar toch bedankt voor de tip!

Even mijn 2de vraag herhalen:
Situatie:
ik heb een class klanten;
Een admin maakt een nieuwe klant aan dmv de methode $klanten->nieuw($naam, $voornaam,...)
In deze class gebeurd de validatie, als er wat fout loopt wat is de beste manier dit door te geven?
Met een bool (True,False) weet je enkel of er iets foutgelopen is, of is het handiger een integer te returnen? (vb 100-> Succes, 200-> gebruikersnaam niet ingevuld, 201 -> Wachtwoord niet ingevuld,...)

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 12:57

DexterDee

I doubt, therefore I might be

Als je twijfelt aan de meerwaarde van je klasse structuur ten opzichte van functions, dan is dat vrijwel zeker een goede indicatie dat je de OOP principes verkeerd toepast. Object georienteerd programmeren is niet een kwestie van een nieuwe syntax aanleren, maar het is een hele andere kijk op dezelfde vraagstelling.

Wat ik vaak zie bij beginnende programmeurs is dat ze al snel roepen dat ze objectgeoriënteerd kunnen programmeren, maar eigenlijk beperkt zich dat tot het praktisch kunnen toepassen van de syntax die nodig is voor classes. Zo wordt een verzamelbak van functies niet meer in functions.php gezet, maar komt er een class met al deze nuttige functies als methods. En daarna komt logischerwijs het besef dat dat niet veel van elkaar verschilt. Het echte objectgeoriënteerd programmeren is een methodiek die een radicaal andere denkwijze vereist.

Het is heel moeilijk in een paar zinnen de essentie aan te geven van OOP. Een goed objectmodel definieert entiteiten en abstraheert complexiteit en zorgt dat gemeenschappelijke functionaliteit gedeeld kan worden op één plaats, zonder duplicatie van code. Het zorgt tevens voor een (hiërarchische) relatie tussen de entiteiten en zorgt ervoor dat er validatie kan plaatsvinden op de structuur van een entiteit.

Je zegt dat klanten en admins bijna niks gemeen hebben, maar volgens mij zijn het beiden gebruikers van de website die allebei op dezelfde manier inloggen en alleen al op dat punt een overlap hebben met elkaar. Om te voorkomen dat je twee keer een stukje functionaliteit moet maken om gebruikersgegevens te valideren, kun je natuurlijk een functie maken en deze bij allebei aanroepen. Beter is om dit soort basisfunctionaliteit in een klasse te stoppen en afgeleiden te maken naar de verschillende typen gebruikers. Verder denk ik dat er bepaalde velden zijn die voor alle typen relevant zijn, zoals een e-mail adres.

Je vraag over foutafhandeling heeft niks met OOP te maken, dat is weer een heel nieuw vraagstuk. Dit kun je op verschillende manieren oplossen. Een van die manieren is het gebruiken van exceptions. In de constructor doe je de validatie en je definieert van te voren een aantal specifieke exceptions die kunnen optreden. Bij een validatiefout gooi je een exceptie op die vang je af in de code die de constructor aanroept. Dat kan met een try {} catch blok. In de aanroepende code zorg je er dan voor dat de juiste actie voor de juiste exceptie genomen wordt.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
In mijn geval komen klanten niet overeen met admins, klanten worden enkel aangemaakt om contactgegevens in op te slaan en te koppelen aan facturen, terwijl admins diegene zijn die inloggen en klanten aanmaken.

Die try - catch - throw gebruik ik nu in mijn database class maar hoe kan dat handig zijn in bv nieuw(), als hij dan throwed moet hij toch weer meteen ook catchen en returnen... Momenteel return ik altijd een int van 3 karakters 100 altijd voor geslaagd, 200 voor niet ingevulde forms, 300 voor geen correcte vorm, 400 voor te korte input, 500 te lange input, ... Als ik dit blijf gebruiken gaat de persoon na mij hopelijk geen rare gezichten trekken?

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 12:57

DexterDee

I doubt, therefore I might be

Verwijderd schreef op vrijdag 05 februari 2010 @ 17:27:
In mijn geval komen klanten niet overeen met admins, klanten worden enkel aangemaakt om contactgegevens in op te slaan en te koppelen aan facturen, terwijl admins diegene zijn die inloggen en klanten aanmaken.

Die try - catch - throw gebruik ik nu in mijn database class maar hoe kan dat handig zijn in bv nieuw(), als hij dan throwed moet hij toch weer meteen ook catchen en returnen...
Nee, de class method nieuw() throwed de exception en de code die $klant->nieuw() aanroept catcht de exception. Door een specifieke exception te throwen in plaats van een integer behou je de semantische integriteit en plaats je de foutafhandeling op de juiste plaats. Ook kun je zo cascading exceptions gebruiken voor meer controle over je errorafhandeling.

De method nieuw() is trouwens niet zo handig op zo'n object. Ten eerste moet je een leeg object instantiëren om die method te mogen aanroepen (tenzij de class/method static is, maar dat is niet echt gewenst in deze situatie). Ten tweede kun je deze method aanroepen op een gevuld object om het zo te recyclen en dat kan erg verwarrend zijn en is foutgevoelig.

Een mogelijke oplossing zou zijn om in de constructor een optionele parameter in te bouwen die aangeeft wat het id van de klant is in de database, dus function __construct($klant_id = null)
Als je een method save() maakt, kun je kijken of $klant_id is meegegeven, zo niet dan betreft het een nieuwe klant, anders update je de huidige klant aan de hand van het id.

Een andere oplossing het het maken van een factory class die een klant object kan maken via verschillende ingangen. Aangezien PHP geen native ondersteuning heeft voor polymorphisme, is een factory een nette oplossing. Zo kun je de volgende methods hebben:
KlantFactory::GetKlantById($id)
KlantFactory::GetKlantByUsername($name)
KlantFactory::NewKlant($firstname, $lastname)

Om maar een voorbeeldje te geven.

Een int van 3 karakters kan trouwens niet, het is een int van 3 digits of een string van drie karakters.

[ Voor 43% gewijzigd door DexterDee op 05-02-2010 17:56 ]

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dus in de praktijk:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$klanten = new klanten;
try{
$klanten->nieuw();
catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage();
}
?>
<?php
class klanten{
public function nieuw(){
throw new Exception('Fout.');
}
?>

Bedoel je het zo?

[ Voor 3% gewijzigd door Verwijderd op 05-02-2010 17:55 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op vrijdag 05 februari 2010 @ 17:55:
Dus in de praktijk:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$klanten = new klanten;
try{
$klanten->nieuw();
catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage();
}
?>
<?php
class klanten{
public function nieuw(){
throw new Exception('Fout.');
}
?>

Bedoel je het zo?
Die geeft een parse error. :9

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Heb hem ook niet getest, is enkel bedoeld om te weten of ik begrijp wat er bedoeld werd...

Acties:
  • 0 Henk 'm!

  • OnTracK
  • Registratie: Oktober 2002
  • Nu online
Ik denk dat je toch even een stapje terug moet doen. Je gebruikt je klanten-object nu meer als een soort container van functies, wat waarschijnlijk de reden is dat je aan het twijfelen bent geraakt over het nut. Over het algemeen gebruikt men instanties van classes (objecten) als individuele objecten. Als je je class nu "klant" noemt, dan zou iedere instantie van die class (een object dus) een klant zijn.

Op een klant kun je bepaalde acties uitvoeren, dat zijn dan class-methods: wijzig() of verwijder() (je hebt een object nodig voor je er iets mee kunt doen)
Dan heb je ook nog functies waarbij je niet één klant-object behandelt, maar wel iets doet in de context van klanten. Over het algemeen zijn dit dan static methods binnen de class: bijvoorbeeld nieuw() of getKlantById() (je hebt niet een klant (object) nodig om een andere aan te maken, of eentje op te zoeken).

Not everybody wins, and certainly not everybody wins all the time.
But once you get into your boat, push off and tie into your shoes.
Then you have indeed won far more than those who have never tried.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@OnTracK nu je het zegt inderdaad er gaat hier een lichtje branden! Dit zal ook gelden voor facturen.

[ Voor 20% gewijzigd door Verwijderd op 05-02-2010 18:17 ]


Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 12:57

DexterDee

I doubt, therefore I might be

Dat komt al aardig in de richting, maar je moet wel specifieke exceptions gooien. Die exceptions kun je het beste definieren in een afgeleide van de PHP exception class:

PHP:
1
2
3
4
5
6
class KlantException extends Exception
{
    const KLANT_USERNAME_NOT_FILLED =   1;
    const KLANT_PASSWORD_NOT_FILLED = 2;
    const KLANT_INPUT_TOO_LONG = 3;
}


In je class doe je dan dit:
PHP:
1
2
3
4
5
6
7
8
9
class klant
{
    public function nieuw() {
        if([username not filled]) {
            $e = new KlantException('Username is not filled', KlantException::KLANT_USERNAME_NOT_FILLED);
            throw($e);
        }
    }
}

En in je code doe je dit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try {
    $klant->nieuw();
} catch (KlantException $e) {
    // een klant exception trad op
    $code = $e->getCode();
        switch($code) {
            case KlantException::KLANT_USERNAME_NOT_FILLED:
                [doe iets nuttigs]
                break;
            case KlantException::KLANT_PASSWORD_NOT_FILLED:
                [doe iets anders nuttigs]
                break;
        }
} catch (Exception $e) {
    // een ander type exception trad op
}


Ik zou hoe dan ook de classes anders opzetten als hoe het hier staat, zoals ik in mijn eerdere post al heb gesuggereerd. Dit voorbeeld illustreert alleen hoe de exceptions zouden moeten werken.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
1. Dus alle 'algemene bewerkingen' in een static zetten, de bewerkingen op 1 enkel admin/factuur/... in een methode zetten.

2. Dus elke class heeft ook een eigen exception class? Waarom doet men niet gewoon return 100, dit is toch veel korter en geeft ook een code terug die opgevangen kan worden...

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 12:57

DexterDee

I doubt, therefore I might be

Verwijderd schreef op vrijdag 05 februari 2010 @ 18:21:
1. Dus alle 'algemene bewerkingen' in een static zetten, de bewerkingen op 1 enkel admin/factuur/... in een methode zetten.
'algemene bewerkingen'? Noem het maar instantiëren van een nieuw object. Dat kun je dus op verschillende manieren doen:
- via een static method
- via de constructor
- via een factory class
2. Dus elke class heeft ook een eigen exception class? Waarom doet men niet gewoon return 100, dit is toch veel korter en geeft ook een code terug die opgevangen kan worden...
Het getal 100 heeft geen betekenis op zichzelf, een exception van het type KlantException wel. Het gaat allemaal over semantiek en semantisch programmeren. Iets dat erg relevant is als je OOP code schrijft en wat programmeurs na jou verwachten in de code. Bovendien kun je met een exception méér dan 1 waarde teruggeven. Je kunt in de afgeleide exception properties definiëren die je in de afhandeling kunt gebruiken. Daarnaast staan de errorcode constanten op een logische plaats en kan een goede programmeeromgeving (IDE) je helpen om deze constanten terug te vinden met class autocompletion, iets dat met losse constanten een stuk lastiger gaat. Als laatste kun je je errorafhandeling van 'eigen' errors en standaard runtime errors combineren met exceptions en kun je zoals eerder gezegd gebruik maken van cascaded exceptions.

Overigens hoeft elke class niet zijn eigen exception te hebben. Bij classes met sterk op elkaar lijkende exceptions kun je de exception class delen. Ook kun je een exception class voor een baseclass maken waar alle afgeleide classes gebruik van maken. Voor kleine applicaties zou je theoretisch zelfs een enkele exception class kunnen maken. Zo lang het maar logisch en semantisch correct blijft.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor al deze informatie! Het is enorm leerrijk voor me!

Acties:
  • 0 Henk 'm!

Verwijderd

Wellicht is het handig om één klasse genaamd user te hebben. Alle verschillende typen gebruikers leidt je daarvan af (lees: Extenden) waarbij je met behulp van het principe overschrijven eventueel methoden/properties verandert waar nodig. Een administrator is immers gewoon een gebruiker met wat meer rechten.

Het werkelijke doel voor elke OOP-programmeur is naar mijn mening altijd op zoek naar een manier om herbruikbare code te schrijven. NIet alleen is dit veel netter, maar op de lange termijn (zeker bij grotere projecten die uitgebreid moeten kunnen worden) zal dit ontzettend veel tijd en moeite schelen.

Om even terug te komen in jouw project. Je gaat op een gegeven moment met behulp van een RBACL (Role-Based Access Control List) aangeven welke gebruikers welke rechten hebben met betrekking tot de website. In dit geval hebben we al drie groepen gebruikers/roles: namelijk Administrators, Members (klanten) en Guests. Dit kan natuurlijk uitgebreid worden met nieuwe groepen gebruikers die toegang hebben tot een specifiek deel van de website, bijvoorbeeld medewerkers die beperkte administrator-rechten hebben. Het is natuurlijk top als je voor de back-end hiervoor alleen maar een klasse user hoeft te extenden en 3 of 4 properties/methoden hoeft over te schrijven in plaats van een compleet nieuwe klasse te moeten schrijven.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Maximized: enkel admins kunnen inloggen, klanten zijn er enkel om gegevens zoals contactpersonen en emailadressen en dergelijke bij te houden en te koppelen aan een factuur. Dus er is maar 1 soort user die kan inloggen, of ook maar iets kan uitvoeren. Dus ... extends user is overbodig.

Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Nu online
Ik denk dat het er hier omgaat dat er in de toekomst wellicht meerdere soorten users kunnen zijn.
Het is dan ook belangrijk om de user generieke dingen in de user klasse te zetten en dan een admin klasse te extenden. De standaard user kan evengoed geen ene ruk doen maar is er meer om het jezelf gemakkelijk te maken mocht je ooit een moderator user of iets dergelijks aan willen maken.
Daarnaast houd je zo zelf een mooie scheiding tussen de verschillende zaken.

*EDIT* Ik denk trouwens dat je de overeenkomsten over het hoofd ziet tussen de klant en de admin.
Beide hebben waarschijnlijk in ieder geval een identificatie van een soort, een (gebruikers)naam en een email-adres.
Dat er maar één van deze twee de rechten heeft om iets te kunnen doen is niet relevant. (en is ook maar één eigenschap die anders is)
Admins bevat de methods nieuwAdmin(), wijzigAdmin(), verwijderAdmin(), getAdminById(),...
ook is er
Klanten bevar de methods nieuwKlant(), wijzigKlant(), verwijderKlant(), getKlantById(),...
Het feit dat je gelijknamige methods gebruikt diw zeer waarschijnlijk eenzelfde soort actie uitvoeren, laat al zien dat een user class iets kan toevoegen.

[ Voor 45% gewijzigd door Caelorum op 06-02-2010 09:40 ]


Acties:
  • 0 Henk 'm!

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 12:26
Verwijderd schreef op vrijdag 05 februari 2010 @ 20:16:
Het is natuurlijk top als je voor de back-end hiervoor alleen maar een klasse user hoeft te extenden en 3 of 4 properties/methoden hoeft over te schrijven in plaats van een compleet nieuwe klasse te moeten schrijven.
Eh, het voordeel is toch juist dat je geen/minder dingen hoeft over te schrijven/typen (of kopiëren/plakken). Ook met de rest van je eigen bericht is dit enigszins in tegenspraak. Je zult wel 'overschrijven2' bedoeld hebben. In het Engels override, misschien is 'herdefiniëren' duidelijker.
@Voutloos: Ja, met genoeg context en logisch denken kun je veel taalfouten herkennen en dus de boodschap goed begrijpen, maar we willen toch ook geen "je snap tog wa kbedoel jonguh". Ik ga ook niet over elk taalfoutje zeuren, maar af en toe kan ik het niet laten en dit was zowel vreemd (in mijn ogen, net als "hij weergeeft niks") als 'stom', omdat het juist min of meer het tegenovergestelde betekent van wat er bedoeld werd. (Het had dus "hoeft te overschrijven" moeten zijn.) Wel bewonderenswaardig dat iemand de moeite neemt om een Nederlandse term te gebruiken trouwens (tenzij je die helemaal zelf gaat verzinnen (hier niet het geval); daar wordt het alleen maar onduidelijk van).
En zo produceer ik (met wat hulp) toch weer een flink offtopic stuk i.p.v. een korte opmerking. :$

[ Voor 40% gewijzigd door Raynman op 06-02-2010 14:14 ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
offtopic:
Raynman, anders leg je ff aan jezelf uit hoe je die zin met een beetje begrijpend lezen eenvoudig goed interpreteren kan 8)7

{signature}


Acties:
  • 0 Henk 'm!

Verwijderd

Raynman schreef op zaterdag 06 februari 2010 @ 10:47:
[...]
Eh, het voordeel is toch juist dat je geen/minder dingen hoeft over te schrijven/typen (of kopiëren/plakken). Ook met de rest van je eigen bericht is dit enigszins in tegenspraak. Je zult wel 'overschrijven2' bedoeld hebben. In het Engels override, misschien is 'herdefiniëren' duidelijker.
@Voutloos: Ja, met genoeg context en logisch denken kun je veel taalfouten herkennen en dus de boodschap goed begrijpen, maar we willen toch ook geen "je snap tog wa kbedoel jonguh". Ik ga ook niet over elk taalfoutje zeuren, maar af en toe kan ik het niet laten en dit was zowel vreemd (in mijn ogen, net als "hij weergeeft niks") als 'stom', omdat het juist min of meer het tegenovergestelde betekent van wat er bedoeld werd. (Het had dus "hoeft te overschrijven" moeten zijn.) Wel bewonderenswaardig dat iemand de moeite neemt om een Nederlandse term te gebruiken trouwens (tenzij je die helemaal zelf gaat verzinnen (hier niet het geval); daar wordt het alleen maar onduidelijk van).
En zo produceer ik (met wat hulp) toch weer een flink offtopic stuk i.p.v. een korte opmerking. :$
offtopic:
Dacht dat het werkwoord overschrijven in de gebruikte context wel duidelijk genoeg was. Technisch gezien ben ik het helemaal met je eens, echter is het in dit geval een vrij duidelijk geval wat betreft mijn bedoelingen. In ieder geval naar mijn mening. :)


Terug naar the subject at hand? :)

[ Voor 5% gewijzigd door Verwijderd op 07-02-2010 19:41 ]


Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
DexterDee schreef op vrijdag 05 februari 2010 @ 17:36:
[...]

Aangezien PHP geen native ondersteuning heeft voor polymorphisme,
Is dat zo? Maar je kunt toch wel ergens een object van het type Gebruiker verwachten, en dan vervolgens een object van het type Klant of Admin aangeleverd krijgen? Volgens mij is dat ook polymorfisme. Omdat PHP weak-typed is verwacht je dan niet specifiek een object van het type Gebruiker, maar je software blijft wel werken.

Corrigeer me als ik ernaast zit, ik vind het hele OOP verhaal reuze interessant (ook in combinatie met PHP) maar ik heb bar weinig praktijkervaring.

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 12:57

DexterDee

I doubt, therefore I might be

mcdronkz schreef op zondag 07 februari 2010 @ 20:03:
[...]


Is dat zo? Maar je kunt toch wel ergens een object van het type Gebruiker verwachten, en dan vervolgens een object van het type Klant of Admin aangeleverd krijgen? Volgens mij is dat ook polymorfisme. Omdat PHP weak-typed is verwacht je dan niet specifiek een object van het type Gebruiker, maar je software blijft wel werken.

Corrigeer me als ik ernaast zit, ik vind het hele OOP verhaal reuze interessant (ook in combinatie met PHP) maar ik heb bar weinig praktijkervaring.
Inderdaad, dat is ook polymorphisme. Wat ik bedoelde was method overloading. Het hergebruiken van dezelfde method naam met andere parameters. Dat is helaas onmogelijk zonder magic methods te gebruiken.
Wat overigens niet werkt is een object naar een ander object casten. Dat vind ik wel een gemis.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Verwijderd

Topicstarter
Na een korte "vakantie" wil ik nu terug van start gaan met deze opdracht.

Echter heb ik een nieuwe twijfel..

Situatie (zoals ik denk dat het hoort):
Class:
admins(id = null)

Methods:
__construct() (Als id != null ophalen() anders nieuw()).
ophalen() (Voert een query uit en set de gegevens in dit object)
nieuw() (Controleert de $_POST gegevens en maakt als alles correct is een nieuw record in de database en set de gegevens in dit object)
wijzig() (Spreekt voor zich)

Static Methods:
getAdminById(id)
getAdminByName(name)
getAlleAdmins()
...
verwijderAdmin(id)

Vraag:
1. Zou ik nieuw nu best in Methods steken of in static methods?
2. Stel nu ik doe getAdminByName(John), dan gaat die met een query het adminId zoeken en vervolgens een object aanmaken, en dat object voert ook weer een query uit om de gegevens op te halen. Is dit niet inefficient? 2x een query uitvoeren terwijl het anders wel met eentje had gekunnen...

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 13:08

MueR

Admin Tweakers Discord

is niet lief

programInEenLanguageOderHetWordtEinMess ;) Ga alsjeblieft geen Engels en Nederlands mixen, zorg dat je gewoon in 1 taal programmeert, bij voorkeur Engels.

Anyone who gets in between me and my morning coffee should be insecure.


  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Verwijderd schreef op donderdag 11 februari 2010 @ 14:34:
1. Zou ik nieuw nu best in Methods steken of in static methods?
Ik zou het in een AdminDAO class steken (DAO = Data Access Object), en een instantie daarvan toekennen aan de objecten die toegang nodig hebben tot admins.
2. Stel nu ik doe getAdminByName(John), dan gaat die met een query het adminId zoeken en vervolgens een object aanmaken, en dat object voert ook weer een query uit om de gegevens op te halen. Is dit niet inefficient? 2x een query uitvoeren terwijl het anders wel met eentje had gekunnen...
Dat hoeft niet - je getAdminByName voert gewoon dezelfde query uit als de getAdminById, alleen gebruikt hij daarbij de naam van de admin als conditie. Met de uitbreiding daarbij dat deze methode meerdere admins terug kan geven, indien de 'name' van een admin niet uniek is. Dan kun je het ook beter getAdminsByName noemen (meervoud), en er rekening mee houden dat het een array van admin objecten teruggeeft.

Voor de rest lijk je snel te leren en op het goede spoor te zitten, *O*.

Verwijderd

Topicstarter
Was even vergeten dat Name inderdaad niet uniek is.
Heel erg bedankt voor de hulp nu kan ik weer verder!

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb intussen een groot deel van de class geprogrammeerd, dus bij deze vraag ik nog eens een laatste bevestiging dat ik juist bezig ben en eventueel opmerkingen naar verbeteringen toen.
(Het engels en nederlands mixen in mijn benamingen ben ik nu aan het oplossen dus let er aub niet op).
Is er trouwens ook nog een simpele elegantere manier om save() te laten weten of het om een nieuwe admin gaat of een bestaande te wijzigen (insert/update).

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<?php
require_once("Exceptions/AdminException.php");
require_once("Database.php");

 class Admin{
    //Admin gegevens
    private $adminId;
    private $gebruikersnaam;
    private $wachtwoord; //Enkel gebruikt bij aanmaken van nieuwe admins, of wijzigen van wachtwoord
    private $naam;
    private $voornaam;
    private $email;
    private $msn;
    private $tel;
    private $gsm;

    public function __construct($in = null, $alleenSetten = null){
        if(isset($alleenSetten) && is_array($in)) return $this->setter($in); //Alle gegevens zitten in de $in en dienen enkel geset te worden
        if(empty($alleenSetten) && is_array($in)) return $this->nieuw($in); //Maakt een nieuwe admin aan
        if(empty($alleenSetten) && is_int($in)) return $this->ophalen($in); //Gebruikt id om de admin op te halen
        if(empty($alleenSetten) && empty($in)) return $this->ophalen();     //Gebruik laatst uitgevoerde query
    }

    //STATIC METHODS
    public static function inloggen($gebruikersnaam, $wachtwoord){
        //Input controleren
        if(empty($gebruikersnaam))  throw(new AdminException('Admin::inloggen()', AdminException::ADMIN_GEBRUIKERSNAAM_NIET_INGEVULD));
        if(empty($wachtwoord))      throw(new AdminException('Admin::inloggen()', AdminException::ADMIN_WACHTWOORD_NIET_INGEVULD));

        //Controleer de gegevens
        $DB = DB::getDB();
        $query = "SELECT * From Admins WHERE Gebruikersnaam = '".$DB->escape($gebruikersnaam)."' AND Wachtwoord = '".md5($wachtwoord)."'";
        if(!$DB->rowExists($query)) throw(new AdminException('Admin::inloggen()', AdminException::ADMIN_GEBRUIKERSNAAM_EN_OF_WACHTWOORD_VERKEERD));

        //Inloggen, sessie setten
        $ingelogdeAdmin = new Admin();
        $_SESSION['adminId'] = $ingelogdeAdmin->adminId;
        return $ingelogdeAdmin;
    }
    public static function getAdminByGebruikersnaam($gebruikersnaam){
        $DB = DB::getDB();
        $query = "SELECT * FROM admins WHERE gebruikersnaam = '".$DB->escape($gebruikersnaam)."'";
        if($DB->rowExists($query)){
            $admin = new Admin();
            return $admin;
        }
        return False;
    }
    public static function getAlleAdmins(){
        $DB = DB::getDB();
        $query = "SELECT * FROM admins";
        $res = $DB->fetchRows($query);
        $admins = array(); //Houd alle objecten van admins bij
        foreach($res as $admin){
            $admins[$admin['adminId']] = new Admin($admin, True);
        }
        return $admins;
    }

    //METHODS
    private function nieuw($in){
        //Check Patterns
        $checkGebruikersnaam = "/^a-zA-Z0-9]+$/";
        $checkEmail = '/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])' .
                      '(([a-z0-9-])*([a-z0-9]))+' .
                      '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i';
                      
        //Vereiste velden ingevuld
        if(empty($in['gebruikersnaam']))                             throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GEBRUIKERSNAAM_NIET_INGEVULD));
        if(empty($in['wachtwoord']))                                 throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_WACHTWOORD_NIET_INGEVULD));
        if(empty($in['herhaalWachtwoord']))                          throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_HERHAAL_WACHTWOORD_NIET_INGEVULD));
        if(empty($in['naam']))                                       throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_NAAM_NIET_INGEVULD));
        if(empty($in['voornaam']))                                   throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_VOORNAAM_NIET_INGEVULD));

        //Maximale lengte
        if(strlen($in['gebruikersnaam']) > 15)                       throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GEBRUIKERSNAAM_MAX_15_KARAKTERS));
        if(strlen($in['wachtwoord']) > 25)                           throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_WACHTWOORD_MAX_25_KARAKTERS));
        if(strlen($in['naam']) > 25)                                 throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_NAAM_MAX_25_KARAKTERS));
        if(strlen($in['voornaam']) > 25)                             throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_VOORNAAM_MAX_25_KARAKTERS));
        if(strlen($in['email']) > 50)                                throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_EMAIL_MAX_50_KARAKTERS));
        if(strlen($in['msn']) > 50)                                  throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_MSN_MAX_50_KARAKTERS));
        if(strlen($in['tel']) > 20)                                  throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_TEL_MAX_20_KARAKTERS));
        if(strlen($in['gsm']) > 25)                                  throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GSM_MAX_25_KARAKTERS));

        //Minimale lengte
        if(strlen($in['gebruikersnaam']) < 5)                        throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GEBRUIKERSNAAM_MIN_5_KARAKTERS));
        if(strlen($in['wachtwoord']) < 5)                            throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_WACHTWOORD_MIN_5_KARAKTERS));
        if(strlen($in['naam']) < 3)                                  throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_NAAM_MIN_3_KARAKTERS));
        if(strlen($in['voornaam']) < 3)                              throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_VOORNAAM_MIN_3_KARAKTERS));

        //Correct herhaald & juiste vorm
        if($in['wachtwoord'] != $in['herhaalWachtwoord'])            throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_WACHTWOORD_INCORRECT_HERHAALD));
        //if(!preg_match($checkGebruikersnaam, $in['gebruikersnaam'])) throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GEBRUIKERSNAAM_NIET_TOEGELATEN_TEKENS));
        //if(!preg_match($checkEmail, $in['email']))                   throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_EMAIL_INCORRECTE_VORM));
        //if(!preg_match($checkEmail, $in['msn']))                     throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_MSN_INCORRECTE_VORM));

        //Controleren of de gebruikersnaam al in gebruik is
        $DB = DB::getDB();
        $query = "SELECT * FROM admins WHERE gebruikersnaam = '".$DB->escape($in['gebruikersnaam'])."'";
        if($DB->rowExists($query)) throw(new AdminException('Admin->nieuw()', AdminException::ADMIN_GEBRUIKERSNAAM_BESTAAT_AL));

        //adminId
        $in['adminId'] = $DB->insertID();

        //Admin gegevens setten
        $this->setter($in);

        //Aanmaken in de database
        $this->save("nieuw");
    }
    private function ophalen($id = null){
        $DB = DB::getDB();
        
        //Ophalen dmv laatst uitgevoerde query
        if(!empty($id)){
            $query = "SELECT * FROM admins WHERE adminId = '".$DB->escape($id)."'";
            if(!$DB->rowExists($query)){
                throw(new AdminException('Admin->ophalen()', AdminException::ADMIN_INVALID_ADMIN_ID));
            }
        }
        $res = $DB->fetchRow(); //Gebruikt de laatst uitgevoerde query

        //Admin gegevens setten
        $this->setter($res);
    }
    private function save($nieuw = null){
        $DB = DB::getDB();
        if(empty($nieuw)){
            $query = "UPDATE admins SET naam = '".$DB->escape($this->naam)."', voornaam = '".$DB->escape($this->voornaam)."'";
            if(isset($this->wachtwoord)) $query .= ", wachtwoord = '".md5($this->wachtwoord)."'";
            if(isset($this->email)) $query .= ", email = '".$DB->escape($this->email)."'";
            if(isset($this->msn)) $query .= ", msn = '".$DB->escape($this->msn)."'";
            if(isset($this->tel)) $query .= ", tel = '".$DB->escape($this->tel)."'";
            if(isset($this->gsm)) $query .= ", gsm = '".$DB->escape($this->gsm)."'";
            $query .= " WHERE adminId = '".$DB->escape($this->adminId)."'";
        }else{
            $query = "INSERT INTO admins (gebruikersnaam, wachtwoord, naam, voornaam";
            if(isset($this->email)) $query .= ", email";
            if(isset($this->msn)) $query .= ", msn";
            if(isset($this->tel)) $query .= ", tel";
            if(isset($this->gsm)) $query .= ", gsm";
            $query .= ") VALUES ('".$DB->escape($this->gebruikersnaam)."', '".md5($this->wachtwoord)."', '".$DB->escape($this->naam)."', '".$DB->escape($this->voornaam)."'";
            if(isset($this->email)) $query .= ", '".$DB->escape($this->email)."'";
            if(isset($this->msn)) $query .= ", '".$DB->escape($this->msn)."'";
            if(isset($this->tel)) $query .= ", '".$DB->escape($this->tel)."'";
            if(isset($this->gsm)) $query .= ", '".$DB->escape($this->gsm)."'";
            $query .= ")";
        }
        $DB->query($query);
    }

    //GETTERS & SETTERS
    public function getAdminId(){
        return $this->adminId;
    }
    public function getGebruikersnaam(){
        return $this->gebruikersnaam;
    }
    public function getNaam(){
        return $this->naam;
    }
    public function getVoornaam(){
        return $this->voornaam;
    }
    public function getEmail(){
        return $this->email;
    }
    public function getMsn(){
        return $this->msn;
    }
    public function getTel(){
        return $this->tel;
    }
    public function getGsm(){
        return $this->gsm;
    }
    
    private function setter($in){
        //Setten van de admin gegevens
        $this->adminId =            $in['adminId'];
        $this->gebruikersnaam =     $in['gebruikersnaam'];
        $this->wachtwoord =         $in['wachtwoord'];
        $this->naam =               $in['naam'];
        $this->voornaam =           $in['voornaam'];

        //Setten van optionele admin gegevens
        if(isset($in['email'])) $this->email = $in['email'];
        if(isset($in['msn'])) $this->msn = $in['msn'];
        if(isset($in['tel'])) $this->tel = $in['tel'];
        if(isset($in['gsm'])) $this->gsm = $in['gsm'];
    }
 }
?>

[ Voor 7% gewijzigd door Verwijderd op 13-02-2010 16:02 ]

Pagina: 1