ugrás a tartalomhoz

Doctrine: "virtuális" tulajdonság létrehozása

fchris82 · 2009. Jún. 1. (H), 17.41
Eddig a Propelt használtam, és most szeretnék áttérni Doctrine-ra. A problémám az, hogy jelen esetben van egy payoff tábla. Tömören az alábbi tulajdonságokkal bír:
payoff:
  id: serial primary key
  created: datetime
  ...
Propel alatt létre tudtam hozni egy valójában nem létező tulajdonságot, melynek neve: number . Ez olyasmi, mint a számlaszám, a létrehozás éve + '-' + id, nullákkal feltöltve. Pl:
  1. id = 23  
  2. created = '2009-03-20'  
  3. --------------------------  
  4. number = 2009-000023  
Ennek megvalósítása egyszerű volt, a Payoff osztályban létrehoztam egy getNumber() fv. Ez Doctrine alatt sem lenne probléma, ami viszont az, hogy így nem tudom "egységesen" kezelni a objektum tulajdonságait. Propel alatt:
  1. echo $obj->getId();  
  2. echo $obj->getCreated('Y-m-d');  
  3. echo $obj->getNumber();  
Doctrine alatt? :
  1. echo $obj->id;  
  2. echo $obj->created;  
  3. echo $obj->getNumber();  
Van vmi tapasztaltabb embernek erre a "problémára" vmi szebb megoldása? Nincs vmi kiegészítés Doctrine alá, hogy a generált fájlokba belekerüljenek a get[oszlopnév]() fv-ek? Nekem az a megoldás sokkal szimpatikusabb volt. A set fv-eket felülbírálva lehetett módosítani az adaton mielőtt az adatbázisba kerül és get fv-eknél pedig kiolvasásánál lehetett vele játszani, esetleg létre lehetett hozni ilyen "vírtuális" tulajdonságokat is, amik az adatbázisban valójában nem léteztek, de a modell rendelkezett vele.
 
1

Átmeneti megoldásként

fchris82 · 2009. Jún. 1. (H), 21.35
Átmeneti megoldásként a Doctrine_Record osztály __call() fv-ét kiegészítettem az alábbival:
  1. /** 
  2.  * SAJÁT KIEGÉSZÍTÉS 
  3.  * Lehetővé teszi, hogy a tulajdonságokhoz hozzáférjünk get[Tulajdonság]() formában is! 
  4.  */  
  5. if(substr($method, 0, 3)=='get') {  
  6.   $key = Doctrine_Inflector::tableize(substr($method, 3));  
  7.   
  8.   // Ha létezik ilyen oszlop  
  9.   if(array_key_exists($key$this->_data)) {  
  10.     // Ha érkezik paraméter ÉS a mező timestamp,  
  11.     // akkor valószínűleg formázni szeretnénk a kimenetet.  
  12.     // Pl: $obj->getCreated('Y.m.d');  
  13.     if(count($args)>0 AND $this->getTable()->getTypeOfColumn($key)=='timestamp') {  
  14.       $v  = $this->get($key);  
  15.       $ts = strtotime($v);  
  16.       return ($ts>0) ? date($args[0], $ts) : $v;  
  17.     }  
  18.   
  19.     return $this->get($key);  
  20.   }  
  21. }  
  22.   
  23. if(substr($method, 0, 3)=='set') {  
  24.   $key = Doctrine_Inflector::tableize(substr($method, 3));  
  25.   
  26.   if(array_key_exists($key$this->_data)) {  
  27.     switch(count($args)) {  
  28.       case 0 : $value = null; break;  
  29.       case 1 : $value = $args[0]; break;  
  30.       default$value = $args;  
  31.     }  
  32.   
  33.     return $this->set($key$value);  
  34.   }  
  35. }  
  36.   
  37. /* Az eredeti kód jön ezután ... */  
Lehetne még azt csinálni, hogy létrehozok egy saját Self_Doctrine_Record osztályt, származtatva a Doctrine_Record-ból, és generálásnál az options-ben megadom, hogy ezt az osztályt használja ( $options = array('baseClassName' => 'Self_Doctrine_Record'); ) és abban az osztályban definiálom felül a fv-t, akkor nem kell az eredeti fájlokban turkálni.

Ez a megoldás "lassú". A Base osztályokba belegenerálva viszont gyorsabb is lenne a $obj->getVar(), mint a $obj->var, mivel az utóbbi a szintén mágikus __get() fv-t használja... Az a gond, hogy a Doctrine_Record sok "getes" fv-t tartalmaz alapból, pl a getLastModified() bezavarhat egyes tábláknál így nehéz "általánosítani" ezt a módszert, anélkül, hogy ne kellene alaposan átírni az alap kódot :-/
2

Szerintem...

Protezis · 2009. Jún. 1. (H), 22.54
A modellben:
  1. public function __get( $key ) {  
  2.  if ( $key == 'number' ) {  
  3.   return $this -> getNumber();  
  4.  }  
  5.  return parent::__get( $key );  
  6. }  
6

Erre én is gondoltam...

fchris82 · 2009. Jún. 3. (Sze), 12.43
Erre én is gondoltam, de vmiért nekem szimpatikusabb a fv hívás, "több lehetőséget" látok benne. Pl dátum esetén rögtön tudom azt formázni! Bár efpe válasza lesz valószínűleg a jó, a HydrationListener, hiszen a dátum formázása az oldalon nyelvfüggő és mindenhol ugyanaz, ha a formázást berakom egy konstansba és a dátumos táblákat kiegészítem ezzel, akkor megoldódik ez a probléma is.
3

Hydration listener? Lehet en

efpe · 2009. Jún. 2. (K), 10.40
Hydration listener?
Lehet en ertettem felre a dolgot, de nem valami ilyesmit szeretnel?
4

symfony?

Sulik Szabolcs · 2009. Jún. 2. (K), 12.50
bevezetod alapjan symfony alatt probalkozol. a doctrine valoban nem tudja ezt, viszont sf alatt a model osztalyaid az sfDoctrineRecord leszarmazottai, amely viszont mar tudja.
5

Részben "nyert"

fchris82 · 2009. Jún. 3. (Sze), 12.22
Nem, nem Symfony alatt csinálom, de onnan vettem az "ötletet". Saját keretrendszer. És igazából nem is a Propelt cserélem le, hanem a saját ORM rendszeremet, de csináltam Symfony-s oldalt, és ott alkalmaztam a fentit, de itt is kellett vmi hasonló, és... Szóval ez bonyolult, és a valóság részletezése nem változtat a problémán ;) De köszi az infót, ez még jól jöhet, mert Symfony-t még fogom használni Doctrine-nal.