2012-05-24 14 views
10

Jestem względną nowicjuszką w PHP i staram się znaleźć najlepszy sposób na wprowadzenie kodu dostępu do bazy danych. Próbuję utworzyć proste obiekty dostępu do bazy danych - każda tabela otrzymuje własną klasę, każda instancja klasy reprezentuje wiersz w tabeli, znasz ćwiczenie.Streszczenie Funkcja statyczna w PHP 5.3

Mam kod, który wydaje się działać, ale niektóre z tego, co widziałem w sieci, sprawiają, że martwię się, że moje podejście może być w jakiś sposób błędne. A od "Czy mogę to zrobić?" i "POWINIENEM to zrobić?" są dwa różne pytania, miałem nadzieję, że niektórzy weterynarze PHP mogą zadzwonić.

Moja obecna strategia polega na utworzeniu abstrakcyjnej klasy tabeli na poziomie podstawowym, która zawiera cały wspólny kod, a następnie każda klasa reprezentująca pojedynczą tabelę rozszerza ją.

Moim głównym problemem jest to kod:


abstract class Table { 
    protected abstract static function get_fields(); 
    protected abstract static function get_primary_key(); 
    protected abstract static function get_table_name(); 

Chodzi o to, że każda klasa wdrożenia zdefiniuje nazwy pól, klucz podstawowy (s), nazwę tabeli, etc., a następnie klasę Table będzie wykorzystywać te funkcje do wypełnienia określonych półwyrobów, tak:


    static function insert($values) { 
     $field_list = array(); 
     $value_list = array(); 
     foreach (static::get_fields() as $field_name) { 
      if (isset($values[$field_name])) { 
       $field_list[] = $field_name; 
       $value_list[] = self::escape($values[$field_name]); 
      } 
     } 
     $field_string = join(", ", $field_list); 
     $value_string = "'" . join("', '", $value_list) . "'"; 

     $sql = "insert into " . static::get_table_name() . " ($field_string) values ($value_string)"; 

jak widać, kluczem jest to, że mam dostęp do tych funkcji przez static abstract poprzedzając je static::. I o ile wiem, działa!

Jednak zaakceptowana odpowiedź na this question wskazuje, że funkcje abstract static są nadal niedozwolone w 5.3.

Więc, próbuję dowiedzieć się, co z tym zrobić. Czy odpowiedź jest błędna - czy funkcje abstract static są teraz uznawane za całkowicie legalny kod PHP? Czy robię coś niewskazanego w moim kodzie? Czy istnieje inne podejście, które powinienem rozważyć?

+1

Jeśli powiedzieć „wiesz ofertę ", Jedno wiem na pewno: umowa nie polega na używaniu do tego funkcji statycznych. Jeśli sądzisz, że tak, to musi to być sprawdzanie wartości null, ponieważ funkcje statyczne nie działają dobrze z dziedziczeniem, z którego chcesz korzystać. Dodatkowo proponuję przeczytać PoEEA, znaczysz, znasz rodzaj książki, prawda? – hakre

+4

@hakre: Skąd się bierze ta wrogość i protekcjonalność? "Wiesz, że wiertło" było odniesieniem do dość standardowego podejścia do modelowania zawartości bazy danych, które moim zdaniem nie było warte omówienia. – BlairHippo

+0

Proszę podać, że to, co opisujesz, jest dość standardowym podejściem. – hakre

Odpowiedz

17

Tu masz przykład

abstract class Table implements iTable { 

    public static function insert() { 
     $class = get_called_class(); 
     $sql = 'INSERT INTO '.$class::get_class_name(); 
     echo $sql; 
    }  

} 

interface iTable { 
    static function get_class_name(); 
}  


class ConcreteTable extends Table 
{ 
    public function ConcreteTable() {} 

    static function get_class_name() { 
     return 'ConcreteTable'; 
    } 

} 

$t = new ConcreteTable(); 
$t::insert(); 

Ten przykład szanuje obiekt paradygmat, i jesteś pewien, że to działa, nawet jeśli wsparcie przystanek PHP Wiązania późno statyczne (co jest specyficzność PHP, myślę)

Edycja: Obie odpowiedzi pokazują, że nie wiadomo, czy klasa abstrakcyjna wprowadza interfejs również dla klas od niego wychodzących.Podążając za wzorcem szablonowym, jest to możliwe w PHP nawet przy funkcjach statycznych (aczkolwiek z dobrego powodu, który daje ci ścisłe standardowe ostrzeżenia). Dowód koncepcji:

abstract class Table 
{ 
    abstract static function get_class_name(); 
    public static function insert() { 
     printf('INSERT INTO %s', static::get_class_name()); 
    }  

} 

class ConcreteTable extends Table 
{ 
    public static function get_class_name() { 
     return 'ConcreteTable'; 
    } 
} 

ConcreteTable::insert(); 

Jeśli usuniesz statyczne słowo tutaj, to rzeczywiście będzie przydatny (i standardowy sposób robienia rzeczy) Kod:

abstract class Table 
{ 
    protected $table = NULL; 
    public function insert() { 
     printf('INSERT INTO %s', $this->table); 
    }  

} 

class ConcreteTable extends Table 
{ 
    protected $table = 'ConcreteTable'; 
} 

$table = new ConcreteTable(); 
... 
$table->insert(); 
+0

Hmm, dlaczego tam jest oczywiście zbędny "nowy" - wystarczy tylko ciąg znaków, np. '$ t = 'ConcretTable';' Dlaczego po prostu nie uzależnisz tego od nazwy funkcji odczytanej ze stałą '__FUNCTION__'? Lub jeszcze bardziej powszechne: Dodaj nazwę tabeli jako chronioną właściwość (lub zapytanie SQL)? – hakre

+0

Zapraszanie interfejsu na przyjęcie wydaje mi się zachowanie, którego szukam, bez żadnych logicznych paradoksów zaśmiecających mój kod. Masz moje podziękowania. :-) – BlairHippo

+0

Zobacz także http://pl.wikipedia.org/wiki/Template_method_pattern – hakre

6

Funkcja abstrakcyjna nigdy nie będzie statyczna, w żadnym języku.

Funkcja statyczna zapewnia funkcjonalność, nawet jeśli nie ma instancji.

Funkcja abstrakcyjna nie zapewnia żadnej funkcji.

Logicznie rzecz biorąc, nie można użyć abstrakcyjnej funkcji statycznej, która - WOLNA I NIGDY - nie zapewnia funkcjonalności.


B rozszerza

Po wywołaniu funkcji statycznych w kontekście B, to będzie prowadzona w kontekście (przyczyną stanie statycznym).

Ale w kontekście ta sama funkcja jest abstrakcyjna, a nie wolno jej nazywać.

+0

To byłoby "tak" dla pytania, czy robię coś niewskazanego. Czy masz jakiś wgląd w to, dlaczego PHP wydaje się pozwalać mi uciec mimo to, lub sugestie alternatywnego podejścia, które jest mniej paradoksalne? – BlairHippo

+0

Używasz niewłaściwego paradygmatu obiektu. Zgadzam się z abstrakcyjnym słowem kluczowym, ale te 3 funkcje będą zawsze działać na instancjach, nie powinny być statyczne. – zessx

+0

Dlaczego nie powinny być statyczne? Lista pól dla obiektu użytkownika pozostanie spójna we wszystkich obiektach użytkownika; nie zależy od instancji. Podobnie, wydaje mi się, że powinienem móc wywoływać "insert" lub "select" na klasie, a nie instancyjny obiekt. – BlairHippo