Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SQL][PHP] Spawdzenie kodu
Forum PHP.pl > Forum > Przedszkole
julek12
Witam,
Czy mógłby ktoś przejrzeć kod i wytknąć mi moje błędy?

  1. <?php
  2. /**
  3.  * TibiaServ
  4.  * Website: http://tibiaserv.pl
  5.  *
  6.  * @author Juliusz Marciniak <juliusz.marciniak@gmail.com>
  7.  * @date 20.10.2009
  8.  * @version 0.1
  9.  * @copyright Copyright (c) 2009 Juliusz Marciniak, All Rights Reserved
  10.  */
  11.  
  12. class Pdo_Database_Engine
  13. {
  14. /**
  15. * Connection to the database.
  16. *
  17. * @access public
  18. * @param string The database DSN.
  19. * @param string The database username. (depends on DSN)
  20. * @param string The database user's password. (depends on DSN)
  21. * @param array The databases driver options (optional)
  22. * @return boolean True on success
  23. */
  24. public function __construct($db_dsn, $db_login = '', $db_password = '', $db_driver_options = array())
  25. {
  26. try
  27. {
  28. $this -> pdo = new PDO($db_dsn, $db_login, $db_password, $db_driver_options);
  29. }
  30. catch(PDOException $exception)
  31. {
  32. die('Connection failed: <br /><b>' . $exception -> getMessage() . '</b>');
  33. }
  34. $this -> pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  35.  
  36. return true;
  37. }
  38.  
  39. /**
  40. * Performs a simple select query.
  41. *
  42. * @access public
  43. * @param string The table name to be queried.
  44. * @param string List of fields to be selected.
  45. * @param string SQL formatted list of conditions to be matched.
  46. * @param array List of options: bind, order by, limit and fetch_array
  47. */
  48. public function query_select($table, $fields = '*', $conditions = '', $options = array())
  49. {
  50. $query = 'SELECT ' . $fields . ' FROM ' . $table;
  51.  
  52. if ($conditions != '')
  53. {
  54. $query .= ' WHERE ' . $conditions;
  55. }
  56.  
  57. if (isset($options['order_by']))
  58. {
  59. $query .= ' ORDER BY ' . $options['order_by'];
  60. }
  61.  
  62. if (isset($options['limit']))
  63. {
  64. $query .= ' LIMIT ' . $options['limit'];
  65. }
  66.  
  67. if (isset($options['bind']))
  68. {
  69. $bind = $options['bind'];
  70. $query = $this -> pdo -> prepare($query);
  71. foreach($bind as $parameter => $value)
  72. {
  73. if (is_array($value))
  74. {
  75. $query -> bindValue($parameter, $value[0], $value[1]);
  76. }
  77. else
  78. {
  79. $query -> bindValue($parameter, $value);
  80. }
  81. }
  82. $query -> execute();
  83. }
  84. else
  85. {
  86. $query = $this -> pdo -> query($query);
  87. }
  88.  
  89. if (isset($options['fetch_array']))
  90. {
  91. if (is_array($options['fetch_array']))
  92. {
  93. $fetch_array = $options['fetch_array'];
  94. return $this -> fetch_array($query, $fetch_array['fetch_style']);
  95. }
  96. else
  97. {
  98. return $this -> fetch_array($query);
  99. }
  100. }
  101. else
  102. {
  103. return $query;
  104. }
  105. }
  106.  
  107. public function fetch_array($query, $fetch_style = PDO::FETCH_BOTH)
  108. {
  109. if (!is_object($query))
  110. {
  111. return '<b>Warning: Invalid argument</b>';
  112. }
  113.  
  114. $fetch_array = $query -> fetch($fetch_style);
  115.  
  116. return $fetch_array;
  117. }
  118.  
  119. /**
  120. * The end of the connection to the database.
  121. *
  122. * @access public
  123. * @return boolean True on success
  124. */
  125. public function __destruct()
  126. {
  127. $this -> pdo = null;
  128.  
  129. return true;
  130. }
  131. }
  132. ?>


Później wykorzystuje to na przykład tak:
  1. $a = new Pdo_Database_Engine('mysql:dbname=test;host=localhost', 'xxx', 'xxx', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
  2.  
  3. $b = $a -> query_select('`bany`', '*', '`typ` = :typ AND `asdasd` = :asdasd', array('fetch_array' => array(true, 'fetch_style' => PDO::FETCH_ASSOC), 'bind' => array(':typ' => array(2, PDO::PARAM_INT), ':asdasd' => 2)));
  4. print_r($b);

Początek mam dobrze, bo patrzyłem z manuala, chodzi mi o te 2 metody.
vokiel
Po pierwsze rezygnujesz z obsługi wyjątków (masz PDOException, a zamieniasz to na die() ), co oznacza cofnięcie się.

Po drugie zastosowanie tego jest bardziej problematyczne niż samego PDO. Niby zamiast 5-ciu linii kodu masz jedną, tylko czytelność jest o wiele mniejsza.

Przydałoby się dorobić sprawdzanie podanych parametrów. Bo przykładowo, jeśli ktoś się pomyli i w zmiennej $fields czy $conditions przekaże tablicę pól? Twój skrypt się wysypie i to niezłapanym wyjątkiem PDO.


Może i Tobie w jakiś sposób to ułatwi pracę, znasz dokładnie strukturę kodu, wiesz co możesz podać w parametrach, czego nie. IMHO ktokolwiek chciałby użyć tej "klasy" w swoich projektach to mógłby się zdziwić i łatwo zdenerwować.

Według mnie taka klasa nie ma zastosowania, jest niepotrzebna, wprowadza tylko niepotrzebny zamęt. W przypadku rozwoju Twojego kodu przez kogoś innego - będzie miał z tym problem. W przypadku rozwoju cudzego kodu przez Ciebie - będziesz miał doświadczenie, nawyki z rozwiązaniem nigdzie nie stosowanym, a braki w tych powszechnych.

Widzę, że chciałeś na szybko zrobić coś a'la ORM. Lepiej już chyba zastosować Doctrine/Propel niż robić takie kwiatki.

Ale to tylko moje subiektywne zdanie winksmiley.jpg
julek12
czyli tu:
  1. die('Connection failed: <br /><b>' . $exception -> getMessage() . '</b>');

wstawić echo zamiast die tak?

Klasa będzie wykorzystywana tylko przeze mnie.
A co do nieczytelnego kodu to był tylko przykład normalnie robie sobie takie coś:
  1. $b = $a -> query_select(
  2. '`bany`', // tabela
  3. '*', // pola
  4. '`typ` = :typ AND `asdasd` = :asdasd', // warunki
  5. 'fetch_array' => array(true, 'fetch_style' => PDO::FETCH_ASSOC), //czy zastosować fetch
  6. 'bind' => array(':typ' => array(2, PDO::PARAM_INT), ':asdasd' => 2) // bindowanie parametrów
  7. )
  8. );
vokiel
Żadnego echo w klasach. Exception, myślisz czemu takie PDO nie korzysta echo tylko PDOException?
Jeśli zechcesz pobrać dane do zmiennej, a zmienną użyć gdzieś dalej w kodzie, to jeśli masz echo to popsuje Ci to skrypt. Exception wyłapujesz a wyświetlasz kiedy chcesz i jeśli chcesz.

Jeśli tylko Ty, to robisz tak jak jest Tobie najwygodniej. Ja bym np dał możliwość podawania pól jako tablicę, a nie tylko jako ciąg. Może się przecież zdarzyć, że listę pól pobierzesz z bazy i będziesz miał jako tablicę. Lepiej to oprogramować w klasie raz niż za każdym razem w skrypcie.
  1. // konstruktor
  2. try{
  3. $this -> pdo = new PDO($db_dsn, $db_login, $db_password, $db_driver_options);
  4. }catch(PDOException $exception){
  5. throw new Exception('Connection failed: <br /><b>' . $exception -> getMessage() . '</b>');
  6. }
julek12
To nie będzie działać:
  1. throw new Exception('Connection failed: <br /><b>' . $exception -> getMessage() . '</b>');


ponieważ to catch łapie te throw new Exception, a tu:
  1. catch(PDOException $exception)
  2. {
  3. ...
  4. }


je wyświetla więc musi być tu coś do wyświetlanie tych wyjątków print, echo, return. I teraz co z tego użyć return?
vokiel
Cytat
To nie będzie działać:
Jesteś pewien?

Chyba nie poczytałeś o wyjątkach. Kod który podałem:
1. Łapie PDOException jeśli wystąpi
2. Pobiera tekstowy opis wyjątku ($exception -> getMessage())
3. Wyrzuca własny (Exception) wyjątek, który możesz wyłapać dalej w kodzie

Np:
  1. try{
  2. $a = new Pdo_Database_Engine('mysql:dbname=test;host=localhost', 'xxx', 'xxx', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
  3.  
  4. $b = $a -> query_select('`bany`', '*', '`typ` = :typ AND `asdasd` = :asdasd', array('fetch_array' => array(true, 'fetch_style' => PDO::FETCH_ASSOC), 'bind' => array(':typ' => array(2, PDO::PARAM_INT), ':asdasd' => 2)));
  5. print_r($b);
  6.  
  7. }catch(Exception $e){
  8. echo $e->getMessage();
  9. }
julek12
zastosowałem twój kod i działa.
i zmieniłem to:
  1. $query = 'SELECT ' . $fields . ' FROM ' . $table;

na to:
  1. if (is_array($fields))
  2. {
  3. $query = 'SELECT ' . implode(', ', $fields) . ' FROM ' . $table;
  4. }
  5. else
  6. {
  7. $query = 'SELECT ' . $fields . ' FROM ' . $table;
  8. }


Dobrze?
vokiel
No tak już lepiej:)

Konstruktor niepotrzebnie zwraca true, możesz to usunąć. Poza tym i tak obejmujesz to w blok try - catch. Więc jeśli nie wystąpi wyjątek - znaczy, że wszystko jest ok. (btw. konstruktor nic nie zwraca)

A skoro już wrzucasz to w blok try-catch, to może zmień też tutaj:
  1. if (!is_object($query)){
  2. //return '<b>Warning: Invalid argument</b>';
  3. throw new Exception('<b>Warning: Invalid argument</b>');
  4. }
julek12
W destruktor coś zwraca czy nie?
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.