Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Optymalizacja klasy, jak?
Forum PHP.pl > Forum > PHP > Object-oriented programming
mijagi
Napisałem ostatnio u siebie na blogu klase uploadującą jeden plik. Dodam, że głównie skupiałem się na bezpieczeństwie. Są osoby, które twierdzą, że ta klasa to "struktura w obiekcie". Chciałbym się dowiedzieć jak napisać taka klase lepiej, chodzi mi o wskazówki. Z góry dziex!
Tutaj klasa :

  1. <?php
  2. ##################
  3. # autor : mijagi #
  4. ##################
  5. class uploadzik {
  6. public $rozmiar_max;
  7. public $rozszerzenia = array();
  8. public $typy_mime = array();
  9. public $nazwa_input;
  10.  
  11. private $nazwa_tmp;
  12. private $typ_mime;
  13. private $nazwa;
  14. private $rozmiar;
  15. private $bledy;
  16.  
  17. public function __construct($rozmiar_max, $rozszerzenia, $typy_mime, $nazwa_input){
  18. if(isset($_FILES[$nazwa_input]) && is_array($_FILES[$nazwa_input])){
  19. if(!is_array($_FILES[$nazwa_input]['tmp_name']) && !is_array($_FILES[$nazwa_input]['name']) && !is_array($_FILES[$nazwa_input]['size']) && !is_array($_FILES[$nazwa_input]['error']) && !is_array($_FILES[$nazwa_input]['type'])){
  20. $this->nazwa_tmp = $_FILES[$nazwa_input]['tmp_name'];
  21. $this->typ_mime = $_FILES[$nazwa_input]['type'];
  22. $this->nazwa = $_FILES[$nazwa_input]['name'];
  23. $this->rozmiar = $_FILES[$nazwa_input]['size'];
  24. $this->bledy = $_FILES[$nazwa_input]['error'];
  25. }
  26.  
  27. }
  28.  
  29. if($this->sprawdzanie($rozmiar_max) == 1){
  30. if(is_array($rozszerzenia) && is_array($typy_mime)){
  31. $znaki = strlen($nazwa_input);
  32. if($znaki > 1 && $znaki < 5){
  33. $this->rozmiar_max = $rozmiar_max;
  34. $this->rozszerzenia = $rozszerzenia;
  35. $this->typy_mime = $typy_mime;
  36. $this->nazwa_input = $nazwa_input;
  37. $this->druk_input($this->ile_plikow);
  38. }else $this->komunikaty(4);
  39. }else $this->komunikaty(2);
  40. }else $this->komunikaty(3);
  41. } #<- konstruktor, sprawdzenie czy obiekt zostanie poprawnie utworzony
  42.  
  43. private function sprawdzanie($x){
  44. if(isset($x)){
  45. if(is_numeric($x) && is_int($x)){
  46. return 1;
  47. }
  48. }
  49. } #<- funkcja pomagajaca konstruktorowi sprawdzic poprawnosc danych
  50.  
  51. private function komunikaty($ktory){
  52. if(isset($ktory)){
  53. switch($ktory)
  54. {
  55. case 1:
  56. echo "Brak pliku";
  57. break;
  58.  
  59. case 2:
  60. echo "Bledna wartosc dla rozszerzenia lub mime";
  61. break;
  62.  
  63. case 3:
  64. echo "Bledna wartosc dla rozmiaru";
  65. break;
  66.  
  67. case 4:
  68. echo "Bledna wartosc dla nazwy inputa";
  69. break;
  70.  
  71. case 5:
  72. echo "Pliki o tym rozszerzeniu nie sa dopuszczalne";
  73. break;
  74.  
  75. case 6:
  76. echo "Bledna wartosc zmiennej";
  77. break;
  78.  
  79. case 7:
  80. echo "Zly wybor";
  81. break;
  82.  
  83. case 8:
  84. echo "Plik nie jest obrazkiem";
  85. break;
  86.  
  87. default:
  88. echo "Nieznany blad";
  89. break;
  90. }
  91. }
  92. } #funkcja drukujaca info o bledzie
  93.  
  94. private function druk_input($ile){
  95. echo "<form action=\"\" method=\"POST\" enctype=\"multipart/form-data\">
  96. <input name=\"$this->nazwa_input\" type=\"file\" /><br />
  97. <input type=\"radio\" name=\"wybor\" value=\"zdjecie\"/>Fotka
  98. <input type=\"radio\" name=\"wybor\" value=\"archiwum\" />Zip/rar<br/>
  99. <input type=\"submit\" name=\"submit\" value=\"up up!\"/></form>";
  100. } #funkcja drukujaca formularz
  101.  
  102. private function rozszerzenie($roz){
  103. if(!is_array($roz)){
  104. $ext = substr($roz,strrpos($roz,'.')+1);
  105. return $ext;
  106. }
  107. } #funkcja sprawdzajaca rozszerzenia
  108.  
  109. private function mimy($mime){
  110. if(in_array($mime, $this->typy_mime)){
  111. return 1;
  112. }
  113. }#funkcja sprawdzajaca mime
  114.  
  115. private function wybor($wybor){
  116. if(!empty($wybor)){
  117. if(!is_array($wybor)){
  118. switch($wybor)
  119. {
  120. case 'zdjecie':
  121. return 1;
  122. break;
  123.  
  124. case 'archiwum':
  125. return 2;
  126. break;
  127.  
  128. default:
  129. return 3;
  130. break;
  131. }
  132. }else $this->komunikaty(6);
  133. }else $this->komunikaty(6);
  134. } #funkcja odpowiada za poprawnosc przypisania sprawdzania danych do zmiennej wybor
  135.  
  136. private function rozmiar_pliku($rozmiar){
  137. if($rozmiar <= $this->rozmiar_max){
  138. return 1;
  139. }
  140. } #funkcja sprawdzajaca rozmiar pliku
  141.  
  142. private function GD_img($tmp){
  143. $image = @getimagesize($tmp);
  144. if(is_array($image) && $image[0] > 2){
  145. return 1;
  146. }
  147. } #sprawdzanie czy obraz jest poprawny w GD
  148.  
  149. private function zmiana_nazwy($nazwa){
  150. $nazwa = 'upload/'.md5(time()).'-'.$_SERVER['REMOTE_ADDR'].'-.'.$this->rozszerzenie($this->nazwa);
  151. return $nazwa;
  152. } #zmiana nazwy wg. wzoru
  153.  
  154. private function info($x){
  155. if($x){
  156. echo 'Na serwer przeslano plik "'.$this->nazwa.'". O rozmiarze: '.$this->rozmiar.' bajtow.';
  157. }
  158. } # drukowanie info, jesli wszystko sie powiodlo
  159.  
  160. public function up_up(){
  161. if(isset($_POST['submit']) && !is_array($_POST['submit'])){
  162. if($this->wybor($_POST['wybor']) < 3){
  163. if(is_uploaded_file($this->nazwa_tmp)){
  164. if($this->rozmiar_pliku($this->rozmiar) == 1){
  165. if($this->wybor($_POST['wybor']) == 1){
  166. if(in_array($this->rozszerzenie($this->nazwa),$this->rozszerzenia[0])){
  167. if(in_array($this->typ_mime,$this->typy_mime[0])){
  168. if($this->GD_img($this->nazwa_tmp) == 1){
  169. $uped = move_uploaded_file($this->nazwa_tmp, $this->zmiana_nazwy($this->nazwa));
  170. $this->info($uped);
  171. }else echo $this->komunikaty(8);
  172. }else echo $this->komunikaty(2);
  173. }else echo $this->komunikaty(2);
  174. }elseif($this->wybor($_POST['wybor']) == 2) {
  175. if(in_array($this->rozszerzenie($this->nazwa),$this->rozszerzenia[1])){
  176. if(in_array($this->typ_mime,$this->typy_mime[1])){
  177. $uped = move_uploaded_file($this->nazwa_tmp, $this->zmiana_nazwy($this->nazwa));
  178. $this->info($uped);
  179. }else echo $this->komunikaty(2);
  180. }else echo $this->komunikaty(2);
  181. }
  182. }else echo $this->komunikaty(2);
  183. }else $this->komunikaty(1);
  184. }else $this->komunikaty(6);
  185. }
  186. } #funkcja odpowiadajaca za sprawdzenie danych pliku i upload jesli wszystko gra
  187.  
  188.  
  189. }
  190.  
  191.  
  192. $rozmiar = 6291456; #max rozmiar pliku
  193. $nazwa = 'plik'; #nazwa inputa
  194.  
  195. $roz_fot = array("jpg","png","gif"); #rozszerzenia dla obrazka
  196. $roz_arch = array("zip","rar"); #rozszerzenia dla zip/rar
  197.  
  198.  
  199. $mime_fot = array("image/gif","image/jpeg","image/png","image/jpg"); #typy mime dla obrazka
  200. $mime_arch = array("application/zip","application/rar","application/x-compressed","application/x-zip-compressed","multipart/x-zip"); #typy mime dla rar/zip
  201.  
  202. #dalej palcow nie pchaj
  203. $typy_mime = array($mime_fot,$mime_arch);
  204. $rozszerzenia = array($roz_fot,$roz_arch);
  205. $up = new uploadzik($rozmiar,$rozszerzenia,$typy_mime,$nazwa);
  206. $up->up_up();
  207. ?>
golaod
Wywal klasę i napisz od początku. Na pewno będzie zoptymalizowana. Zero przemyślenia wygląda jakbyś po prostu jedną funkcję na sztywno podzielił na kilka metod i myślał, że to jest świetna klasa.

Po co dajesz komuś w formularzu wybór tego co wysyła ? On ma po prostu coś wysłać, a ty masz sprawdzić na miejscu jakie ma rozszerzenie i rozmiar. Btw. jeszcze jest np. rozszerzenie jpEg, tar, tar.gz, gz itp itd.
Dalej lecąc to po co mieszasz angielski z polskim ?
nazwa_tmp, typy_mime i nagle jeszcze mimY - WTF? co to jest up_up ?

Nie wiem czemu jednak osobiście jestem zrażony gdy widzę echo "coś" w metodzie klasy nie bardzo mi się to podoba chyba, że jest pod parametrem
  1. function metoda( $output = false ) {
  2.  
  3. if( ! $output ) {
  4. return "coś";
  5. }
  6. echo "coś";
  7.  
  8. }


Metoda komunikaty w ogóle nie jest przydatna. Zrobić metodę tylko po to by użyć switcha dla komunikatu błędu ?
Nie będę Ci pisać jak pisać swoje klasy. Polecam po prostu poczytać kod i zobaczyć jak to inni robią. Zrozumiesz wtedy, że konstrukcja konkretnej jednej Twojej metode jest rozbity na inne bardziej przejrzyste i lepsze jeśli chodzi o inną funkcjonalność( dodatkową )
mijagi
Cytat
Wywal klasę i napisz od początku. Na pewno będzie zoptymalizowana. Zero przemyślenia wygląda jakbyś po prostu jedną funkcję na sztywno podzielił na kilka metod i myślał, że to jest świetna klasa.

Gdybym tak myślał to bym to nie przyszedl z prośbą o porady tongue.gif
Fakt z rozszerzeniami tar.gz, byłby problem, ze względu, że szukam ostatniej kropki.
Specjalnie dalem komentarze w tablicach z rozszerzeniami i mime, żeby user to rozszerzył sobie jeśli chce, a co do "jpEg" to mogłem najpierw użyć funkcji strlower - dzieki tongue.gif

Btw, nie czepiajcie sie nazw chciałbym się dowiedzieć czegos jak poprawic ten kod, nazwy naprawde sa tu nieistotne.
erix
  1. if(isset($_POST['submit']) && !is_array($_POST['submit'])){
  2. if($this->wybor($_POST['wybor']) < 3){
  3. if(is_uploaded_file($this->nazwa_tmp)){
  4. if($this->rozmiar_pliku($this->rozmiar) == 1){
  5. if($this->wybor($_POST['wybor']) == 1){
  6. if(in_array($this->rozszerzenie($this->nazwa),$this->rozszerzenia[0])){
  7. if(in_array($this->typ_mime,$this->typy_mime[0])){
  8. if($this->GD_img($this->nazwa_tmp) == 1){
  9. $uped = move_uploaded_file($this->nazwa_tmp, $this->zmiana_nazwy($this->nazwa));
  10. $this->info($uped);
  11. }else echo $this->komunikaty(8);
  12. }else echo $this->komunikaty(2);
  13. }else echo $this->komunikaty(2);
  14. }elseif($this->wybor($_POST['wybor']) == 2) {
  15. if(in_array($this->rozszerzenie($this->nazwa),$this->rozszerzenia[1])){
  16. if(in_array($this->typ_mime,$this->typy_mime[1])){
  17. $uped = move_uploaded_file($this->nazwa_tmp, $this->zmiana_nazwy($this->nazwa));
  18. $this->info($uped);
  19. }else echo $this->komunikaty(2);
  20. }else echo $this->komunikaty(2);
  21. }
  22. }else echo $this->komunikaty(2);
  23. }else $this->komunikaty(1);
  24. }else $this->komunikaty(6);
  25. }

O wyjątkach, to nie słyszałeś? Czytelność kodu jest fatalna, wszystko można by było zgrabnie zrobić.

  1. }else $this->komunikaty(4);

Hmm, ciekawe co zrobisz, gdy zechcesz rozbudować klasę i dodać nowe komunikaty o błędach, zobaczymy, do jakiego momentu się nie pogubisz. biggrin.gif Już nawet PHP dla $_FILES['file']['error'] używa STAŁYCH, a nie surowych kodów numerycznych.

  1. private function rozszerzenie($roz){
  2. if(!is_array($roz)){
  3. $ext = substr($roz,strrpos($roz,'.')+1);
  4. return $ext;
  5. }
  6. }

A o pathinfo nie słyszał? biggrin.gif

  1. private function GD_img($tmp){
  2. $image = @getimagesize($tmp);
  3. if(is_array($image) && $image[0] > 2){
  4. return 1;
  5. }
  6. }

A teraz patrz na dokumentację:
Cytat
The getimagesize() function does not require the GD image library.


Co jeszcze?
  1. Szkoda, że nie masz żadnej obsługi uploadu wielu plików zapisanych jako tablica; trzeba dla każdego ręcznie z osobna.
  2. brak phpDoc
  3. nazewnictwo nieco dziwne; ani intuicyjne, ani konsekwentne - w jednym miejscu masz up_up, w drugim mimy, że tylko Ty wiesz, o co chodzi. tongue.gif
  4. za bardzo strukturalny, aż prosi się o wyjątki, a Ty robisz drzewko warunków
  5. komunikaty o błędzie lepiej zwracać właśnie przez wyjątki
  6. jak mam z poziomu skryptu sprawdzić, czy upload się powiódł? Żadnego return, o wyjątku z odpowiednim kodem błędu nie wspomnę

Poczytaj trochę o programowaniu obiektowym, bo na razie to jest tylko strukturalny ubrany w inne nazwy zmiennych...
cojack
A co te public $zmienna robią? Nie słyszał Pan o zasadzie hermetyzacji?
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.