2009-09-09 21 views
5

Mam dość dużą witrynę i każda strona jest zbudowana z kilku dołączonych plików, moja strona jest w 100% w formacie proceduralnym i staram się nauczyć korzystać z klas i więcej podejścia OOP w PHP.Czy powinienem ponownie łączyć się z mysql w PHP?

Obecnie moja strona ma plik nagłówkowy, który jest zawarty na każdej stronie, w tym nagłówku jest utworzone połączenie mysql i trwa przez cały czas trwania strony, więc jeśli muszę uruchomić 10 różnych zapytań z różnych plików, wszystkie działają bez potrzeby nawiązywania nowego połączenia, więc połączenie jest nawiązywane tylko raz.

Teraz, gdy próbuję przekonwertować na bardziej OO sposób, zaczynam od pisania klasy mysql do łączenia i uruchamiania kwerend, więc mam zamiar użyć klas __construct funkcja do nawiązania połączenia z mysql, jestem Ciekawe, jak to by działało, za każdym razem, gdy ta klasa zostanie wywołana, spróbuje nawiązać połączenie z mysql zamiast tylko raz.

Może nie myślę jasno. Czy powinienem zainicjować tę klasę w nagłówku 1 raz, a potem nie będę się już musiał martwić?

Odpowiedz

6

Można utworzyć pojedynczy obiekt globalny klasy MySQL i używać go wszędzie. Wtedy twój konstruktor zostanie wywołany tylko raz.

Można też tworzyć nowe obiekty w klasie MySQL wszędzie. mysql_connect nie otwiera nowe połączenia, jeśli istnieje już jeden otwarty:

Jeśli drugie wywołanie mysql_connect() z tymi samymi argumentami, nie nowe połączenie zostanie nawiązane, ale zamiast tego, identyfikator połączenia z już otwarty link zostanie zwrócony.

+0

Można również napisać oddzielną pojedynczą klasę do łączenia się z bazą danych, w ten sposób otwiera się tylko jedno połączenie, jest spójne i jest suche. –

+1

Eh ... Mam na myśli klasę singleton. Och, jakże nienawidzę tych tygodni, które mają tylko poniedziałki ... –

+0

Tak, to jest inne rozwiązanie, o którym nie myślałem. –

-2

Możesz użyć tej metody, jeśli użyjesz funkcji mysql_pconnect(), która wyszuka, czy jest już połączenie mysql i na wypadek gdyby go znalazł, nie utworzyłby innego.

W alternatywa, jeśli wziąć pod uwagę, ani używać instancji w php, można wywołać obiektu bazy danych php bezpośrednio, jak:

class DB {} 

DB::connect($host, $user, $pass); 

W przypadku korzystania z tej metody, nie trzeba się martwić o wielu połączeń . Oczywiście, jeśli potrzebujesz użyć kilku połączeń do więcej niż jednej bazy danych na raz, możesz skorzystać z instancji obiektu lub utworzyć klasę, aby mogła zająć kilka parametrów i przechowywać je wszystkie na raz (niezbyt to bardzo polecane)

+0

Nie wprowadzaj w błąd przy korzystaniu z mysql_pconnect(). –

+0

mysql_pconnect: Najpierw, podczas łączenia, funkcja najpierw spróbuje znaleźć (trwałe) łącze, które jest już otwarte z tym samym hostem, nazwą użytkownika i hasłem. Jeśli zostanie znaleziony, jego identyfikator zostanie zwrócony zamiast otwierania nowego połączenia. źródło: php.net co jest znowu nie tak? – yoda

1

Tak, nie powinieneś łączyć wiele razy. Obciążenie związane z otwieraniem i zamykaniem połączenia jest przez cały czas większe niż koszt utrzymania go w stanie otwartym podczas względnie małego czasu działania skryptów. Powinieneś więc utworzyć instancję klasy na początku i zachować ją w zmiennej globalnej.

Z pewnością nie jest to zły pomysł, aby pisać własne zajęcia jako ćwiczenie, ale może powinieneś zajrzeć do jednego z istniejących rozwiązań zarządzania połączeniami z bazą danych (Zend_Db itp.).

0

Zawsze można zapisać odniesienie do łącza do bazy danych w zmiennej STATIC klasy i wywołać ją w razie potrzeby. Jednak PHP sam próbuje użyć istniejącego łącza, jeśli istnieje w pamięci.

Mam przykładowy kod obsługi bazy danych dla ciebie, oczywiście jego PHP 5 i używa ChNP.

<?php 
// Class providing generic data access functionality 
class DatabaseHandler 
{ 
    // Hold an instance of the PDO class 
    private static $_mHandler; 

    // Private constructor to prevent direct creation of object 
    private function __construct() 
    { 
    } 

    // Return an initialized database handler 
    private static function GetHandler() 
    { 
    // Create a database connection only if one doesn’t already exist 
    if (!isset(self::$_mHandler)) 
    { 
     // Execute code catching potential exceptions 
     try 
     { 
     // Create a new PDO class instance 
     self::$_mHandler = 
      new PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD); 

     // Configure PDO to throw exceptions 
     self::$_mHandler->setAttribute(PDO::ATTR_ERRMODE, 
             PDO::ERRMODE_EXCEPTION); 
     self::$_mHandler->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); 
     } 
     catch (PDOException $e) 
     { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
     } 
    } 

    // Return the database handler 
    return self::$_mHandler; 
    } 
    // Clear the PDO class instance 
    public static function Close() 
    { 
    self::$_mHandler = null; 
    } 
    // Wrapper method for PDO::prepare 
    private static function Prepare($queryString) 
    { 
    // Execute code catching potential exceptions 
    try 
    { 
     // Get the database handler and prepare the query 
     $database_handler = self::GetHandler(); 
     $statement_handler = $database_handler->prepare($queryString); 

     // Return the prepared statement 
     return $statement_handler; 
    } 
    catch (PDOException $e) 
    { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
    } 
    } 

    // Wrapper method for PDOStatement::execute() 
    public static function Execute($sqlQuery, $params = null) 
    { 
    // Try to execute an SQL query or a stored procedure 
    try 
    { 
     $statement_handler = self::Prepare($sqlQuery); 

     // Execute query 
     $statement_handler->execute($params); 
    } 
    // Trigger an error if an exception was thrown when executing the SQL query 
    catch(PDOException $e) 
    { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
    } 
    } 

    // Wrapper method for PDOStatement::fetchAll() 
    public static function GetAll($sqlQuery, $params = null, 
           $fetchStyle = PDO::FETCH_ASSOC) 
    { 
    // Initialize the return value to null 
    $result = null; 

    // Try to execute an SQL query or a stored procedure 
    try 
    { 
     $statement_handler = self::Prepare($sqlQuery); 

     // Execute the query 
     $statement_handler->execute($params); 

     // Fetch result 
     $result = $statement_handler->fetchAll($fetchStyle); 
    } 
    // Trigger an error if an exception was thrown when executing the SQL query 
    catch(PDOException $e) 
    { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
    } 

    // Return the query results 
    return $result; 
    } 

    // Wrapper method for PDOStatement::fetch() 
    public static function GetRow($sqlQuery, $params = null, 
           $fetchStyle = PDO::FETCH_ASSOC) 
    { 
    // Initialize the return value to null 
    $result = null; 

    // Try to execute an SQL query or a stored procedure 
    try 
    { 

     $statement_handler = self::Prepare($sqlQuery); 

     // Execute the query 
     $statement_handler->execute($params); 

     // Fetch result 
     $result = $statement_handler->fetch($fetchStyle); 
    } 
    // Trigger an error if an exception was thrown when executing the SQL query 
    catch(PDOException $e) 
    { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
    } 

    // Return the query results 
    return $result; 
    } 

    // Return the first column value from a row 
    public static function GetOne($sqlQuery, $params = null) 
    { 
    // Initialize the return value to null  
    $result = null; 

    // Try to execute an SQL query or a stored procedure 
    try 
    { 
     $statement_handler = self::Prepare($sqlQuery); 

     // Execute the query 
     $statement_handler->execute($params); 

     // Fetch result 
     $result = $statement_handler->fetch(PDO::FETCH_NUM); 

     /* Save the first value of the result set (first column of the first row) 
     to $result */ 
     $result = $result[0]; 
    } 
    // Trigger an error if an exception was thrown when executing the SQL query 
    catch(PDOException $e) 
    { 
     // Close the database handler and trigger an error 
     self::Close(); 
     trigger_error($e->getMessage(), E_USER_ERROR); 
    } 

    // Return the query results 
    return $result; 
    } 
} 
?> 
0

należy przekazać obiekt połączenia (prawdopodobnie PDO) wokół i różne miejsca powinny być w stanie podnieść, że w górę, albo jako parametr, lub jako własność jakiegoś centralnego obiektu, które inni mają odniesienie do czegoś lub czegoś.

Posiadanie wielu połączeń może być przydatne, wydaje się obłędne, że mysql_connect odbiera istniejące połączenie, kiedy być może chciałeś nowego - ale i tak jest to obłędne. Wystarczy użyć PDO.

2

Najlepszym sposobem, jak sądzę, jest użycie specjalnej klasy do obsługi połączeń mysql i używania go jako singleton. Utwórz konstruktor jako prywatny i poproś o zwrócenie instancji istniejącego lub nowego połączenia.

Oto mój przykład:

class db 
{ 

    public $host; 
    public $user; 
    public $pass; 
    public $database; 

    private static $instance = false; 

    private function __construct() 
    { 

    } 

    public static function getInstance() 
    { 
     if (self::$instance === false) 
     { 
      self::$instance = new db; 
     } 
     return self::$instance; 
    } 

     public function db_connect() 
     { 
     } 

     public function db_disconnect() 
     { 
     } 
} 

W ten sposób, kiedy zadzwonić: db :: getInstance() -> db_connect(), jesteś pewien, że będzie tylko być jedno wystąpienie związku wszędzie.

+0

Właśnie teraz spoglądam wstecz na to. Jestem trochę zdezorientowany, masz go jako db :: getInstance() -> db_connect() czy muszę używać db :: getInstance() -> METHODNAME-HERE dla każdej metody, którą wywołuję w klasie DB? JEŚLI mam metodę o nazwie execute(), które przekazuję kwerendę SQL, musiałbym to zrobić w ten sposób, db :: getInstance() -> execute ($ sql)? Dzięki za pomoc – JasonDavis

Powiązane problemy