Door
Ozzie PHP
op 11-02-2019 17:08
gewijzigd op 11-02-2019 17:12
3.997 views
Stel ik heb een User class en ik wil die laten samenwerken met een UserModel, wat is dan de beste manier om dat UserModel als property in de User class te krijgen?
Zelf dacht ik aan zoiets als dit:
<?php
$id = $_SESSION['userid'];
$model = new UserModel($db_conn);
$user = new User($id, $model);
?>
Is het bovenstaande een gebruikelijke manier? Ik zie namelijk ook wel eens dit:
<?php
$id = $_SESSION['userid'];
$model = new UserModel($db_conn);
$user = new User($id);
$user->loadModel($model);
?>
Weet iemand dit toevallig?
En nog een laatste vraag ... "mag" je het ID ook meegeven aan het UserModel in plaats van aan de User class?
<?php
$model = new UserModel($id, $db_conn);
?>
Of is dat niet gebruikelijk?
Ik vraag dat omdat als ik het ID mee zou geven aan het UserModel, ik in de constructor van het model meteen alle gegevens zou kunnen ophalen uit de database en die als property zou kunnen opslaan. Als ik het ID meegeef aan de User class zelf (zoals nu het geval is) dan moet de User class het ID eerst doorgeven aan het UserModel en moet er vanuit de User class een functie in het UserModel worden aangeroepen die de data ophaalt.
Ja, oké ... maar daarmee heb ik nog geen antwoord op mijn vraag :-)
Heb het inmiddels al min of meer opgelost volgens een eigen interpretatie, maar ik dacht dat er wellicht wat richtlijnen waren die ik kon volgen.
Een User is gewoon een User class, een representatie van een User.
Het model is het model dat bepaalt hoe de data wordt opgehaald.
Dus User is een Controller.. Die kan nooit extenden op een model.
Bij het model geef je bijna het juiste antwoord.
Die kan inderdaad uit de achterliggende lagen wat halen.
Extenden op een database is niet goed. Want een model zou niet moeten weten of het een database is of XML of andere data.
Dus class UserModel extends Model, En Model regelt de rest WAT er moet gebeuren en waat het vandaan kan komen. Moeilijk is het niet, alleen een beetje overnadenken.
Vergeet ook niet OOP is een ding om het jezelf makkelijker te maken en overzichtelijk.
Als iets makkelijker is om het anders te doen en het werkt en is overzichtelijk, veilig, en logisch dan is dat ook goed he.
>> Dus User is een Controller.. Die kan nooit extenden op een model.
Precies! Dat is wat ik al zei. Gelukkig had ik het dus bij het rechte eind.
>> Extenden op een database is niet goed. Want een model zou niet moeten weten of het een database is of XML of andere data.
Dit vind ik wel interessant. Ik laat het model niet extenden op een database (immers, een model IS geen database). In plaats daarvan geef ik de database mee aan het model via de constructor.
Nu zeg jij "Want een model zou niet moeten weten of het een database is of XML of andere data."
Dat vind ik wel even een lastige, want in mijn UserModel moet ik data ophalen uit de database en dus moet ik in het UserModel queries uitvoeren. Het model weet dus dat het een (in dit geval MySQLi) database meekrijgt. Ik zou niet weten hoe je dat (handig) op een andere manier zou moeten oplossen eigenlijk.
>> Als iets makkelijker is om het anders te doen en het werkt en is overzichtelijk, veilig, en logisch dan is dat ook goed he.
Dat is zeker waar. Ik zie vaak gruwelijk ingewikkelde constructies, en daar ben ik JUIST niet naar op zoek. Ik zoek simpele methodes die makkelijk te interpreteren zijn, maar waarmee ik wel het idee / het nut van OOP (alles centraal en makkelijk uit te breiden) in stand houd.
... want in mijn UserModel moet ik data ophalen uit de database en dus moet ik in het UserModel queries uitvoeren. Het model weet dus dat het een (in dit geval MySQLi) database meekrijgt.
Dan zou je dus met een DI container kunnen gaan werken. Dan geef je gewoon de hele container mee, en het model ziet maar uit welk potje ie z'n data haalt. Wordt het allemaal wel een beetje "losjes" gekoppeld van.
>> Dan geef je gewoon de hele container mee, en het model ziet maar uit welk potje ie z'n data haalt.
Ik snap het nog steeds niet. Er moeten queries zijn die data uit de database ophalen. Die queries moet ik toch in het model plaatsen? Waar zou ik ze anders dan moeten plaatsen?
In die container zit (oa) een instantie van je database. Als het model wat je op dat moment gebruikt queries uit moet voeren pakt het dus de database uit de container. Moet de data ergens anders vandaan komen, dan pakt ie whatever nodig is om dat te doen.
Bart v B zei hierboven: "Want een model zou niet moeten weten of het een database is of XML of andere data.".
Hoe je vanuit het model een database aanspreekt snap ik. Wat ik bedoelde is ... om gegevens uit de database te kunnen halen moeten er queries worden uitgevoerd. Die queries moeten toch in het model staan? Anders gezegd, het model weet dan toch dat het data ophaalt uit een database?
<?php
$id = $_SESSION['userid'];
$model = new UserModel($db_conn);
$user = new User($id, $model);
?>
Waarom gebruik je geen data mapper? Dan krijg je zoiets, dat lijkt op het bovenstaande:
<?php
$user_mapper = new UserMapper($storage);
$user = $user_mapper->getUserById($_SESSION['user_id']);
?>
In dit geval is User wél een model, maar een model dat niet hoeft te weten waar en hoe de data worden opgeslagen: dat is de verantwoordelijkheid van de UserMapper.
Een data mapper is vooral handig als je samenhangende data in één keer wilt opvragen of opslaan. Dat is vooral het geval wanneer een object grotendeels overeenkomt met één rij in één databasetabel.
Het hangt er dus vooral van af hoe complex je UserModel is. Bestaat het model vooral uit getters en setters die overeenkomen met kolommen in dezelfde tabel (bijvoorbeeld `email` in een tabel `users`), dan is een data mapper een efficiënte en effectieve oplossing.
Om het voorbeeld verkort uit te breiden met een e-mailadres: