Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Dostęp destroktora do unset()
Athlan
post
Post #1





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Realizując projekt przyszła mi potrzeba dopisania pewnej klasy do mojego frameworka. Mianowicie, ma ona przechwycić plik uploadowany z podanego pola i skopiować go do plików tymczasowych frameworka. Stamtąd może wyciągać informacje o nim. Po zuploadowaniu klasa może przyjąc plik w inne miejsce metodą publiczną copy(). Nie będę jednak opisywał działania klasy, ale przedstawię główne zadanie:

Skopiować plik do folderu plików tymczasowych framework ( /application/var/ ) przy konstruktorze i skasować go w destruktorze.

Ostatnio dość irytującą rzeczą stał się fakt, iż desruktor nie może użyć funkcji unlink() (usowania pliku). Gdy wypluję jego ścieżkę za pomocą echo(), wówczas zostanie ona wyświetlona, ba, mogę ją nawet usunąć z buforu funkcją unset(). Patrząc na te aspekty, można stwierdzić, że destruktor ma pełny dostęp do danych przed zniszczeniem instancji klasy. Ok, fajnie, pobierzmy sobie dla funkcji unlink() zmienną którą zwraca metoda $this->_temp() (ścieżka do pliku na którym pracuje sobie klasa. Po zakończeniu prac na pliku, trzeba go usunąć. Zamiast usunięcia pojawia się tajemniczy błąd:

Cytat
Fatal error: Exception thrown without a stack frame in Unknown on line 0


Klasa wygląda mniej więcej tak:

  1. <?php
  2.  
  3. final class Vfile
  4. {
  5. // ...
  6.  
  7. public function __destruct()
  8. {
  9. unlink($this->_temp());
  10. }
  11.  
  12. // ...
  13. }
  14.  
  15. ?>


gdyby wstawić echo(), wypluje nam scieżkę do pliku, ale nie widocznie php nie chce użyć funkcji unlink() w destruktorze.

Coś pominąłem, źle robie? A może destruktor wywoływany jest później niż zamykane są prawa dostępu do pliku (chociaż nielogiczne)? Czy jest jakiś haczyk na mój problem?

btw: to samo mam z obsługą sesji na plikach tekstowych, z bazą danych działa (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Problem rozwiązałem kopjując plik do /var/ mojego frameworka w konstruktorze, zbierając wszystkie informacje i usówając również w konstruktorze. Wszystkie metody zwracają poszczególne informacje... wobec tego destruktor pozostaje bezrobotny (i dobrze), gdyż nie musi usówac pliku, bo zostało to wykonane zaraz po wykonaniu kopii zapasowej przez framework z tempu serwera. Gdy metoda mojej klasy copy() zostanie poproszona o plik, ponownie skopjuje go z tempu serwera juz w docelowe miejsce. Myślę, że połowa z Was powie: "poi co framework kopiuje sobie plik do swojej własnej pamięci?". Szczeże mówiąc sam się zastanawiam (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) może usunę to z mojej klasy (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)

Ostatecznie jednak zdecydowałem się, że nie będę zasmiecał pamięci frameworka... a niech klasa sobie lata do tempu serwewa... Ostatecznie wygląda to tak


  1. <?php
  2.  
  3. final class Vfile
  4. {
  5. private $_sInstance = NULL;
  6. private $_aFilePost = array();
  7. private $_aFileData = array();
  8.  
  9. public function __construct($sPostField)
  10. {
  11. if(!defined("V_VAR"))
  12. throw new VfileException('V_VAR has no defined!');
  13.  
  14. $this->_sInstance = $sPostField;
  15. $this->_aFilePost = $_FILES[$sPostField];
  16.  
  17. $this->_aFileData = $this->_aFilePost;
  18. $this->_aFileData['extension'] = end(explode('.', $this->_aFileData['name']));
  19. $this->_aFileData['temp'] = $this->_aFilePost['tmp_name'];
  20. }
  21.  
  22. public static function posted($sPostField)
  23. {
  24. return (bool) (isset($_FILES[$sPostField]['tmp_name']));
  25. }
  26.  
  27. public function copy($sFilePatch, $sFileName = NULL)
  28. {
  29. $sFileName = ($sFileName) ? $sFileName : $this->name;
  30.  
  31. if(!($bResult = copy($this->temp, $sFilePatch . $sFileName)))
  32. throw new VfileException('I cannot load file "' . $sFileName . '" to directory "' . $sFilePatch . '"!');
  33.  
  34. return $bResult;
  35. }
  36.  
  37. public function __get($sInfoCardKey)
  38. {
  39. return (isset($this->_aFileData[$sInfoCardKey])) ? $this->_aFileData[$sInfoCardKey] : NULL;
  40. }
  41.  
  42. public function info()
  43. {
  44. return $this->_aFileData;
  45. }
  46. }
  47. ?>



Pozdrawiam, Athlan (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Ten post edytował Athlan 14.11.2006, 18:44:41
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Athlan
post
Post #2





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Cytat
Czy twierdzisz tak, bo w Twojej aplikacji coś nie zadziałało?
Napisz najprostszy możliwy test wywołujący unlink() w destruct'orze i zobaczysz, że zadziała - coś innego u Ciebie nie gra.


Zazwyczaj jak mi coś nie działa tworzę testy. Specjalnie dla Ciebie zadedykowałem poniższy kod obrazujący mój pogląd, a raczej fakt istanienia błędu (jeżeli mogę tak to nazwać).

Używam php 5.2.0, pozwoliłem sobie stworzyć kod obrazujący moją teorię i okazało się, że mam rację:

  1. <?php
  2.  
  3. /**
  4.  * Test by Piotr 'Athlan' Pelczar
  5.  * 
  6.  * Klasa pokazuje jakie prawa dostępu do plików ma destruktor i konstruktor
  7.  * 
  8.  * NOTE:
  9.  * 
  10.  * specjalnie została użyta funkcja die() a nie wyjątek, gdyż
  11.  * w destruktorze nie mogą być łapane żadne wyjątki... a przerwanie jego
  12.  * pracy jest konieczne. Udowodnone jest to, że destruktor ma pełne prawa
  13.  * do atrybutu $this->_sFilePatch.
  14.  * 
  15.  * ATTENTION:
  16.  * 
  17.  * przed odpaleniem klasy nalezy stworzyć plik i nadać mu
  18.  * prawa chmod 777 o nazwie/ścieżce podanej w konstruktorze klasy.
  19.  * 
  20.  */
  21.  
  22. // budujemy klasę...
  23. class MyTest
  24. {
  25. private $_sFilePatch = null;
  26.  
  27. public function __construct($sFilePatch)
  28. {
  29. $this->_sFilePatch = $sFilePatch;
  30.  
  31. echo 'constructor said: '.$this->_sFilePatch.'<br />';
  32.  
  33. if(!file_exists($this->_sFilePatch) || !is_writable($this->_sFilePatch))
  34. die('constructor: no usable file');
  35. }
  36.  
  37. public function __destruct()
  38. {
  39. echo 'destructor said: '.$this->_sFilePatch.'<br />';
  40.  
  41. if(!file_exists($this->_sFilePatch) || !is_writable($this->_sFilePatch))
  42. die('destructor: no usable file');
  43.  
  44. unlink($this->_sFilePatch);
  45. }
  46. }
  47.  
  48. // ok odpalamy klasę...
  49. $oMyTest = new MyTest('./file.txt');
  50.  
  51. ?>


Otrzymałem nastepujący rezultat:

Kod
constructor said: ./file.txt
destructor said: ./file.txt
destructor: no usable file


Jak widać... konstruktor w pełni widzi plik (ma do niego dostęp), a destruktor (pomimo tego że używa odpowieniego atrybutu) pliku nie widzi... paradoksalne zjawisko prawda?
Go to the top of the page
+Quote Post

Posty w temacie


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: 2.10.2025 - 17:19