Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Fatal error: Exception thrown without a stack frame in Unknown on line 0, Problem z unique
Jarod
post 11.02.2007, 21:57:05
Post #1





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Mam taki kod (niedokończony ale odczytuje dane z bazy i zapisuje).
  1. <?php
  2.  
  3. require_once('Core/Cube/Session/SessionHandler.interface.php');
  4. require_once('Core/Cube/Session/SessionException.class.php');
  5. require_once('Core/Cube/Database/' . Config::$DbType . '/' . Config::$DbType . '.class.php');
  6.  
  7. class CubeSession implements SessionHandler
  8. {
  9. private $sSessionValues = null;
  10. private $sAddressIp = null;
  11. private $oConnection = null;
  12. private $sLogin = null;
  13.  
  14. public function __construct($oRegistry, $sConnectionName)
  15. {
  16. $this->oConnection = $oRegistry->get($sConnectionName);
  17.  
  18. session_set_save_handler(array(&$this, 'open'), array(&$this, 'close'), array(&$this, 'read'), array(&$this, 'write'), array(&$this, 'destroy'), array(&$this, 'gc'));
  19.  
  20. $this->sAddressIp = $_SERVER['REMOTE_ADDR'];
  21. if (isset($_SESSION['Login'])) $this->sLogin = $_SESSION['Login'];
  22. }
  23.  
  24. public function open($sSessionSavePath, $sSessionName)
  25. {
  26. return true;
  27. }
  28.  
  29. public function close()
  30. {
  31. $this->gc(Config::$SessionMaxLifeTime);
  32. return true;
  33. }
  34.  
  35. public function read($sSessionId)
  36. {
  37. $this->oConnection->query('SELECT sessions_values FROM sessions WHERE sessions_identifier = '' . $sSessionId . ''');
  38. $this->sSessionValues = $this->oConnection->fetchOne();
  39.  
  40. return $this->sSessionValues;
  41. }
  42.  
  43.  
  44. public function write($sSessionId, $aSessionValues)
  45. {
  46. $aInsert = array('sessions_identifier'=>session_id(), 'sessions_time_start'=>'21:15',
  47. 'sessions_last_time' => '21:16', 'sessions_values'=>'serialize','login'=>'dupa', 'address_ip'=>$this->sAddressIp );
  48. @$this->oConnection->insert('sessions', $aInsert);
  49.  
  50.  
  51. echo '<br/>Metoda write() została wywołana<br/>';
  52. }
  53.  
  54. public function destroy($sSessionId){}
  55.  
  56. public function gc($iSessionLifeTime)
  57. {
  58. echo 'Zniszczone';
  59. }
  60.  
  61. }
  62.  
  63.  
  64. ?>


Błąd, który podałem w temacie pojawia się gdy tabela sessions wygląda tak:
  1. CREATE TABLE sessions
  2. (
  3. sessions_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  4. sessions_identifier VARCHAR(32) NOT NULL,
  5. sessions_time_start TIME NOT NULL,
  6. sessions_last_time TIME NOT NULL,
  7. sessions_values TEXT NOT NULL,
  8. login VARCHAR(20),
  9. address_ip VARCHAR(15),
  10. UNIQUE(sessions_identifier)
  11. ) ENGINE = InnoDB DEFAULT CHARSET=utf8;


Jeśli usunę UNIQUE(sessions_identifier) z tabeli to błąd się nie pojawia. Można to obejść sprawdzając czy wpis o podanym numerze sesji istnieje. Jeśli nie to wykonujemy insert a jeśli istnieje to update.
Problem w tym, że zawsze sprawdzałem to poprzez mysql_affected_rows(). Niestety w tym wypadku to nic nie daje i błąd się pojawia. Mógłbym wykonywać selecta i sprawdzać czy został zwrócony wynik (jeśli tak to wpis już istnieje) ale chciałbym uniknąć zbędnego zapytania do bazy..

Macie jakiś pomysł?


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
mike
post 12.02.2007, 08:38:15
Post #2





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

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


Mam trzy pytania pomocnicze?
  • Obiektem jakiej klasy jest $this->oConnection;
  • Co dokładnie robi $this->oConnection->insert(), bo zakładam że to właśnie tu jest źródło problemów;
  • Co się dzieje jeśli usuniesz @ przez wywołaniem tego inserta


Ten post edytował mike_mech 12.02.2007, 08:38:35
Go to the top of the page
+Quote Post
Jarod
post 12.02.2007, 23:03:22
Post #3





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Cytat(mike_mech @ 12.02.2007, 08:38:15 ) *
Mam trzy pytania pomocnicze?
  • Obiektem jakiej klasy jest $this->oConnection;

W $this->oConnection zapisana jest instancja klasy Mysql (domyślasz się co umożliwia)

Cytat(mike_mech @ 12.02.2007, 08:38:15 ) *
  • Co dokładnie robi $this->oConnection->insert(), bo zakładam że to właśnie tu jest źródło problemów;

  1. <?php
  2. /**
  3.  * Metoda wykonująca przekazane zapytanie SQL, zapisująca identyfikator wyniku
  4.  * zapytania do prywatnej właściwości $rQuery i dopisująca do tablicy $aQuerySta
    ck
  5.  * treść zapytania. Jeśli zapytanie nie powiedzie się, zwracany jest odpowiedni
  6.  * komunikat wyjątku.
  7.  * 
  8.  * @param string $sQuery Zapytanie SQL
  9.  */
  10. public function query($sQuery)
  11. {
  12. if (isset($this->rQuery)) unset($this->rQuery);
  13.  
  14. if (!$this->rQuery = @ mysql_query($sQuery, $this->rDatabaseHandle))
  15. throw new MysqlException('Nieudane zapytanie: ' . $sQuery);
  16.  
  17. array_push($this->aQueryStack, $sQuery);
  18. }
  19.  
  20.  
  21. /**
  22.  * Metoda pobiera dwa parametry: nazwę tabeli oraz tablicę z atrybutami tabeli
  23.  * i ich wartościami, które zostaną dodane do bazy. Po odpowiednim przetworzeniu
  24.  * parametrów konstruowane jest zapytanie, a następnie wykonywana jest metoda
  25.  * query() z tym zapytaniem.
  26.  * 
  27.  * @param string $sTableName Nazwa tabeli w bazie danych
  28.  * @param array $aInsert Atrybuty tabeli z przypisanymi wartościami
  29.  */
  30. public function insert($sTableName, array $aInsert)
  31. {
  32. $aInsert = $this->_quoteArray($aInsert);
  33.  
  34. $sSqlFields = '`' . implode('`, `', array_keys($aInsert)) . '`';
  35. $sSqlValues = implode(', ', array_values($aInsert));
  36.  
  37. $sQuery = 'INSERT INTO ' . $sTableName . ' (' . $sSqlFields . ') VALUES (' . $sSqlValues . ')';
  38.  
  39. $this->query($sQuery);
  40. }
  41. ?>



Cytat(mike_mech @ 12.02.2007, 08:38:15 ) *
  • Co się dzieje jeśli usuniesz @ przez wywołaniem tego inserta

Dokładnie ten sam błąd. @ nic w tym przypadku nie wnosi.


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
mike
post 13.02.2007, 15:25:23
Post #4





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

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


Cytat(J4r0d @ 12.02.2007, 23:03:22 ) *
Dokładnie ten sam błąd. @ nic w tym przypadku nie wnosi.

Hmm, tak. Ale nadal masz @ przed jedną z kluczowych instrukcji. Bardziej mi chodziło o to żebyś zdjął je zewsząd, to może pomóc w uzyskaniu tekstu błędu, który powie coś więcej.

Zdejmij @ z przed mysql_query() w linii 14.
Go to the top of the page
+Quote Post
Jarod
post 13.02.2007, 21:04:14
Post #5





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Cytat(mike_mech @ 13.02.2007, 15:25:23 ) *
Hmm, tak. Ale nadal masz @ przed jedną z kluczowych instrukcji. Bardziej mi chodziło o to żebyś zdjął je zewsząd, to może pomóc w uzyskaniu tekstu błędu, który powie coś więcej.

Zdejmij @ z przed mysql_query() w linii 14.

Wszędzie pousuwałem @. Błąd ten sam. Nie wiem co jest grane..

Cytat(J4r0d @ 13.02.2007, 20:49:16 ) *
Wszędzie pousuwałem @. Błąd ten sam. Nie wiem co jest grane..


EDIT: Na szybko napisałem:
  1. <?php
  2. class Mysql
  3. {
  4. public function __construct()
  5. {
  6. $link = mysql_connect('localhost', 'root', 'maestro')
  7.  or die('Nie można się połączyć: ' . mysql_error());
  8.  
  9.  mysql_select_db('cube') or die('Nie można się połączyć: ' . mysql_error());
  10.  
  11.  mysql_query('INSERT INTO sessions VALUES (null, '1', '22:00', '22:05', 'serialize', 'dupa', '127.0.0.1')') or die('Błąd zapytania'.mysql_error());
  12.  
  13. }
  14. }
  15.  
  16. $oM = new Mysql();
  17. ?>


I dostaję błąd:
Kod
Błąd zapytania Duplicate entry '1' for key 2
Czyli tak jak powinno być :/


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
mike
post 13.02.2007, 21:06:13
Post #6





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

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


Hmm, zagadkowa sprawa.
Mam kolejne pytanko pomocnicze, które może pozwoli znaleźć przyczynę błędu.
Czy problem wywala przy każdym zapytaniu INSERT czy tylko przy tych, które naruszają klucz unikalności?
Podejrzewam, że odpowiedź jest jasna, że tylko podczas wstawiana takich samych danych, ale wolę się upewnić.

Nie mniej jednak mam pomysł. Wstaw sam wyrzucanie wyjątku w miejscu gdzie faktycznie problem może wystąpić. Ciekawe czy nadal będzie fatal czy Twój wyjątek.

  1. <?php
  2.  
  3. // ...
  4.  
  5. public function insert($sTableName, array $aInsert)
  6. {
  7. $aInsert = $this->_quoteArray($aInsert);
  8.  
  9. $sSqlFields = '`' . implode('`, `', array_keys($aInsert)) . '`';
  10. $sSqlValues = implode(', ', array_values($aInsert));
  11.  
  12. $sQuery = 'INSERT INTO ' . $sTableName . ' (' . $sSqlFields . ') VALUES (' . $sSqlValues . ')';
  13.  
  14. $this->query($sQuery);
  15.  
  16. if(mysql_errno() != 0) {
  17. throw new Exception(mysql_error(), mysql_errno());
  18. }
  19.  
  20. }
  21.  
  22. // ...
  23.  
  24. ?>
Go to the top of the page
+Quote Post
Jarod
post 13.02.2007, 21:11:36
Post #7





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Cytat(mike_mech @ 13.02.2007, 21:06:13 ) *
Hmm, zagadkowa sprawa.
Mam kolejne pytanko pomocnicze, które może pozwoli znaleźć przyczynę błędu.
Czy problem wywala przy każdym zapytaniu INSERT czy tylko przy tych, które naruszają klucz unikalności?
Podejrzewam, że odpowiedź jest jasna, że tylko podczas wstawiana takich samych danych, ale wolę się upewnić.

Pisałem, że tylko gdy jest naruszany klucz integralności..


Cytat(mike_mech @ 13.02.2007, 21:06:13 ) *
Nie mniej jednak mam pomysł. Wstaw sam wyrzucanie wyjątku w miejscu gdzie faktycznie problem może wystąpić. Ciekawe czy nadal będzie fatal czy Twój wyjątek.

Nadal fatal..

EDIT. Przetestowałem dokładniej. Sterownik do bazy mysql jest poprawny. Problem występuje tylko przy insercie wydawanym w klassie CubeSession. W innych miejscach poprawnie wywala informacje o duplikacji..


EDIT2. Problem rozwiązany. Trzeba było dodać obsługę wyjątków w CubeSession:
  1. <?php
  2. public function write($sSessionId, $aSessionValues)
  3. {
  4. $aInsert = array('sessions_identifier'=>session_id(), 'sessions_time_start'=>'21:15',
  5. 'sessions_last_time' => '21:16', 'sessions_values'=>'serialize','login'=>'dupa', 'address_ip'=>$this->sAddressIp );
  6. // $this->oConnection->insert('sessions', $aInsert);
  7.  
  8. try
  9. {
  10. $this->oConnection->query('INSERT INTO sessions VALUES (null, '1', '22:00', '22:05', 'serialize', 'dupa', '127.0.0.1')');
  11. }
  12. catch (Exception $e)
  13. {
  14. echo $e;
  15. }
  16. ?>

Nie rozumiem tylko dlaczego bez obsługi wyjątków wywala się tak.. Ktoś to potrafi wytłumaczyć?

Ten post edytował J4r0d 13.02.2007, 21:31:35


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
kicaj
post 2.05.2007, 22:49:25
Post #8





Grupa: Zarejestrowani
Postów: 1 640
Pomógł: 28
Dołączył: 13.02.2003
Skąd: Międzyrzecz/Poznań

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


Mam identyczny przypadek i identyczny blad... rozwiazalem go podobnie, jednak to wyglada mi na amatorke:p

Wiem ze jest to blad w PHP, jednak znalezione rozwiazania z __destruct() i/lub __sleep() nie pomagaly, jesli ktos juz wie cos na ten temat wiecej, zapraszam:)


--------------------
PHP Developer

"Nadmiar wiedzy jest równie szkodliwy jak jej brak" Émile Zola
Go to the top of the page
+Quote Post
Turgon
post 5.05.2007, 11:13:57
Post #9





Grupa: Zarejestrowani
Postów: 800
Pomógł: 0
Dołączył: 26.11.2005
Skąd: Nowy Sącz

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


Czy ludzie naprawdę nie domyślacie się dlaczego ? Skoro używacie session_set_save_handler(), to większość funkcji jest wywoływana po za skryptem i jak nie ma ramki try{}, to skrypt głupieje, bo jest po za...


--------------------
Jah Music Is On My Mind !
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.07.2025 - 10:20