Hoe een userId ophalen?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Tom Swinkels

Tom Swinkels

17/12/2012 09:54:14
Quote Anchor link
Beste,

Ik weet niet zo goed hoe ik mijn probleem nu moet aangeven, toch ga ik het proberen uit te leggen.

Bij een transactie heb ik ook het UserId nodig om bij te houden van welke user die transactie nu is.

Wanneer ik een transactie opsla, geef ik aan de create methode van de transactionMapper het transaction object en het user object mee, heel duidelijk dus.

Maar wanneer ik nu een select heb moet je dan (zoals ik het nu doe) gewoon in de tansaction object een userId meegeven? Of moet ik bij select ook ergens een User object aanmaken met daarbij het id, en dat dan terug geven? Hoe doe ik dit dan?

Hopelijk snappen jullie het probleem en kunnen jullie mij vertellen wat nu de goede oplossing hiervoor is.
 
PHP hulp

PHP hulp

21/11/2024 20:58:42
 
Moose -

Moose -

17/12/2012 10:28:15
Quote Anchor link
Tuurlijk snappen we dit probleem niet. Welk script gebruik je? Een transactie wordt toch uitgevoerd door een User, dus hoe is het dan mogelijk om die niet te hebben?
 
Tom Swinkels

Tom Swinkels

17/12/2012 11:02:11
Quote Anchor link
Welk script gebruik ik? Rare vraag, ik programmeer alles zelf.

Klopt, dat is ook geen probleem.

Maar stel dat ik als administrator alle transacties op wil halen, moet ik toch weten van welke user het is.

TransactionMapper -> create

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public function create( Transaction $transaction, User $user )
    {
        $sql = "INSERT INTO
                           transaction
                SET
                           user_id = :userId,
                           description = :description,
                           credit = :credit,
                           date_add = NOW()
               ";
        $result = $this->_db->prepare( $sql );

        $data = array( 'userId'         => $user->getId(),
                       'description'    => $transaction->getDescription(),
                       'credit'         => $transaction->getCredit() );

        $result->execute( $data );

        $transaction->setId( $this->_db->lastInsertId() );

        return $transaction;
    }


Zoals het nu is

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
    protected function populateTransaction( $arrayData )
    {
        $transaction = new Transaction();
        $transaction->setId( $arrayData['id'] );
        $transaction->setUserId( $arrayData['user_id'] );
        $transaction->setDescription( $arrayData['description'] );
        $transaction->setCredit( $arrayData['credit'] );
        $transaction->setDateAdd( $arrayData['date'] );
        return $transaction;
    }


Ik dacht zelf dat het beter op een andere manier kan, zo iets zoals:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
    protected function populateTransaction( $arrayData )
    {
        $user = new User();
        $user->setId( $arrayData['user_id'] );
        
        
        $transaction = new Transaction();
        $transaction->setId( $arrayData['id'] );
        $transaction->setDescription( $arrayData['description'] );
        $transaction->setCredit( $arrayData['credit'] );
        $transaction->setDateAdd( $arrayData['date'] );
        return $transaction;
    }


Alleen ik kan natuurlijk niet twee objecten returnen, dit kan vast op een andere manier alleen weet ik zo niet welke.
 
Kris Peeters

Kris Peeters

17/12/2012 11:33:40
Quote Anchor link
Kan je toen op welke manier je create() aanspreekt? (Dus, wat gebeurt buiten de class)

Misschien toch ook even vermelden met welke classes je bezig bent.


Die return $transaction in het eerste stuk code, zal in principe niet nodig zijn.
Objecten worden by ref doorgegeven. Maar daarover meer als ik meer weet...
Gewijzigd op 17/12/2012 11:34:45 door Kris Peeters
 
Moose -

Moose -

17/12/2012 11:34:25
Quote Anchor link
Je kan een array returnen.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
return array($transaction, $user)


En dat haal je dan zo op:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
list($transatie, $user) = populateTransaction($data)


Zie ook: http://php.net/manual/en/function.list.php
 
Tom Swinkels

Tom Swinkels

17/12/2012 11:42:26
Quote Anchor link
@kris, van jou reactie snap ik helemaal niets.

@not, dat zou kunnen, maar is dat ook de manier zoals ze het in het oo doen?
 
Henk Verhoeven

Henk Verhoeven

17/12/2012 11:45:42
Quote Anchor link
Tom,

Je kunt ook de Transaction een referentie naar de user meegeven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected function populateTransaction( $arrayData )
    {
        $user = new User();
        $user->setId( $arrayData['user_id'] );
        
        
        $transaction = new Transaction();
        $transaction->setId( $arrayData['id'] );
        $transaction->setDescription( $arrayData['description'] );
        $transaction->setCredit( $arrayData['credit'] );
        $transaction->setDateAdd( $arrayData['date'] );
        $transaction->setUser($user);
        return $transaction;
    }


Je hebt dan natuurlijk wel een method getUser nodig op Transaction.

Het opvragen van het ene object aan het andere heet trouwens 'navigatie'. M.a.w. de volgende code 'navieert' van een transactie naar de bijbehorende user:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$user = $transaction->getUser();


Je kunt ook de functie "zoals het nu is" gebruiken met:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd;

    function getUser() {
        $user = new User();
        $user->setId( $this->getUserId() );
        return $user;
    }

(..)


Nadeel is dat er steeds een nieuwe user wordt gemaakt als getUser wordt aangeroepen. Het kan efficienter:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd, $user;

    function getUser() {
        if (!$this->user) {
            $this->user = new User();
            $this->user->setId( $this->getUserId() );
        }
        return $this->user;
    }

(..)

Dit is een vorm van caching.

En als de user nog meer gegevens heeft en als die ook in de database staan:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd, $user;

    function getUser() {
        if (!$this->user) {
                $this->user = User::retrieve($this->getUserId());
        }
        return $this->user;
    }

(..)
}

class User {

    static function retrieve($userId) {
        $user = new User();
        //voeg hier een dabase query in die de user data in $arrayData zet
            
        $user->populate($arrayData);
        return $user;
    }

(..)
Gewijzigd op 17/12/2012 11:52:25 door Henk Verhoeven
 
Kris Peeters

Kris Peeters

17/12/2012 11:48:17
Quote Anchor link
Toon eens wat er buiten de class gebeurt.

Iets als

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
$mijn_transaction
= new Transaction();
$mijn_user = new User();

$mijn_object = new Mijn_class()  // geen idee waar die class over gaat
$mijn_object->create( $mijn_transaction , $mijn_user );
// en hier verwacht je dus die id te kennen.
?>
 
Moose -

Moose -

17/12/2012 11:54:40
Quote Anchor link
Henk Verhoeven op 17/12/2012 11:45:42:
Tom,

Je kunt ook de Transaction een referentie naar de user meegeven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected function populateTransaction( $arrayData )
    {
        $user = new User();
        $user->setId( $arrayData['user_id'] );
        
        
        $transaction = new Transaction();
        $transaction->setId( $arrayData['id'] );
        $transaction->setDescription( $arrayData['description'] );
        $transaction->setCredit( $arrayData['credit'] );
        $transaction->setDateAdd( $arrayData['date'] );
        $transaction->setUser($user);
        return $transaction;
    }


Je hebt dan natuurlijk wel een method getUser nodig op Transaction.

Het opvragen van het ene object aan het andere heet trouwens 'navigatie'. M.a.w. de volgende code 'navieert' van een transactie naar de bijbehorende user:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$user = $transaction->getUser();


Je kunt ook de functie "zoals het nu is" gebruiken met:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd;

    function getUser() {
          $user = new User();
        $user->setId( $this->getUserId() );
        return $user;
    }

(..)


Nadeel is dat er steeds een nieuwe user wordt gemaakt als getUser wordt aangeroepen. Het kan efficienter:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd, $user;

    function getUser() {
        if (!$this->user) {
            $this->user = new User();
            $this->user->setId( $this->getUserId() );
        }
        return $this->user;
    }

(..)

Dit is een vorm van caching.

En als de user nog meer gegevens heeft en als die ook in de database staan:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
class Transaction {

    var $id, $userId, $description, $credit, $dateAdd, $user;

    function getUser() {
        if (!$this->user) {
                $this->user = User::retrieve($this->getUserId());
        }
        return $this->user;
    }

(..)
}

class User {

    static function retrieve($userId) {
        $user = new User();
        //voeg hier een dabase query in die de user data in $arrayData zet
            
        $user->populate($arrayData);
        return $user;
    }

(..)



Is het niet handiger om helemaal geen User object te maken binnen je Transactions class? Lijkt mij logischer om alleen maar een getter ervoor te maken (desnoods User final maken, zodat hij alleen maar via de constructor meegegeven kan worden). Dus dan heb je iets van

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$transaction = new Transaction($user)


Je kan toch nooit een transaction aanmaken zonder user (lijkt mij)
 
Tom Swinkels

Tom Swinkels

17/12/2012 12:08:59
Quote Anchor link
@henk, je geeft me nu zoveel opties dat ik zelf nu niet meer uit de beste optie kom. Ik heb enkel het ID nodig, verder kan ik via $emailMapper->getEmailByUserId( $user->getId() ); het email adres opvragen.

@not, dat klopt, maar daarom stuur ik het user object ook mee naar create, maar bij een select is het niet altijd zo.
 
Moose -

Moose -

17/12/2012 12:10:14
Quote Anchor link
Hoe selecteer je dan precies? Is dat niet via $user->getTransactions() ?
 
Tom Swinkels

Tom Swinkels

17/12/2012 12:21:06
Quote Anchor link
Het gaat er nu nog even om welke manier je zou gebruiken voor het UserId? De eerste manier, door setUser() methode aan te maken spreekt mij het meeste aan.
 
Moose -

Moose -

17/12/2012 12:41:15
Quote Anchor link
Kun je hier eens antwoord op geven:

Kris Peeters op 17/12/2012 11:48:17:
Toon eens wat er buiten de class gebeurt.

Iets als

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
$mijn_transaction
= new Transaction();
$mijn_user = new User();

$mijn_object = new Mijn_class()  // geen idee waar die class over gaat
$mijn_object->create( $mijn_transaction , $mijn_user );
// en hier verwacht je dus die id te kennen.
?>


Ik begrijp niet echt wat je nu precies wilt
 
Tom Swinkels

Tom Swinkels

17/12/2012 13:29:42
Quote Anchor link
Natuurlijk kan ik dat :)

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
                            $transactionMapper = new TransactionMapper( $db );
                            $transaction = new Transaction();
                            $transaction->setCredit( '-1' );
                            $transaction->setDescription( 'SMS verstuurd' );
                            $transactionMapper->create( $transaction, $user );


User is het user object die heeft ook het id.
 
Moose -

Moose -

17/12/2012 13:41:07
Quote Anchor link
Ja dat ziet er goed uit toch? Wat is dan het probleem? Wat is je relatie tussen User en Transaction?

Edit: ah sorry je vraag staat bovenin ergens. Ik ben ook wel benieuwd hoe je dit leuk kan oplossen
Gewijzigd op 17/12/2012 13:46:56 door Moose -
 
Henk Verhoeven

Henk Verhoeven

17/12/2012 19:38:49
Quote Anchor link
Sorry voor al die opties. Die TransactionMapper doet object-relational mapping?

En als ik het goed begrijp is de vraag hoe je de relaties implementeert:
1. Hij mapt de foreign key en doet verder niets. Dit lijkt me "zoals het nu is".
2. Hij doet "ijverige instantiatie" (eager instantiation) van de gereleateerde objecten. Dit is zoals ik beschrijf bij "de Transaction een referentie naar de user meegeven".
3. Het object doet "luie instatiatie" (lazy instatiation) van het gerelateerde object. Dit is het geval in alle overige opties die ik beschreef.

Manier 1 heeft tot gevolg dat de code die iets met de objecten doet zelf aan de slag moet met de relatie.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
                            $transactionMapper = new TransactionMapper( $db );
                            $transaction = new Transaction();
                            $transaction->setCredit( '-1' );
                            $transaction->setDescription( 'SMS verstuurd' );
                            $transaction->setUserId($user->getId());
                            $transactionMapper->create( $transaction );

Als je $user->getId() op diverse plaatsen moet schrijven is dat natuurlijk niet optimaal ("Don't repeat yourself").

Manier 2 heeft tot gevolg dat je, als je een Transaction object maakt die gerelateerd is aan een user, je ook altijd een User object moet maken. Als je die toch altijd nodig gaat hebben is dat de meest efficiente optie.

Heb je het gerelateerde object soms wel en soms niet nodig dan is is manier 3 de beste keus.

Zowel bij manier 2 als manier 3 krijg je:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
                            $transactionMapper = new TransactionMapper( $db );
                            $transaction = new Transaction();
                            $transaction->setCredit( '-1' );
                            $transaction->setDescription( 'SMS verstuurd' );
                            $transaction->setUser($user);
                            $transactionMapper->create( $transaction );

Bij manier 2 slaat de transaction een referentie naar de User op en moet de TransactionMappers create functie de user opvragen, dan de id van de user opvragen en die in de $data array stoppen. Bij manier 3 doet de functie setUser van de Transaction dat en zet hem in userId:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
    function setUser($user) {
        $this->userId = $user ? $user->getId() : null;
    }

De TransactionMappers create functie hoeft dan alleen maar de gegevens uit de Transacion in de $data array stoppen en hoeft verder niet te weten hoe het zit met de relatie met de user.

En wat betreft die verschillende opties die ik beschreef voor manier 3: als je geen duidelijk voordeel ziet dan doe je toch gewoon "The simpelest thing that could possibly work"?
Gewijzigd op 17/12/2012 19:54:41 door Henk Verhoeven
 
Tom Swinkels

Tom Swinkels

17/12/2012 22:58:50
Quote Anchor link
@henk, bedankt voor je antwoord.

Ik had dit topic vooral aangemaakt voor bij het ophalen van de transacties, ik zie dat jij nu ook al aan setUser het user object meegeeft, bij het create van een transactie. Is dit ook de meest voorkomende manier?
 
Henk Verhoeven

Henk Verhoeven

18/12/2012 11:35:02
Quote Anchor link
Als je met getters en setters werkt is volgens mij de meest voorkomende manier om ook de relatie tussen twee objecten te regelen met setters en getters die die het gerelateerde object als argument resp return value hebben. In dit geval setUser($user) en getUser(). En als je die setter en getter toch al hebt, waarom zou je dan nog de user als parameter aan create meegeven?

Maar er is ook een hele andere stijl, ActiveRecord. Ik heb daar in Kohana een voorbeeld van gezien waarbij er met __set en __get werdt gewerkt. ActiveRecord is geloof ik vrij populair met PHP. Daardoor weet ik niet wat nu in algemene zin de meest voorkomende manier is.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.