2011-08-01 14 views
5

Załóżmy Mam następujący Doctrine 2 jednostki:Stałe w doktrynie 2 podmiotów

/** 
* @ORM\Entity 
* @ORM\Table(name="users") 
*/ 
class User { 

    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue 
    * 
    * @var int 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(length=100) 
    * 
    * @var string 
    */ 
    protected $name; 

    /** 
    * @ORM\Column(type="integer") 
    * 
    * @var int 
    */ 
    protected $status; 
} 

Użytkownik może mieć kilka stanów, na przykład: W trakcie, aktywny, zawieszeniu. Stany te są potrzebne w całym kodzie (usługi, repozytorium itp.), A także w warstwie interfejsu użytkownika (formularz edycji użytkownika wyświetliłby je w rozwijanym menu).

Aby uniknąć definiowania ich w wielu miejscach, co zrobiłem do tej pory było użyć klasy do nich wszystkich (Wszystkie stałe w aplikacji) posiadają, i wygląda nieco jak poniżej:

class App_Constants extends Zrzr_Constants 
{ 

    protected static $_constants = array( 
     'users' => array( 
      'status' => array( 
       0 => 'Pending', 
       1 => 'Active', 
       2 => 'Suspended'))); 

} 

Klasa bazowa (Zrzr_Constants) będzie oferować kilka metod, aby je odzyskać, a wygląda to tak:

class Zrzr_Constants 
{ 
    protected static $_constants = array(); 

    public static function getConstantValues($key, $subkey) 
    { 
     // ... 
    } 

    public static function getConstantByName($name) 
    { 
     // ... 
    } 
} 

potocznym byłoby:

// example of retrieval by constant name ... it would return an integer 
$pendingStatus = App_Constants::getConstantByName('USERS.STATUS.PENDING'); 

// example of retrieval for UI display purposes ... would return an array 
$statuses = App_Constants::getConstantValues('users', 'status'); 

Oczywiście oznacza to, że istnieją pewne ograniczenia polegające na tym, że stałe etykiety nie mogą zawierać kropek, ale mogę z tym żyć.

Korzystanie z Doctrine 2 i przejście na DDD mówi mi jednak, że pole "status" powinno być w rzeczywistości "obiektem wartości" (ale Doctrine 2 jeszcze nie obsługuje obiektów wartości) lub przynajmniej powinno to być stałe zdefiniowane wewnątrz jednostki (przy użyciu const).

Moje pytanie brzmi: jak to zrobić, aby uniknąć ciągłej redefinicji warstwy UI? Muszę mieć dostęp do stałej według nazwy (w kodzie) i mieć wszystkie możliwe wartości dla takiego pola w przypadku listy rozwijanej interfejsu użytkownika (na przykład).

+0

Twój widok jest jedynym miejscem, które potrzebuje nazw.Warstwa interfejsu użytkownika powinna wykonywać całą konwersję między nazwami i wartościami; wszędzie indziej powinien po prostu użyć wartości całkowitej. Może być użyteczne dodanie niektórych metod do twojego obiektu, takich jak 'isPending()' – rojoca

+0

@rojoca - Kiedy mówisz "użyj wartości całkowitej" z pewnością nie masz na myśli czegoś takiego: 'if ($ user-> getStatus() = = 2) ... '. Interfejs użytkownika może nie być jedyną inną warstwą korzystającą z tych stałych. A co z tymi stałymi używanymi w zapytaniach, które nie przechodzą przez model domeny (przy zastosowaniu jakiegoś CQS)? – Ghola

+0

Nie; w twoim przykładzie myślę, że 'if ($ user-> isPending())' jest lepsze, ponieważ mówi dokładnie, co to znaczy. Możesz tworzyć stałe takie jak 'User :: STATUS_PENDING' w swoim modelu domeny, a następnie używać ich w' App_Constants' np. 'User :: STATUS_PENDING => 'Pending''. App_Constants zależy od twojej domeny, czy kodujesz wartości (tak jak robisz to obecnie), czy używasz stałych klas; równie dobrze możesz używać stałych. – rojoca

Odpowiedz

2

myślę, że można zrobić to w ten sposób:

class User { 
    const STATUS_PENDING = 'Pending'; 
    const STATUS_ACTIVE = 'Active'; 
    const STATUS_SUSPENDED = 'Suspended'; 

    public static function getStatusList() { 
    return array(
       self::STATUS_PENDING, 
       self::STATUS_ACTIVE, 
       self::STATUS_SUSPENDED 
       ); 
    } 

    public function getStatus() {...} 

    public function setStatus($value) {...} 

    public function isStatusPending() {...} //If you need it 
} 

W warstwie UI, można dostać wersje tekstowe swoich statusów korzystania z usług lokalizacyjnych (jeśli Stałe stanu są numery, warstwa UI może konwertować je do ciągi przez dodanie prefiksu, na przykład user_status_0). W widokach Symfony2 można użyć filtru gałązkowego, aby uzyskać tekstową wersję statusu użytkownika z domeny lokalizacji user.

Jeśli twoja strona jest tylko w jednym języku, to po prostu Użytkownik :: STATUS_XXX będzie dobrze, tak myślę. Nie sądzę, że powinieneś nadkomplikować sprawę, tworząc nową klasę do przechowywania statusów użytkownika.

Jeśli skończy się posiadanie wielu statusów lub innych powiązanych spraw, myślę, że będziesz musiał stworzyć osobny byt dla nich.

+0

W końcu znalazłem się w ten sposób w stałych domenach, ponieważ wydaje się bardziej naturalne w podejściu DDD. Ciągle używam klasy Constants dla innych stałych systemowych, które nie są powiązane z domeną. – Ghola

2

można zdefiniować klasę jak w poniższym przykładzie

class ContactResource 
{ 
    const TYPE_PHONE = 1; 
    const TYPE_EMAIL = 2; 
    const TYPE_BIRTDAY = 3; 
    const TYPE_ADDRESS = 4; 
    const TYPE_OTHER = 5; 
    const TYPE_SKYPE = 6; 
    const TYPE_LINKEDIN = 7; 
    const TYPE_MEETUP = 8; 
    const TYPE_TELEGRAM = 9; 
    const TYPE_INSTAGRAM = 10; 
    const TYPE_TWITTER = 11; 

    public static $resourceType = array(
     ContactResource::TYPE_PHONE => "Phone", 
     ContactResource::TYPE_EMAIL => "Email", 
     ContactResource::TYPE_BIRTDAY => "Birtday", 
     ContactResource::TYPE_ADDRESS => "Address", 
     ContactResource::TYPE_OTHER => "Other", 
     ContactResource::TYPE_SKYPE => "Skype", 
     ContactResource::TYPE_LINKEDIN => "LinkedIn", 
     ContactResource::TYPE_MEETUP => "Meetup", 
     ContactResource::TYPE_TELEGRAM => "Telegram", 
     ContactResource::TYPE_INSTAGRAM => "Instagram", 
     ContactResource::TYPE_TWITTER => "Twitter", 
    ); 

    /** 
    * @var integer 
    * 
    * @ORM\Column(type="integer", length=2) 
    * 
    */ 
    private $type; 


    public function __toString() 
    { 
     return (string)$this->getType(); 
    } 

    public function getType() 
    { 
     if (!is_null($this->type)) { 
      return self::$resourceType[$this->type]; 
     } else { 
      return null; 
     } 
    } 

    public static function getTypeList() { 
     return self::$resourceType; 
    } 

} 

Jeśli chcesz uzyskać typ w Gałązka

{{ entity.type }} 

Na liście wyborów

ContactResource::getTypeList() 

Nadziei działa dla ciebie!

+0

Czym różni się to od odpowiedzi Vladislava? – Ghola

+0

Odpowiedź Vladislava jest słuszna, ale ważne jest zdefiniowanie metody toString, a także de pobierających i ustawiających, aby z niej korzystać. Chcę tylko uzupełnić odpowiedź :) – xandrucancelas

+0

Nie śledzę, kiedy zdefiniowano typ $? Jak zatem uzyskać resourceType powiązany z twoją stałą wartością? dzięki. – MortisQc