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.

Wat is "gebruikelijk"?
Ja klopt, ik herhaal inderdaad mezelf, maar ik weet niet hoe ik het anders moet doen eigenlijk.

Als ik een class weggooi, gaat het mis als ik wil wisselen van de manier waarop ik m'n data ophaal.

Stel, overal in je applicatie gebruik ik bijv. $user->getName();

Maar ... gebruikers kunnen zijn opgeslagen in de interne database, of ze komen van (ik noem maar wat) Facebook. Dan moet in het ene geval de naam uit de database worden opgehaald, en in het andere geval via een API van Facebook. Ik het dus 2 aparte modellen nodig ... denk ik :-s

Als je een goede methode weet om dit op te lossen dan hoor ik dat heel graag.
Dat kan met een data mapper. ;-)

Behandel de User die je nu hebt als het model, met getters en setters voor de eigenschappen, maar delegeer het opslaan en weer opvragen van het model naar een andere klasse, bijvoorbeeld de UserMapper.
Poeh ... ik volg 'm effe niet meer Ward ;-)

Kun je misschien een heeeeeeel simplistisch voorbeeld geven van hoe jij het dan bedoelt? Bijv. aan de hand van de method getUsername()? Dat zou heel fijn zijn. Als ik het principe doorheb, kan ik daar op voortborduren :-)
Zonder handen, zonder foutafhandeling, enzovoort:


<?php
class UserMapper()
{
    protected $Database;

    public function __construct(\PDO $database)
    {
        $this->Database = $database;
    }

    public function fetchUserById($user_id)
    {
        $stmt = $this->Database->prepare('SELECT * FROM users WHERE user_id = :user_id');
        $stmt->bindValue(':user_id', $user_id, \PDO::PARAM_INT);
        $stmt->execute();
        $result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        $user_data = $result[0];
        $user = new User();
        $user->setUsername($user_data['username']);
        return $user;
    }
}

class User
{
    protected $Username;

    public function getUsername()
    {
        return $this->Username;
    }

    public function setUsername($username)
    {
        $this->Username = $username;
    }
}

// Gebruik:
$db = new PDO('mysql:dbname=test;host=localhost', 'root', '');
$user_mapper = new UserMapper($db);
$user = $user_mapper->fetchUserById($_SESSION['user_id']);
echo $user->getUsername();
?>
Ah, kijk eens aan. een stuk helderder. Thanks Ward!

Alleen eens over nadenken hoe je dat in de praktijk toepast, want je hebt in jouw opzet dus altijd 2 objecten, de User en de Mapper. Stel ik laad/fetch de User in "het begin" van de applicatie en wil deze verderop in de applicatie opslaan, dan moet ik dus ook die $user_mapper bij de hand hebben ... of een nieuw object initialiseren. Hmmm, iets om over na te denken ...
Klopt, je zult soms iets met de state van een object moeten doen voor dit soort situaties:

1. App A vraagt user X op.
2. App B vraagt user X op.
3. App A wijzigt user X.

Wat gebeurt er nu met user X in app B?
Geen idee? Is het een raadsel? :-D

Reageren