2009-07-18 10 views
6

Obecnie tworzę system blogów, który mam nadzieję przekształcić w pełny system CMS w przyszłości.Jak uniknąć używania globalnych obiektów PHP?

Istnieją dwie klasy/obiekty, które byłyby użyteczne, aby mieć globalny dostęp (połączenie z bazą danych mysqli i niestandardową klasą, która sprawdza, czy użytkownik jest zalogowany).

Szukam sposobu, aby to zrobić bez użycia obiektów globalnych, a jeśli to możliwe, nie przekazywanie obiektów do każdej funkcji za każdym razem, gdy są one wywoływane.

Odpowiedz

13

Można utworzyć obiekty statyczne, a następnie uzyskać do nich dostęp w dowolnym miejscu. Przykład:

myClass::myFunction(); 

To zadziała w dowolnym miejscu skryptu. Jednak możesz chcieć odczytywać klasy statyczne i ewentualnie używać klasy Singleton w celu utworzenia zwykłej klasy wewnątrz statycznego obiektu, który może być używany w dowolnym miejscu.

Expanded

myślę, co chce zrobić, jest bardzo podobny do tego, co robię z moim klasy DB.

class myClass 
{ 
    static $class = false; 
    static function get_connection() 
    { 
     if(self::$class == false) 
     { 
      self::$class = new myClass; 
     } 
     return self::$class; 
    } 
    // Then create regular class functions. 
} 

Co się dzieje, jest po odebraniu połączenia, za pomocą $ object = myClass :: get_connection(), będzie w stanie regularnie zrobić funkcję cokolwiek.

$object = myClass::get_connection(); 
$object->runClass(); 

Expanded

Gdy to zrobisz, że deklaracje statyczne, wystarczy zadzwonić get_connection i przypisać wartość zwracaną do zmiennej. Następnie pozostałe funkcje mogą mieć takie samo zachowanie jak klasa, którą wywołałeś za pomocą $ class = new myClass (ponieważ tak właśnie zrobiliśmy). Wszystko, co robisz, to przechowywanie zmiennej klasy wewnątrz klasy statycznej.

class myClass 
{ 
    static $class = false; 
    static function get_connection() 
    { 
     if(self::$class == false) 
     { 
      self::$class = new myClass; 
     } 
     return self::$class; 
    } 
    // Then create regular class functions. 
    public function is_logged_in() 
    { 
     // This will work 
     $this->test = "Hi"; 
     echo $this->test; 
    } 
} 

$object = myClass::get_connection(); 
$object->is_logged_in(); 
+0

Witam, dziękuję za odpowiedź, czy możliwe jest zapisanie zmiennych w klasach statycznych. tj. funkcja połączenia, aby sprawdzić, czy użytkownik jest zalogowany, a następnie uzyskać dostęp do tej zmiennej kilka razy później na stronie? –

+2

Tak, dla klasy statycznej dokonaj tego samego, co zrobiłem, aby zadeklarować zmienną $ class. Jedyne, co musisz zrobić, to "zadeklarować" każdą zmienną, której używasz. –

+1

Ale kod, który ci dałem pozwala ci na regularne używanie każdej regularnej klasy. Część statyczna po prostu podaje klasę, zamiast ją globalizować. Będę edytować, aby pokazać trochę więcej. –

1

Cóż, jeśli masz już jakiś przedmiot przez które odnoszą się do układu bloga, można komponować te obiekty w tym, tak, że są one $blog->db() i $blog->auth() czy cokolwiek innego.

+0

Mogłem, ale obiekty będą również musiały być dostępne poza klasą bloga. –

8

Możesz przekazać bieżące obiekty globalne do konstruktora.

<?php 
    class Foo { 
    protected $m_db; 
    function __construct($a_db) { 
     $this->m_db = $a_db; 
    } 
    } 
?> 
3

Niedawno zreorganizowałem moje ramy przygotowujące do drugiej wersji CMS naszej firmy. I undid Naprawiłem ogromną ilość rzeczy, które zrobiłem statycznie, aby zastąpić je normalnymi obiektami. W ten sposób stworzyłem ogromną elastyczność, która polegała na tym, że przechodzę i włamuję się do podstawowych plików. Teraz używam tylko konstrukcji statycznych, gdy jedyną alternatywą są funkcje globalne, które są związane tylko z podstawową funkcjonalnością niskiego poziomu.

Pokażę kilka linii mojego pliku bootstrap.php (wszystkie moje żądania zostaną wysłane przez ten plik, ale możesz osiągnąć ten sam wynik, włączając go na górze każdego pliku), aby pokazać ci co miałem na myśli. Jest to dość mocna wersja tego, co prawdopodobnie wykorzystasz w swojej sytuacji, ale mam nadzieję, że pomysł jest pomocny. (Wszystko to jest lekko zmodyfikowane.)

//bootstrap.php 

... 

// CONSTRUCT APPLICATION 

{  
    $Database = new Databases\Mysql(
     Constant::get('DATABASE_HOST'), 
     Constant::get('DATABASE_USER'), 
     Constant::get('DATABASE_PASSWORD'), 
     Constant::get('DATABASE_SCHEMA') 
    ); 

    $Registry  = new Collections\Registry; 
    $Loader  = new Loaders\Base; 
    $Debugger  = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console 

    $Application = new Applications\Base($Database, $Registry, $Loader, $Debugger); 
} 

... 

Jak widać, mam wszelkiego rodzaju opcje tworzenia mojego obiektu aplikacji, które mogę przewidziany jako argument konstruktora do innych obiektów, aby dać im dostęp do tych „światowych” pierwszej potrzeby.

Obiekt bazy danych nie wymaga objaśnień. Obiekt rejestru działa jako kontener dla obiektu, do którego mogę chcieć uzyskać dostęp w innym miejscu aplikacji. Program ładujący działa jako narzędzie do ładowania innych zasobów, takich jak pliki szablonów. I debugger jest tam, aby obsłużyć wyjście debugowania.

Mogę, na przykład, zmienić klasę bazy danych, którą utworzę i, voila Mam połączenie z bazą danych SQLite. Mogę zmienić klasę debuggera (jak wspomniano) i teraz wszystkie moje informacje dotyczące debugowania będą logowane do mojej konsoli JavaScript.

OK, teraz wracamy do problemu. W jaki sposób dajesz dostęp do wszystkich innych obiektów? Po prostu przekazujesz go argumentowi do konstruktora.

// still bootstrap.php 

... 

// DISPATCH APPLICATION 

{ 
    $Router = new Routers\Http($Application); 
    $Router->routeUri($_SERVER['REQUEST_URI']); 
} 

... 

To nie wszystko, ale mój router (lub jakikolwiek obiekt, który z nim konstruuję) jest bardziej elastyczny. Teraz mogę inaczej utworzyć instancję obiektu aplikacji, a mój router zachowa się odpowiednio inaczej.

Powiązane problemy