Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Enumerator w PHP
Forum PHP.pl > Inne > Oceny
batman
Oddaję dzisiaj pod waszą ocenę klasę enumeratora, którego tak bardzo mi brakuje w PHP (SplEnum to jakieś nieporozumienie). Jak sama nazwa wskazuje jet to standardowy typ wyliczeniowy, zaimplementowany w PHP.

Kod klasy
  1. namespace Batman;
  2.  
  3. abstract class Enum
  4. {
  5. private static $_consts = null;
  6.  
  7. final public function __construct()
  8. {
  9. throw new \ErrorException('Can\'t create object from enum');
  10. }
  11.  
  12. final static private function getConstants()
  13. {
  14. if(self::$_consts === null) {
  15. $class = get_called_class();
  16. if($class == __CLASS__) {
  17. throw new \BadMethodCallException('You can\'t access constants from Enum class');
  18. }
  19. $reflection = new \ReflectionClass($class);
  20. self::$_consts = $reflection->getConstants();
  21. }
  22. return self::$_consts;
  23. }
  24.  
  25. final static public function getNames()
  26. {
  27. return array_keys(self::getConstants());
  28. }
  29.  
  30. final static public function getValues()
  31. {
  32. return array_values(self::getConstants());
  33. }
  34. }


Przykład użycia
  1. class UserStatus extends \Batman\Enum
  2. {
  3. const DELETED = -1;
  4. const BLOCKED = 0;
  5. const ACTIVE = 1;
  6. }


Download, issue tracker i całą resztę znajdziecie na githubie.
hwao
Sam kod jest bardzo ładnie napisany, dlatego też nie spodziewam się w tym temacie za dużego ruchu. Także muszę się poczepiać żeby napisać cokolwiek smile.gif

[PHP] test1.php - pobierz, plaintext
  1. <?php
  2.  
  3. include './Enum.php';
  4.  
  5. class UserStatus extends \Batman\Enum
  6. {
  7. const DELETED = 'ble';
  8. const BLOCKED = 0;
  9. const ACTIVE = 1;
  10. }
[PHP] test1.php - pobierz, plaintext


Można ustawić jako string, raczej nie powinno się dopuszczać do takiej możliwości.

[PHP] test2.php - pobierz, plaintext
  1. <?php
  2.  
  3. include './Enum.php';
  4.  
  5. class UserStatus extends \Batman\Enum
  6. {
  7. const DELETED = 'ble';
  8. const BLOCKED = 0;
  9. const ACTIVE = 1;
  10. }
  11.  
  12. var_dump( UserStatus::DELETED );
  13. var_dump( UserStatus::getNames() );
  14. var_dump( UserStatus::getValues() );
[PHP] test2.php - pobierz, plaintext


Są 2 metody, przydała by mi się jeszcze 3 która zwraca mi Wartość (Values) => Nazwa (Names)
Lub metoda, która z Value poda mi Name:

[PHP] test3.php - pobierz, plaintext
  1. $mUserStatus = \UserStatus::DELETED;
  2.  
  3. var_dump( $mUserStatus );
  4.  
  5. echo 'User status: '.$mUserStatus;
[PHP] test3.php - pobierz, plaintext


Żeby po uruchomieniu jakiejś metody z parametrem $mUserStatus był output:
Kod
User status: DELETED
batman
Cytat
Można ustawić jako string, raczej nie powinno się dopuszczać do takiej możliwości.
Niestety PHP nie daje możliwości wymuszenia typu prostego. Ale w momencie korzystania z refleksji będę mógł dodać sprawdzenie typu.

Cytat
Są 2 metody, przydała by mi się jeszcze 3 która zwraca mi Wartość (Values) => Nazwa (Names)
Lub metoda, która z Value poda mi Name:
Pojawi się metoda toArray i prawdopodobnie iterator.

Cytat
Żeby po uruchomieniu jakiejś metody z parametrem $mUserStatus był output:
Kod
User status: DELETED
Dobry pomysł. Nie potrzebowałem takiej funkcjonalności, ale na pewno się przyda.
Bags_Bunny
  1. class EnumTest1 extends \Batman\Enum
  2. {
  3. const foo = 1;
  4. }
  5.  
  6. class EnumTest2 extends \Batman\Enum
  7. {
  8. const bar = 1;
  9. }
  10.  
  11. print_r( EnumTest1::getNames() ); //foo
  12. print_r( EnumTest2::getNames() ); //foo (!)
Speedy
Gdzie wykorzystujesz tę klasę? Czy jest ona tak naprawdę potrzebna w PHP, czy to raczej sztuka dla sztuki? Czy odpowiednia implementacja interfejsu Iterator lub IteratorAggregate nie byłaby wystarczająca?
batman
@Bags_Bunny
Dzięki za znalezienie tego babola. Poprawione.

@Speedy
Równie dobrze sztuką dla sztuki można nazwać interfejsy lub klasy abstrakcyjne. Wymienione przez Ciebie iteratory służą do czegoś zupełnie innego. Zadaniem typu wyliczeniowego jest zebranie w jednym miejscu podobnych do siebie danych. Najlepszym przykładem będą tutaj dni tygodnia lub miesiące. Tworząc typ wyliczeniowy, w kodzie posługujemy się czytelnymi dla ludzi nazwami, natomiast aplikacja otrzymuje liczbę. W ten sposób nie zaśmiecamy klas/konfiguracji zbędnymi informacjami.
Speedy
Klasy abstrakcyjne i interfejsy akurat są przydatne. Enumeratory mamy też dostępne jako typ pola w tabelach bazy danych, a aplikacje internetowe prawie zawsze bazy wykorzystują, więc można z tego korzystać, choć ja i tak wolę tworzyć sobie tabele słownikowe, bo projekt jest wtedy bardziej czytelny i elastyczny.
batman
@Speedy
Nie można polegać na zewnętrznych mechanizmach. Co z tego, że baza danych posiada pole typu enum. A jeśli będziemy korzystali z MongoDB lub chmury? Tam nie ma czegoś takiego jak enum.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.