Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP]Cachowanie danych.
Gruchol
post
Post #1





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 28.11.2014

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


Witam,
Po dłuższym czasie postanowiłem wrócić do przygody z php. Jako swój pierwszy projekt postanowiłem zakodować stronę pewnej gry.
Aktualnie robię ranking, jednak przeszukiwanie całej bazy w której są dane kilkudziesięciu tysięcy użytkowników za bardzo obciąży serwer.
Potrzebuje wyświetlić i cachować takie dane jak czas gry, poziom gracza jakieś tam osiągnięcia itd. Chciałbym aby te dane aktualizowały się np. co 10 minut.
Na internecie znalazłem klasę nospora, jednak nie wiem jeszcze jak za bardzo się jej używa.
Prosiłbym Was o jakieś wskazówki i poradniki (mogą być anglojęzyczne) jakiej klasy użyć ew. jak to rozwiązać.
Pozdrawiam.
Go to the top of the page
+Quote Post
Rysh
post
Post #2





Grupa: Zarejestrowani
Postów: 821
Pomógł: 111
Dołączył: 11.09.2006
Skąd: Biała Podlaska

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


Zazwyczaj klasy tego typu działają na podobnej zasadzie.
Czyli klasa sprawdza czy zapytanie jest cachowane jeśli jest to je pobiera i wyświetlasz, w przeciwnym wypadku pobierasz dane z bazy danych i wysyłasz do cache na określona ilość sekund.
Biblioteka sama sprawdzi czy czas świeżości danych został przekroczony, jeśli został to nic nie zwróci.
Jeśli masz problem najlepiej z wpadnij konkretnym bilbioteką/kodem, będzie łatwiej nam pomóc.

Takich bibliotek znajdziesz wiele:
https://www.google.pl/search?q=php+cache+github
Go to the top of the page
+Quote Post
Gruchol
post
Post #3





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 28.11.2014

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


Napisałem taką funkcję

  1. function DisplayRanking()
  2. {
  3. global $db;
  4.  
  5. $info = $db->query("SELECT player.player.id, player.player.name, player.player.level, player.player.playtime, player.player.last_play, player.guild.name AS 'guild_name' FROM player.player, player.guild, player.guild_member WHERE player.player.id = player.guild_member.pid AND player.guild.id = player.guild_member.guild_id ORDER BY level DESC LIMIT 5");
  6. $info->execute();
  7.  
  8. echo "<table style='border: 1px solid;'>";
  9.  
  10. while($row = $info->fetch(PDO::FETCH_ASSOC))
  11. {
  12. if(!empty($row['guild_name']))
  13. {
  14. $guild_name = $row['guild_name'];
  15. }
  16. else
  17. {
  18. $guild_name = "(Brak)";
  19. }
  20.  
  21. echo "<tr>";
  22. echo "<td>".$row['name']."</td>";
  23. echo "<td>".$row['level']."</td>";
  24. echo "<td>".$guild_name."</td>";
  25. echo "<td>".$row['playtime']."</td>";
  26. echo "<td>".$row['last_play']."</td>";
  27. echo "</tr>";
  28. }
  29.  
  30. echo "</table>";
  31.  
  32. }


Najbardziej przekonuje mnie: http://www.phpfastcache.com/ jednak kompletnie nie wiem jak to zastosować w tej funkcji. Na ich stronie są przykłady jednak nie za bardzo wiem o co w nich biega.
Mam jeszcze 1 problem, w tej funkcji jest zapytanie które ma wyszukać dane graczy. Chciałbym aby wyszukał wszystkich graczy a nie tylko tych co są w gildii.

Byłbym bardzo wdzięczny gdybyś pokazał mi na przykładzie tej funkcji jak zastosować ten system cache.
Go to the top of the page
+Quote Post
Rysh
post
Post #4





Grupa: Zarejestrowani
Postów: 821
Pomógł: 111
Dołączył: 11.09.2006
Skąd: Biała Podlaska

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


Którego dokładnie nie rozumiesz?
  1. <?php
  2. use phpFastCache\CacheManager;
  3. // auto, redis, cookie, files, sqlite, xcache, memcache, apc, memcached, wincache
  4.  
  5. $config = array(
  6. "storage" => "files",
  7. "path" => "/path/dir/to/your/cache",
  8. );
  9. CacheManager::setup($config);
  10. CacheManager::CachingMethod("phpfastcache");
  11.  
  12. $cache = CacheManager::getInstance();
  13.  
  14. // The getter, obviously, return your cache object
  15. $cache->get($keyword);
  16.  
  17. // The setter, for those who missed it, put 0 meant cache it forever
  18. $cache->set($keyword, $something_your_want_to_cache, $time_as_second = 0);
  19. ?>
Go to the top of the page
+Quote Post
Gruchol
post
Post #5





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 28.11.2014

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


Ten phpFastCache bez użycia nawet wywala mi mnóstwo błędów w dodatku chyba nie obsługuje zapytań mysqla.
Możesz polecić jakąś łatwą do ogarnięcia na początek bibliotekę?
Go to the top of the page
+Quote Post
daro0
post
Post #6





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

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


No przecież można sobie napisać tylko prostą funkcję, po co od razu jakieś klasy:

https://kohanaframework.org/3.2/guide/api/Kohana_Core#cache

I jako data daje się tą tablicę którą zwróci zapytanie, nastąpi serializacja i zapis do pliku tekstowego, następnie odczyt i sprawdzanie po dacie i godzinie ostatniej modyfikacji czy jest ważna, jeśli tak to odczyt i deserializacja. Co w tym takiego trudnego?


Go to the top of the page
+Quote Post
Gruchol
post
Post #7





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 28.11.2014

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


Próbowałem napisać swoją funkcję ale to chyba nie ma sensu.
Wyszło mi coś takiego (nie działa warunek z time())

  1. global $db;
  2.  
  3. $file_name = "cache.txt";
  4. if(filemtime($file_name) > time() + 1*60)
  5. {
  6. $query_to_cache = $db->query("SELECT player.player.id, player.player.name, player.player.level, player.player.playtime, player.player.last_play, player.guild.name AS 'guild_name' FROM player.player, player.guild, player.guild_member WHERE player.player.id = player.guild_member.pid AND player.guild.id = player.guild_member.guild_id ORDER BY level DESC LIMIT 5");
  7. $query_to_cache->execute();
  8. $query_to_cache = $query_to_cache->fetch(PDO::FETCH_ASSOC);
  9.  
  10. $fp = fopen($file_name, 'w');
  11. fwrite($fp, print_r($query_to_cache, TRUE));
  12. fclose($fp);
  13. }


Jednak to nie ma sensu ;/
Bardzo bym prosił o pokazanie na przykładzie tego:

  1. function DisplayRanking()
  2. {
  3. global $db;
  4.  
  5. $info = $db->query("SELECT player.player.id, player.player.name, player.player.level, player.player.playtime, player.player.last_play, player.guild.name AS 'guild_name' FROM player.player, player.guild, player.guild_member WHERE player.player.id = player.guild_member.pid AND player.guild.id = player.guild_member.guild_id ORDER BY level DESC LIMIT 5");
  6. $info->execute();
  7.  
  8. echo "<table style='border: 1px solid;'>";
  9.  
  10. while($row = $info->fetch(PDO::FETCH_ASSOC))
  11. {
  12. if(!empty($row['guild_name']))
  13. {
  14. $guild_name = $row['guild_name'];
  15. }
  16. else
  17. {
  18. $guild_name = "(Brak)";
  19. }
  20.  
  21. echo "<tr>";
  22. echo "<td>".$row['name']."</td>";
  23. echo "<td>".$row['level']."</td>";
  24. echo "<td>".$guild_name."</td>";
  25. echo "<td>".$row['playtime']."</td>";
  26. echo "<td>".$row['last_play']."</td>";
  27. echo "</tr>";
  28. }
  29.  
  30. echo "</table>";
  31.  


jak cachować to zapytanie i później wyświetlać to w tabeli.
Niestety ciężko mi cokolwiek zrozumieć do czasu aż nie zobaczę czegoś na "żywym" przykładzie.
Oczywiście to nie jest jedyna funkcja którą będę musiał cachować, chcę na jej przykładzie zobaczyć tylko jak to działa.

Ogarnąłem już to cachowanie, bo znalazłem bardzo prostą bibliotekę.
Funkcja zwraca mi aktualnie tablice w tym stylu $dane[1][id];
I jak z takiej tablicy wyszukać dane po np. nazwie a nie po numerze tablicy?
Chodzi mi o coś w stylu $dane["Zenek"]["id"], czyli wyciągam id gracza Zenek.


Ten post edytował Gruchol 25.07.2016, 18:52:31
Go to the top of the page
+Quote Post
daro0
post
Post #8





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

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


No to masz tu (ale nie sprawdzałem działania kodu), może to zrozumiesz. I nie licz na gotowce, zresztą ograniczyłem tylko do jednego rekordu.

  1. define('DOCROOT', realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR);
  2.  
  3. function DisplayRanking()
  4. {
  5. //najpierw sprawdzanie czy cache jest, jesli nie to pobieranie z bazy i zapis do cache
  6. if (($row = load_cache('ranking', 60)) === NULL)
  7. {
  8. $db = new PDO('mysql:host=localhost;dbname=test', 'root', 'qwerty123');
  9. $stmt = $db->prepare("SELECT player.player.id, player.player.name,
  10. player.player.level, player.player.playtime,
  11. player.player.last_play, player.guild.name AS 'guild_name'
  12. FROM player.player, player.guild, player.guild_member
  13. WHERE player.player.id = player.guild_member.pid
  14. AND player.guild.id = player.guild_member.guild_id
  15. ORDER BY level DESC LIMIT 1");
  16. $stmt->execute();
  17.  
  18. // jesli cokolwiek jest w bazie to zapis
  19. if ($row = $stmt->fetch(PDO::FETCH_OBJ))
  20. {
  21. save_cache('ranking', $row);
  22. }
  23. }
  24.  
  25. //jesli cokolwiek jest to wyswietl w tabeli
  26. if ($row)
  27. {
  28. display($row);
  29. }
  30.  
  31. }
  32.  
  33. function display($row)
  34. {
  35. echo "<table>";
  36.  
  37. if(!empty($row->guild_name))
  38. {
  39. $guild_name = $row->guild_name;
  40. }
  41. else
  42. {
  43. $guild_name = "(Brak)";
  44. }
  45.  
  46. echo "<tr>";
  47. echo "<td>".$row->name."</td>";
  48. echo "<td>".$row->level."</td>";
  49. echo "<td>".$guild_name."</td>";
  50. echo "<td>".$row->playtime."</td>";
  51. echo "<td>".$row->last_play."</td>";
  52. echo "</tr>";
  53.  
  54. echo "</table>";
  55. }
  56.  
  57. function save_cache($name, $data)
  58. {
  59. $file = sha1($name).'.cache';
  60. $dir = DOCROOT . 'cache' . DIRECTORY_SEPARATOR;
  61.  
  62. $data = serialize($data);
  63. return (bool) file_put_contents($dir.$file, $data, LOCK_EX);
  64.  
  65. }
  66.  
  67. function load_cache($name, $lifetime = 60)
  68. {
  69. $file = sha1($name).'.cache';
  70. $dir = DOCROOT . 'cache' . DIRECTORY_SEPARATOR;
  71.  
  72. // cache wazna jesli aktualny czas time() - czas ostatniej modyfikacji pliku
  73. // jest mniejszy od czasu zycia w sekundach
  74. if (is_file($dir.$file))
  75. {
  76. if ((time() - filemtime($dir.$file)) < $lifetime)
  77. {
  78. return unserialize(file_get_contents($dir.$file));
  79. }
  80. else // jesli nie, to usuwanie pliku jesli jest
  81. {
  82. unlink($dir.$file);
  83. }
  84. }
  85.  
  86. return NULL;
  87. }
  88.  
  89. // i wywolanie glownej funkcji
  90. DisplayRanking();
  91.  


Przeanalizuj to sobie jak to wszystko działa.

Ten post edytował daro0 27.07.2016, 05:44:11
Go to the top of the page
+Quote Post
Gruchol
post
Post #9





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 28.11.2014

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


Tutaj lekko poprawiłem warunek bo wyrzucało błąd, że nie ma pliku:

  1. function load_cache($name, $lifetime = 60)
  2. {
  3. $file = sha1($name).'.cache';
  4. $dir = DOCROOT . 'cache' . DIRECTORY_SEPARATOR;
  5.  
  6. // cache wazna jesli aktualny czas time() - czas ostatniej modyfikacji pliku
  7. // jest mniejszy od czasu zycia w sekundach
  8. if (file_exists($dir.$file) AND (time() - filemtime($dir.$file)) < $lifetime)
  9. {
  10. return unserialize(file_get_contents($dir.$file));
  11. }
  12. elseif(file_exists($dir.$file)) // jesli nie, to usuwanie pliku jesli jest
  13. {
  14. unlink($dir.$file);
  15. }


Teraz próbuje przerobić aby wkładało wszystkie rekordy a nie tylko jeden lecz już nie mam pojęcia co z tym zrobić.
Próbowałem tak:
  1. while($row = $stmt->fetch(PDO::FETCH_ASSOC))
jednak nic nie chce ruszyć.

Ten post edytował Gruchol 26.07.2016, 21:42:58
Go to the top of the page
+Quote Post
daro0
post
Post #10





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

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


Sam zauważyłem ten błąd i też poprawiłem.

  1.  
  2. $query = "SELECT player.player.id, player.player.name,
  3. player.player.level, player.player.playtime,
  4. player.player.last_play, player.guild.name AS 'guild_name'
  5. FROM player.player, player.guild, player.guild_member
  6. WHERE player.player.id = player.guild_member.pid
  7. AND player.guild.id = player.guild_member.guild_id
  8. ORDER BY level DESC LIMIT 5";
  9.  
  10. if (($rows = load_cache($query, 60)) === NULL)
  11. {
  12. $db = new PDO('mysql:host=localhost;dbname=test', 'root', 'qwerty123');
  13. $stmt = $db->prepare($query);
  14. $stmt->execute();
  15.  
  16. $rows = $stmt->fetchAll(PDO::FETCH_CLASS, "stdClass");
  17. save_cache($query, $rows);
  18.  
  19. }
  20.  
  21. if ($rows !== NULL)
  22. {
  23. foreach ($rows as $row)
  24. {
  25. // wyswietlasz kazdy wiersz
  26. }
  27. }
  28.  


http://php.net/manual/en/pdostatement.fetchall.php

Zwróć uwagę że otrzymasz tablicę obiektów typu stdClass a jako nazwa cache powinno być to zapytanie, dlatego też zrobiłem inaczej.

Ten post edytował daro0 27.07.2016, 06:09:22
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 12.10.2025 - 22:47