Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Połączenie z bazą danych, raz.
Forum PHP.pl > Forum > PHP > Object-oriented programming
fannet
Witajcie piszę ponieważ mam od dłuższego czasu problem związany z programowaniem obiektowym, otóż staram się uczyć, ale nie jakoś chce do tej głowy wpadać, no ale do rzeczy otóż staram się pisać jakieś klasy w nich metody, ale większość z nich wymaga połączenia z bazą danych i wychodzi że na 10 klas w każdej mam w konstruktorze coś takiego:
  1. <?php
  2. function __construct()
  3. {
  4.  if(!$this->connect = new mysqli(HOST, USER, PASS, NAME))
  5.  {
  6.    throw new Exception("jak zwykle złe połączenie");
  7.  }
  8. }
  9. ?>
W programowaniu obiektowych chyba podstawowym założeniem jest aby kod się nie powtarzał i żeby jeden napisany kod był wykorzystywany wiele razy, a w moim przypadku wygląda to zupełnie odwrotnie.. Proszę o jakieś naprowadzenie mnie na tą właściwą drogę w mojej i tak już pomieszanej nauce.
_olo_1984
napisz sobie prosty sterownik (klase) do mysql, potem używaj jej dowoli. Raz napisany kod wykorzystasz w każdym miejscu aplikacji. Przykładów jest bardzo dużo, poszukaj tu na formu lub google.Pozdr
fannet
Słowo kluczowe "sterownik" otworzyło mi bramę do wielu nowych lektur do analizy smile.gif
Załóżmy że już mam taki sterownik i teraz mi wychodzi na to że będę musiał w konstruktorze tworzyć nowy egzemplarz klasy?

Edit: Teraz pomyślałem przecież mogę chyba skorzystać z rozszerzenia wbudowanego w php mysqli? Wiec pozostaje pytanie jak się do tego odwołać.
Pax95
Nie widzę niczego złego w twojej klasie. Dodaj destruktor i wykorzystaj wzorzec Singleton, a obiekt inicjuj na początku dokumentu i się nie przejmuj połączeniem w innych klasach.
skowron-line
tak jak juz kolega wyżej napisał napisz sobie sterownik bazy danych a potem.
  1. <?php
  2. class user{
  3. public function __construct()
  4. {
  5. include_once( 'sterownik.sql.class.php' );
  6. $this->mysq = new sterownikMysql( 'host','user','pass','db' );
  7. }
  8. }
  9. ?>

dołącz go do każdej z klas.
Pax95
@UP: Właśnie nie o to mi chodziło :]. Połączenie tworzymy tylko jedno, nie inicjujemy go w każdej klasie.
EDIT: Nie będę żałował.
  1. <?php
  2. class Datebase
  3. {
  4.   private static $s_instance;
  5.  
  6.   private function __construct()
  7.   {
  8.      // Połączenie z bazą danych
  9.   }
  10.  
  11.   public static function getInstance()
  12.   {
  13.      if ( self::$s_instance === null )
  14.      {
  15.         self::$s_instance = new self;
  16.      }
  17.      return self::$s_instance
  18.   }
  19.  
  20.   public function __destruct()
  21.   {
  22.      // Usunięcie połączenia
  23.   }
  24. }
  25. ?>


Inicjujemy na samym początku np. index.php
  1. <?php
  2. $Datebase = Datebase::getInstance();
  3. //dalsze operacje
  4. ?>
Tarcil
Witam

Chciałbym dorzucić mój problem do tego tematu.

Napisałem klasę, która w konstruktorze tworzy połączenie z bazą danych oraz zawiera metody insertQuery, selectQuery itd, które przygotowują zapytanie do bazy, wykonywane prywatną metodą doQuery. Wszystko chodziło pięknie, ale był problem, kiedy przyszło zagnieździć zapytanie do bazy w zapytaniu. Już tłumaczę:

Załóżmy, że mamy dwie tabele.
  1. <?php
  2. Tabela news:
  3. ID int
  4. title varchar(255)
  5. time int
  6. text text
  7. authorID
  8. ?>

  1. <?php
  2. Tabela administrators:
  3. ID int
  4. name varchar(40)
  5. pass char(32)
  6. ?>


Tworzę sobie egzemplarz obiektu do obsługi bazy
  1. <?php
  2. $sql = new mySql(HOST, USER, PASS, NAME)
  3. ?>


Wyszukuję newsy w bazie:
  1. <?php
  2. $sql->selectQuery('title, time, authorID', 'news');
  3. while($news = $sql->fetchResults())
  4. {
  5. //wyświetlam news
  6. //tutaj musze wykonać coś takiego:
  7. mysql_query('SELECT name FROM administrators WHERE id='.$news['authorID']);
  8.  
  9. }
  10. ?>


Tyle, że nie po to pisałem klasę, żeby używać mysql_query(). To jedna sprawa, druga jest taka, że jeśli zamiast mysql_query() użyję znów $sql->selectQuery to zmieni mi to zapytanie używane do przewijania wyników w linijce while($news=$sql->fetchResults(). Muszę więc tworzyć dodatkowy obiekt (a to jest drugie połączenie z bazą danych - coś, czego trzeba unikać).
Sprawę rozwiązałem tak, że wydzieliłem kod połączenia z bazą danych do klasy mySqlConnect, a zapytania do klasy mySqlQueries. Tworzę jedno połączenie z bazą, a potem odpowiednio do potrzeb tworzę obiekty odpowiadające za przygotowanie zapytań do bazy:
  1. <?php
  2. $sql = new mySqlConnect(HOST, USER, PASS, DBNAME);
  3. $query_news = new mySqlQueries($sql->handler);
  4. $query_author = new mySqlQueries($sql->handler);
  5. $query_news->selectQuery('id, title, text, authorID', 'news');
  6. while($news = $query_news->fetchResults())
  7. {
  8. //wyświetlanie newsa...
  9. $query_author->selectQuery('name', 'administrators', 'id='.$news['authorID']);
  10. $admin = $query_author->fetchResults();
  11. //wyświetlenie nazwy autora newsa
  12. }
  13. $query_news->__destruct();
  14. $query_author->__destruct();
  15. ?>


Tak to działa u mnie... tylko, że coś mi mówi, że to nie jest dobre podejście... Czy ktoś podejmie się oceny takiego rozwiązania i ewnetualnie wskaże mi bardziej właściwą drogę?

Pozdrawiam
Tarcil
PS. Przepraszam, jeżeli wciąłem się w złym temacie.
Black-Berry
Twój problem jest bardzo 'klasyczny'. Masz tak:
  1. <?php
  2. while($news = $query_news->fetchResults())
  3. ?>

a jeśli masz zagnieżdzenia powinieneś mieć tak:
  1. <?php
  2. $result =  $query_news->getResult();
  3. while($news = $query_news->fetchResults($result))
  4. ?>


A co do wyższych postów to na dalszym etapie prac przekonacie się że singletony to bagno w które lepiej się nie pakować. Było wiele wątków na ten temat. Zainteresujcie się rozwiązaniem za pomocą kontekstu;

Tarcil kombinujesz bez singletona ale coś masz nie tak; Zrób sobie plik Bootstrap.php a w nim:

  1. <?php
  2. function __autoload($class)
  3.    {
  4.        $class = str_replace('_', '/', $class);
  5.        require_once $class . '.php';
  6.    }
  7.    
  8.    //creating core objects...
  9.    $config = new Config();
  10.    $log = new Log();
  11.    $dbDriver = new Db_Driver();
  12.    $session = new Session();
  13.    $language = new Language();
  14.    $user = new User();
  15.    [b]$news= new News();[/b]
  16.    $router = new Router();
  17.    $buffer = new Buffer();
  18.    
  19.    //creating context...
  20.    $context = new Core_Context();
  21.    $context->setConfig($config);
  22.    $context->setLog($log);
  23.    $context->setDbDriver($dbDriver);
  24.    $context->setSession($session);
  25.    $context->setLanguage($language);
  26.    $context->setUser($user);
  27.    [b]$context->setNews($news);[/b]
  28.    $context->setRouter($router);
  29.    $context->setBuffer($buffer);
  30.    
  31.    //setting context...
  32.    $log->setContext($context);
  33.    $dbDriver->setContext($context);
  34.    $session->setContext($context);
  35.    $language->setContext($context);
  36.    $user->setContext($context);
  37.    [b]$news->setContext($context);[/b]
  38.    $router->setContext($context);
  39.    $buffer->setContext($context);
  40.    
  41.    //other...
  42.    $config->load(MAIN_PATH . 'config.ini');
  43.    $dbDriver->connect();
  44.    $dbDriver->query('SET NAMES `utf8`');
  45.    $language->initialize();
  46.   [b] $news->initialize();[/b]
  47. ?>
Tarcil
Dzięki smile.gif
Jak znajdę trochę czasu na przepisanie kodu to na pewno skorzystam smile.gif

Black-BerryChciałem Ci dać "Pomógł" ale nie widzę nigdzie odpowiedniego przycisku...

Pozdrawiam
skowron-line
Cytat(Tarcil @ 2.02.2009, 12:06:20 ) *
Black-BerryChciałem Ci dać "Pomógł" ale nie widzę nigdzie odpowiedniego przycisku...

I nie znajdziesz jeżeli nie jesteś autorem Wątku.
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.