Hoe een userId ophalen?
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.
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?
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}
{
$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)
1
2
3
4
5
6
7
8
9
10
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;
}
{
$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)
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
{
$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.
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
@not, dat zou kunnen, maar is dat ook de manier zoals ze het in het oo doen?
Je kunt ook de Transaction een referentie naar de user meegeven:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
{
$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:
Je kunt ook de functie "zoals het nu is" gebruiken met:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
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;
}
(..)
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
(..)
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)
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
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;
}
(..)
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
Iets als
Henk Verhoeven op 17/12/2012 11:45:42:
Tom,
Je kunt ook de Transaction een referentie naar de user meegeven:
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:
Je kunt ook de functie "zoals het nu is" gebruiken met:
Nadeel is dat er steeds een nieuwe user wordt gemaakt als getUser wordt aangeroepen. Het kan efficienter:
Dit is een vorm van caching.
En als de user nog meer gegevens heeft en als die ook in de database staan:
Je kunt ook de Transaction een referentie naar de user meegeven:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
{
$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:
Je kunt ook de functie "zoals het nu is" gebruiken met:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
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;
}
(..)
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
(..)
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)
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
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;
}
(..)
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
Je kan toch nooit een transaction aanmaken zonder user (lijkt mij)
@not, dat klopt, maar daarom stuur ik het user object ook mee naar create, maar bij een select is het niet altijd zo.
Hoe selecteer je dan precies? Is dat niet via $user->getTransactions() ?
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.
Kris Peeters op 17/12/2012 11:48:17:
Toon eens wat er buiten de class gebeurt.
Iets als
Iets als
Ik begrijp niet echt wat je nu precies wilt
Code (php)
1
2
3
4
5
2
3
4
5
$transactionMapper = new TransactionMapper( $db );
$transaction = new Transaction();
$transaction->setCredit( '-1' );
$transaction->setDescription( 'SMS verstuurd' );
$transactionMapper->create( $transaction, $user );
$transaction = new Transaction();
$transaction->setCredit( '-1' );
$transaction->setDescription( 'SMS verstuurd' );
$transactionMapper->create( $transaction, $user );
User is het user object die heeft ook het id.
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 -
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)
1
2
3
4
5
6
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 );
$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)
1
2
3
4
5
6
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 );
$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:
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
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?
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.