[OOP] Login systeem
ik ga het nog eens overlopen want ik ben weer even de weg kwijt. Ik heb volgende classes:
- User is gewoon het object User.
- UserMapper is de datalaag?
- PDODatabaseStorage is de databaselaag?
Als ik dus nu een user in de database wil steken krijgen we denk ik:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
// User Object aanmaken
$user = new User('Jasper');
$user->setEmail('[email protected]');
$user->setPassword();
// Steek in de database
$pdo = new PDO(...);
$pdoStorage = new PDODatabaseStorage($pdo);
$userMapper = new UserMapper($pdoStorage);
$userMapper->create($user);
?>
// User Object aanmaken
$user = new User('Jasper');
$user->setEmail('[email protected]');
$user->setPassword();
// Steek in de database
$pdo = new PDO(...);
$pdoStorage = new PDODatabaseStorage($pdo);
$userMapper = new UserMapper($pdoStorage);
$userMapper->create($user);
?>
dat klopt al hé?
Ja, wat je nu hebt is goed. Het User object is een Entity, een object dat gegevens vasthoudt en meer eigenlijk niet. De DatabaseStorage is de abstracte database layer, de laag over de database waardoor de database flexibel wordt. De UserMapper is een DataMapper, het object dat tussen de databaselaag en de User entity inzit.
Hoe koppel ik mijn UserMapper aan mijn PDODatabaseStorage? Ik snap dat we de storage meegeven aan de UserMapper en dat we daar dan bijvoorbeeld de create functie op kunnen aanroepen. Maar volgens de StorageInterface moet create een storableInterface object binnenkrijgen, mijn functie krijgt een array binnen waardoor ik foutmeldingen kweek.
En hoe zit het met functie's zoals getById of getByEmailAndPass? Is dat allemaal via de read function?
In het geval van een sessie wil je niet alles opslaan, dan kun je nog een 3e parameter toevoegen waarin je in een array zet welke velden je wilt opslaan.
Dit gaat wel erg gecompliceerd worden, dus ben je opzoek naar een uitdaging dan kun je hieraan beginnen, ik zal je wel her en der een duwtje in de rug geven. Maar eigenlijk raad ik je aan dan te gaan werken met een Object Relation Mapper, ORM, zoals Doctrine2. Dat is één van de meestgebruikte libraries voor het geen we hier nu aan het doen zijn.
De getById en getByEmailAndPass zijn gewoon aparte functies in de mapper en die gaan inderdaad via de read functie.
Gewijzigd op 12/11/2012 11:03:24 door Wouter J
Dat was eigenlijk net het gene dat ik niet wou doen, ik wou zoveel mogelijk code zelf schrijven omdat ik daar meer van leer. Indien ik het ORM gewoon moet zien als een pattern dan is dit oke voor mij. Ik zal eens wat googlen op die term en zien waar ik kom.
Bedankt!
Of ORM een pattern is weet ik niet, ik denk het niet. Meer een systeem.
Maar oke, ik zal mij gaan verdiepen in het ORM.
Dat kan wel, maar het gaat je heel veel, naar mijn mening, onnodig tijd kosten. Maar je kan eens gaan kijken of je je eigne ORM'tje kan maken.
deze dia reeks staat bij de lijst van ORM's o.a. PDO. Klopt het dat PDO ook een ORM is? Verder zie ik daar ORM's staan van verschillende frameworks zoals kohana en Zend. Ik veronderstel dat ze allemaal ongeveer hetzelfde werken en dat de keuze dus niet erg veel uitmaakt?
Wouter, in Ik raad je aan Doctrine te gebruiken, dat is een losstaande applicatie met enorm veel mogelijkheden, misschien wel te uitgebreid. Mocht je hem te uitgebreid vinden dan kun je misschien beter naar Propel kijken of inderdaad een van de frameworks.
Mocht je willen gaan werken met Doctrine of Propel dan raad ik je aan de Symfony2 documentatie te lezen. Ik weet het, het klinkt vreemd, maar het is een hele goede documentatie om je kennis te laten maken met Doctrine of Propel en heel erg veel heeft niks met Symfony2 te maken: Doctrine (generate:* commands zijn SF specifiek en je moet doctrine op een andere manier verkijgen dan $this->getDoctrine()) en propel.
deze tutorial aan het volgen. Die doet ook ongeveer wat ik wil doen maar wel zonder ORM.
Als ik het goed begrijp kan ik het zo stellen:
model = domain object + datamapper
UserModel = User + UserMapper
Als ik dan in de UserMapper de storage ophaal en daar dan de functie op toepas dan kan ik vanuit de UserMapper de verschillende storage mogelijkheden ophalen toch?
Wat ik dus wil doen is de UserMapper als laag tussen de domain objects en de Storage maken.
Dus dan krijgt elke create function het object binnen dat moet opgeslagen worden. Het enige waar ik nog geen oplossing op weet is hoe ik het zo dynamisch mogelijk kan houden. Stel nu dat ik eerst alleen een property name in mijn User object hebt en ik wil dat nadien opsplitsen in name en lastName dan moet ik elke storage klasse aanpassen en dat is wat we niet willen doen hé?
Ben ik op deze manier al een stapje verder op de denkpiste of sta ik nog altijd op de zelfde plek en snap ik dus nog niet waarom er een ORM nodig is.
Wat is de taak van de mapper en wat is de taak van de ORM? Klopt mijn interpretatie of doen die twee zaken toch iets anders dan ik denk dat ze doen.
ik ben nu ook nog Als ik het goed begrijp kan ik het zo stellen:
model = domain object + datamapper
UserModel = User + UserMapper
Als ik dan in de UserMapper de storage ophaal en daar dan de functie op toepas dan kan ik vanuit de UserMapper de verschillende storage mogelijkheden ophalen toch?
Code (php)
Wat ik dus wil doen is de UserMapper als laag tussen de domain objects en de Storage maken.
Dus dan krijgt elke create function het object binnen dat moet opgeslagen worden. Het enige waar ik nog geen oplossing op weet is hoe ik het zo dynamisch mogelijk kan houden. Stel nu dat ik eerst alleen een property name in mijn User object hebt en ik wil dat nadien opsplitsen in name en lastName dan moet ik elke storage klasse aanpassen en dat is wat we niet willen doen hé?
Ben ik op deze manier al een stapje verder op de denkpiste of sta ik nog altijd op de zelfde plek en snap ik dus nog niet waarom er een ORM nodig is.
Wat is de taak van de mapper en wat is de taak van de ORM? Klopt mijn interpretatie of doen die twee zaken toch iets anders dan ik denk dat ze doen.
er is weer een heleboel veranderd. De UserMapper krijgt het object User binnen, die maakt er een array van en stuurt het door naar de storage die de UserMapper ook binnenkrijgt.
Mijn PDOStorage krijgt dus een array binnen bij oa de methode create(), ik heb dit in de praktijk zo uitgewerkt. Is dat efficiënt?
Code (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
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
<?php
public function create($object, array $fields)
{
$fieldNames = implode(', ',array_keys($fields));
$prepare = '';
foreach ($fields as $key => $value)
{
$prepare .= ':'.$key .', ';
// make an array for the prepared statements
$prepared[':'.$key] = $value;
}
$prepare = substr($prepare, 0, -2);
try
{
$qry = $this->db->prepare("INSERT INTO ".$object." (" . $fieldNames . ") VALUES (".$prepare.") ");
//echo '<pre>' . print_r($fieldNames) . '</pre>';
//echo $object;
$qry->execute($prepared);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
?>
public function create($object, array $fields)
{
$fieldNames = implode(', ',array_keys($fields));
$prepare = '';
foreach ($fields as $key => $value)
{
$prepare .= ':'.$key .', ';
// make an array for the prepared statements
$prepared[':'.$key] = $value;
}
$prepare = substr($prepare, 0, -2);
try
{
$qry = $this->db->prepare("INSERT INTO ".$object." (" . $fieldNames . ") VALUES (".$prepare.") ");
//echo '<pre>' . print_r($fieldNames) . '</pre>';
//echo $object;
$qry->execute($prepared);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
?>
Nu wil ik beginnen aan PDOStorage->update() Vinden jullie dat die ook alleen een array met de user gegevens moet binnen krijgen of ook een array criterium. Ik krijg het praktisch niet goed uitgewerkt.
Ik zou ook nog even $prepared = array(); neerzetten rond regel 5, maar voor de rest klopt het wel (behalve die comments dan, die kunnen nooit werken). En die exception vang je ook wel mooi op, maar je zou hem ook verder kunnen laten opborrelen.
bedankt voor je reactie. Wat bedoel je juist met het verder laten opborrelen van de exception?
Ik heb de functies (find - create - update) nu allemaal afzonderlijk getest en ze blijken te werken. Vind je dat het goed in een zit? Heb je nog extra tips? Het "ORM" mapje is nu niet meer nodig zeker?
Code staat op git https://github.com/JasperDS/login_system/tree/master/lib/Jds
Jasper
Quote:
Wat bedoel je juist met het verder laten opborrelen van de exception?
Nou, in dit geval handel je hem meteen in je klasse op. Je kan er ook voor kiezen hem pas later op te vangen. Lees anders eens dit topic: http://www.phphulp.nl/php/forum/topic/waar-en-wanneer-exceptions-afhandelen/85753/
mijn createfunctie in de userMapper ziet er nu zo uit:
Code (php)
Zoals je ziet geef ik geen id mee omdat de db dit zelf doet met Auto Increment.
MAAR mijn sessionStorage die moet wel een id binnen krijgen. Moet ik het id dan toch doorgeven in mijn mapper en het er terug uitgooien in mijn PDOStorage of is er een andere optie?
In dat topic over de exceptions zie ik veel over de "Application-class" / controller. Ontbreekt deze niet in mijn "systeempje". Moet ik die controller zien zoals een controller bij het MVC pattern en heb ik nu slechts mijn model gemaakt?
Jij zou dus elke functie uit de Usermapper / Storage klassen een User / object laten returnen of zie ik dat verkeerd?
Wat is het voordeel dat de create functie de User terug geeft en is het wel zijn taak om dat te doen?
Bedankt voor het lezen!
Jasper
Gewijzigd op 05/12/2012 22:09:05 door Niels K