Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP] Klasa do "keszowania" zapytań
adam882
post 24.06.2011, 12:58:30
Post #1





Grupa: Zarejestrowani
Postów: 289
Pomógł: 1
Dołączył: 2.11.2007

Ostrzeżenie: (0%)
-----


Witam

Prosiłbym o sprawdzenie poprawności w napisaniu klasy do "keszowania" zapytań mysql (czy chociaż dobrze zacząłem ją pisać), gdyż nie mam wiedzy na temat zaawansowanego programowania w php (którego trochę mogłem już zapomnieć) i zawsze używałem gotowych klas mysql. Klasa nie jest jeszcze dopracowana.
  1. //Klasa mysql cache
  2. class mysql
  3. {
  4. //Ustawienia
  5. private $folder='temp/'; //Folder cache
  6.  
  7. //Pomocne w klasie
  8. private $connect; //Do połączenia i zamykania połączenia z mysql
  9. public $row=array(); //Do pobierania wyników z bazy
  10. private $cache_buffer=array(); //Przechowuje tutaj dane z cache
  11. public $cache_stan=0; //Pomaga w zakończeniu pętli w fetch_assoc()
  12. public $array_num=0; //Ostatni numer tablicy
  13. private $zapytanie_bez_cache; //Gdy cache jest nieaktywne przypisuje mu wyniki z mysql_query(), aby móc odtworzyć rekordy z użyciem w funkcji klasy: fetch_assoc
  14. private $cache_name; //Nazwa pliku cache
  15. public $queries=0; //Zlicza zapytania
  16.  
  17.  
  18. ########## Konstruktor ##########
  19. function __construct($host,$user,$pass,$baza)
  20. {
  21. $this->connect=@mysql_connect($host,$user,$pass) or die('Nie mogę się połączyć z mysql <br /> Błąd: '.mysql_error());
  22. @mysql_select_db($baza) or die('Nie mogę wybrać bazy <br /> Błąd: '.mysql_error());
  23.  
  24. }
  25. ##############################
  26.  
  27.  
  28.  
  29. ########## Destruktor
  30. function __destruct()
  31. {
  32. @mysql_close($this->connect);
  33. }
  34. ##############################
  35.  
  36.  
  37.  
  38. ########## Zapytanie ##########
  39. public function query($zapytanie, $cache=false) //Drugi parametr określa, czy włączyć cache i jednocześnie przypisuje nazwę pliku
  40. {
  41.  
  42. $this->cache_name=$cache; //Daje znać, czy użyć cache jednocześnie tworząc nazwę pliku
  43.  
  44. if($this->cache_name) //Z cachowaniem (czy nazwa pliku cache została podana)
  45. {
  46.  
  47. if(file_exists(''.$this->folder.''.$this->cache_name.'.plik')) //Gdy plik cache istnieje
  48. {
  49. $this->cache_buffer=unserialize(file_get_contents(''.$this->folder.''.$this->cache_name.'.plik')); //Wczytuje tablice z pliku
  50. $this->array_num=count($this->cache_buffer); //Liczba elementów tablicy
  51. }
  52. else //Gdy nie ma pliku cache, to tworzymy go
  53. {
  54. $temp=array();
  55. $wynik=mysql_query($zapytanie) or die('Problem z zapytaniem <br /> Błąd: '.mysql_error()); //Zapytanie do bazy
  56. $this->queries++; //Liczba zapytań rośnie
  57.  
  58. while($r=mysql_fetch_assoc($wynik))
  59. {
  60. $temp[]= $r;
  61. }
  62. ignore_user_abort(1); //Gdzieś spotkałem się z takim zaleceniem
  63. $this->cache_buffer=$temp; //Przenosi tablicę z wynikami do buffera
  64. $this->array_num=count($this->cache_buffer); //Liczba elementów tablicy
  65. @file_put_contents(''.$this->folder.''.$this->cache_name.'.plik',serialize($temp)); //umieszczenie pliku
  66. }
  67. return 1;
  68. }
  69. else //Bez cachowania
  70. {
  71. $this->zapytanie_bez_cache=mysql_query($zapytanie) or
  72. die('Problem z zapytaniem<br /> Błąd: '.mysql_error()); //Zapytanie do bazy, przypisuje je zmiennej, aby móc potem pobrać rekordy
  73. $this->queries++; //Liczba zapytań rośnie
  74. }
  75.  
  76. }
  77. ##############################
  78.  
  79.  
  80.  
  81. ########## Pobieranie wyników ##########
  82. public function fetch_assoc()
  83. {
  84. if($this->cache_name) //Z cachowaniem
  85. {
  86.  
  87. if($this->array_num==$this->cache_stan){ //Czy ilość elementów jest równa numerowi tablicy, jeśli nie, to numer tablicy się zwiększa
  88. return 0; //Pobrano wszystkie elementy tablicy - koniec pętli
  89. }
  90. else
  91. {
  92. $this->row = $this->cache_buffer[$this->cache_stan]; //Tworzy tablicę do wyświetlania wyników, począwszy od tablicy z numerem 0
  93. $this->cache_stan++; return 1; //Pobiera elementy, indeks zwiększa się, pętla trwa
  94. }
  95. }
  96. else //Bez cachowania
  97. {
  98. $this->row = mysql_fetch_assoc($this->zapytanie_bez_cache);
  99. return $this->row;
  100. }
  101. }
  102. ########################################
  103.  
  104.  
  105.  
  106. ########## Mysql_num_rows ##########
  107. public function num_rows()
  108. {
  109. if($this->cache_name) //Z cachowaniem
  110. {
  111. return $this->array_num;
  112. }
  113. else //Bez cachowania
  114. {
  115. return mysql_num_rows($this->zapytanie_bez_cache);
  116. }
  117. }
  118. ####################################
  119.  
  120.  
  121. }
  122.  
  123. ##################################################
  124. ###################### TEST ######################
  125. ##BENCHMARK
  126. function czas()
  127. {
  128. $time = explode(" ", microtime());
  129. $a= (double)$time[0];
  130. $b= (double)$time[1];
  131. return $b + $a;
  132. }
  133. ##BENCHMARK
  134.  
  135. $poczatek = czas();
  136. $x=0;
  137.  
  138. $sql=new mysql('localhost','root','krasnal','baza');
  139. $sql->query('SELECT nazwa FROM rekordy ORDER BY id DESC LIMIT 100','NazwaPlikuCache'); //Drugi parametr tworzy plik cache o takiej nazwie, nie podając go cache się wyłącza
  140. if($sql->num_rows()>0){echo 'Są rekordy ('.$sql->num_rows().')<br />';}else{echo 'brak rekordów!<br />';} //Test mysql_num_rows
  141. while($sql->fetch_assoc())
  142. {
  143. $x++;
  144. echo $x.') '.$sql->row['nazwa'].'<br />';
  145.  
  146. }
  147. $koniec= czas();
  148. $c = $koniec - $poczatek;
  149. echo "<br /><br />czas generowania " . substr($c, 0, 5) . " sek.<br />Zapytań: ".$sql->queries;
  150. ##################################################
  151. ###################### TEST ######################
Powód edycji: [erix]: przeniosłem
Go to the top of the page
+Quote Post
erix
post 24.06.2011, 13:11:32
Post #2





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




  • baty za małpy przed funkcjami. Kopiesz sobie grobowiec. Coś pójdzie nie tak, to się tylko naszukasz.
  • dlaczego nie PDO/MySQLi?


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
cepa
post 24.06.2011, 13:33:01
Post #3





Grupa: Zarejestrowani
Postów: 125
Pomógł: 7
Dołączył: 27.01.2010

Ostrzeżenie: (0%)
-----


no troche do poprawienia jest:

1) nie tworz polaczenia w klasie tylko przekazuj polaczenei do klasy

2) tranzakcje i locki

3) nie uzywaj plikow do cachowania bo ci sie to wysypie, w php nie ma mutexow na pliki wiec istnieje prawdopodobienstwo ze kilka procesow php zacznie pisac w tym samym czasie do jednego pliku i uszkodzi cache

4) uzyj persistent storage, np: apc smile.gif


--------------------
Go to the top of the page
+Quote Post
adam882
post 24.06.2011, 14:08:08
Post #4





Grupa: Zarejestrowani
Postów: 289
Pomógł: 1
Dołączył: 2.11.2007

Ostrzeżenie: (0%)
-----


@erix
"małpy" usunę, sam nie wiem po co je dałem na czas testowania i pisania klasy. Wolę pozostać przy samym MySQL (przyzwyczajenie).

@cepa
W wielu klasach mysql, które przeglądałem to mniej więcej tak jak u mnie tworzono połączenia wewnątrz klasy.
Stosowanie plików cache jest złym rozwiązaniem? Możliwe, że plik cache może się uszkodzić, ale pewnie da się to jakoś zabezpieczyć, żeby nie dochodziło do nadpisywania pliku w tym samym czasie (zresztą żeby tak się stało, to chyba musiałbym mieć serwis, na którym przesiaduje z kilka tys osób online). Wiele serwisów używa cache mysql na plikach. Nie potrzebna jest mi mega zaawansowana klasa, wystarczy mi tylko, żeby była szybka, prosta, stabilna i używała cache smile.gif
Go to the top of the page
+Quote Post
cepa
post 24.06.2011, 14:37:31
Post #5





Grupa: Zarejestrowani
Postów: 125
Pomógł: 7
Dołączył: 27.01.2010

Ostrzeżenie: (0%)
-----


Cytat(adam882 @ 24.06.2011, 15:08:08 ) *
W wielu klasach mysql, które przeglądałem to mniej więcej tak jak u mnie tworzono połączenia wewnątrz klasy.

to ze w wielu to widziales to nie znaczy ze bylo to dobre, powiedzonko o muchach i gownie jest chyba najbardziej adekwatne smile.gif

Cytat(adam882 @ 24.06.2011, 15:08:08 ) *
Stosowanie plików cache jest złym rozwiązaniem? Możliwe, że plik cache może się uszkodzić, ale pewnie da się to jakoś zabezpieczyć, żeby nie dochodziło do nadpisywania pliku w tym samym czasie (zresztą żeby tak się stało, to chyba musiałbym mieć serwis, na którym przesiaduje z kilka tys osób online). Wiele serwisów używa cache mysql na plikach. Nie potrzebna jest mi mega zaawansowana klasa, wystarczy mi tylko, żeby była szybka, prosta, stabilna i używała cache smile.gif

cache na plikach nie jest zlym rozwiazaniem jak twoja aplikacja radzi sobie z konkurencyjnoscia, przykladowo taka baza danych tez operuje na plikach ale zapis do plikow jest zabezpieczony aby nie bylo sytuacji ze nagle dane z dwoch polaczen zaczna sie nawzajem nadpisywac.
php jest wolne i nawet przy niewielkim ruchu bedziesz mial przeklamania, sproboj uzyc swojego cache jako np: licznik odwiedzin.
poprostu takie rozwiazanie w php nie jest stabilne, apc czy memcache sa o niebo lepsze i szybsze smile.gif


--------------------
Go to the top of the page
+Quote Post
adam882
post 24.06.2011, 14:49:34
Post #6





Grupa: Zarejestrowani
Postów: 289
Pomógł: 1
Dołączył: 2.11.2007

Ostrzeżenie: (0%)
-----


Czyli w takim razie postaram się zmodyfikować klasę tak, aby połączenie było przekazywane do niej, tylko czy wtedy jest sens użycia mysql_close() w __destruct?
Zna ktoś może jakieś proste sposoby na zabezpieczenie nadpisywania plików w klasie w przypadku kilku połączeń?
Go to the top of the page
+Quote Post
cepa
post 24.06.2011, 14:57:06
Post #7





Grupa: Zarejestrowani
Postów: 125
Pomógł: 7
Dołączył: 27.01.2010

Ostrzeżenie: (0%)
-----


Cytat(adam882 @ 24.06.2011, 15:49:34 ) *
Czyli w takim razie postaram się zmodyfikować klasę tak, aby połączenie było przekazywane do niej, tylko czy wtedy jest sens użycia mysql_close() w __destruct?

nie ma sensu, jak ktos wyzej zauwazyl uzycie PDO byloby wygodniejsze, w destruktorze zwolnilbym referencje do obiektu bo to jest skurwoza podczas testowania pozniej, czyli poprostu $this->_connection = null

Cytat(adam882 @ 24.06.2011, 15:49:34 ) *
Zna ktoś może jakieś proste sposoby na zabezpieczenie nadpisywania plików w klasie w przypadku kilku połączeń?

nie ma, najprostsze to wlasnie apc, memcache itp itd, poszperaj na necie troche o thread race smile.gif


--------------------
Go to the top of the page
+Quote Post
erix
post 24.06.2011, 15:10:42
Post #8





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
Wolę pozostać przy samym MySQL (przyzwyczajenie).

Radzę poczytać o tym, czy jest sens stosować to przyzwyczajenie...


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
Fifi209
post 24.06.2011, 15:10:43
Post #9





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Cytat(cepa @ 24.06.2011, 14:33:01 ) *
1) nie tworz polaczenia w klasie tylko przekazuj polaczenei do klasy

Dlaczego?
Cytat(cepa @ 24.06.2011, 14:33:01 ) *
2) tranzakcje i locki

Transakcje jak już


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
cepa
post 24.06.2011, 15:19:18
Post #10





Grupa: Zarejestrowani
Postów: 125
Pomógł: 7
Dołączył: 27.01.2010

Ostrzeżenie: (0%)
-----


Cytat(Fifi209 @ 24.06.2011, 16:10:43 ) *
Dlaczego?


1) mozna wtedy uzywac obiektu w sytuacji jak potrzebne jest wiecej niz jedna baza, chociazby skrypty migracji itp
2) testowanie, jezeli masz interfejs obiektu poalczenia to mozna zrobic mocka, lub podawac mu inne zrodla danych a kod nadal dziala jak nalezy



--------------------
Go to the top of the page
+Quote Post
thek
post 24.06.2011, 16:57:39
Post #11





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Nikt nie powiedział, że klasa połączenia to Singleton? wink.gif Jeśli nie jest to można się bawić z nieograniczona liczbą obiektów i tym samym baz.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
Fifi209
post 24.06.2011, 17:36:04
Post #12





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Cytat(thek @ 24.06.2011, 17:57:39 ) *
Nikt nie powiedział, że klasa połączenia to Singleton? wink.gif

Nie, bo nie jest.
Cytat(thek @ 24.06.2011, 17:57:39 ) *
Jeśli nie jest to można się bawić z nieograniczona liczbą obiektów i tym samym baz.

I dobrze, bo nie chciałbym być zmuszony do korzystania z tylko jednego połączenia czy bazy.


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
adam882
post 25.06.2011, 06:52:45
Post #13





Grupa: Zarejestrowani
Postów: 289
Pomógł: 1
Dołączył: 2.11.2007

Ostrzeżenie: (0%)
-----


Zastanawiam się nad wdrożeniem APC, jednak prawie nic nie słyszałem o tym module (opieram się jedynie teraz na manualu php). Z tego co mi się wydaje dane będą przechowywane gdzieś w pamięci, więc folder cache nie będzie potrzebny?
Czy działanie takiej klasy powinno wyglądać mniej więcej tak?: Sprawdź czy istnieje cache przez apc_exists(), jeżeli tak, to pobiera je przez apc_fetch(), jeżeli nie to tworzy przy pomocy apc_store(). Całe cache kasowane będzie przy pomocy apc_clear_cache(), a elementy przy apc_delete()? Czy używając apc w cache mysql powinno się określać czas żywotności takiego cache?
Go to the top of the page
+Quote Post
cepa
post 28.06.2011, 12:09:05
Post #14





Grupa: Zarejestrowani
Postów: 125
Pomógł: 7
Dołączył: 27.01.2010

Ostrzeżenie: (0%)
-----


http://files.ognisco.com/kickasscache/kickasscache-20110608

tutaj jest prosta klaska ktora realizuje cache z apc i jest zabezpieczona przed thread race


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 08:38