Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Непонятки с PDO lastInsertId()

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
RUOK
Отправлено: 19 Мая, 2015 - 20:23:53
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Июль 2014  


Помог: 0 раз(а)




Привет.

PDO lastInsertId() выдает 0, при определенных обстоятельствах. А именно когда PDO завернут в другой объект и из этой обертки вызывается. Обертка нужна для реконнекта при обрыве, только для этой цели я ее использую. Если вызывать lastInsertId() без обертки, то всё работает как надо и ID выдаются, а из обертки - всегда 0.

Вот код класса обертки:

PHP:
скопировать код в буфер обмена
  1.  
  2.  
  3. class R_PDO    {
  4.    
  5.     protected $pdo_conn;
  6.    
  7.     protected $dsn, $username, $password, $driver_options;
  8.    
  9.    
  10.    
  11.     public function __construct($dsn, $username, $password, $driver_options)    {
  12.        
  13.         $this -> dsn = $dsn;
  14.         $this -> username = $username;
  15.         $this -> password = $password;
  16.         $this -> driver_options = $driver_options;
  17.        
  18.         $this -> connect();
  19.        
  20.     }
  21.    
  22.     public function __destruct()    {
  23.    
  24.         $this -> pdo_conn = null;
  25.    
  26.     }
  27.  
  28.    
  29.     public function __call($name, array $arguments)    {
  30.        
  31.         try    {
  32.            
  33.             $this -> connection() -> query("SHOW STATUS;") -> execute();
  34.            
  35.            
  36.         }    catch(PDOException $e)    {
  37.            
  38.             if($e->getCode() != 'HY000' || !stristr($e->getMessage(), 'server has gone away')) {
  39.                
  40.                 throw $e;
  41.                
  42.             }    else    {
  43.                
  44.                 write_logs('R_PDO: connection fail, reconnecting...');
  45.                 $this -> reconnect();
  46.                                
  47.                
  48.             }
  49.            
  50.         }
  51.        
  52.        
  53.         return call_user_func_array(array($this -> connection(), $name), $arguments);
  54.        
  55.     }
  56.  
  57.     protected function connection()    {
  58.        
  59.         return $this -> pdo_conn instanceof PDO ? $this -> pdo_conn : $this -> connect();
  60.                
  61.     }
  62.  
  63.     public function connect()    {
  64.        
  65.         try    {
  66.                                    
  67.             $this -> pdo_conn = new PDO($this -> dsn, $this -> username, $this -> password, (array)$this -> driver_options);
  68.             $this -> pdo_conn -> setAttribute(PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);
  69.            
  70.         }    catch(PDOException $e)    {
  71.            
  72.             write_logs($e->getMessage());
  73.             die();
  74.            
  75.         }
  76.        
  77.         return $this -> pdo_conn;
  78.        
  79.     }
  80.  
  81.     public function reconnect()    {
  82.        
  83.         $this -> pdo_conn = null;
  84.         return $this -> connect();
  85.        
  86.     }
  87.  
  88.    
  89.    
  90. }
  91.  
  92.  


Помогите разобраться.
 
 Top
OrmaJever Модератор
Отправлено: 19 Мая, 2015 - 20:43:58
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




и в каком месте здесь вызываеться lastInsertId ? Однако


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
RUOK
Отправлено: 19 Мая, 2015 - 21:00:06
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Июль 2014  


Помог: 0 раз(а)




OrmaJever пишет:
и в каком месте здесь вызываеться lastInsertId ? Однако


это класс-обертка для PDO

lastInsertId дергается из основного скрипта:
PHP:
скопировать код в буфер обмена
  1.  
  2.  
  3. $dbh = new R_PDO(DSN, MYSQL_USER, MYSQL_PASS, unserialize(MYSQL_OPTIONS));
  4. $dbh -> exec("SET NAMES 'utf8';");
  5.  
  6.  
  7. ......
  8. ......
  9.  
  10. $sth = $dbh -> prepare("INSERT INTO regions (name)
  11.                                                 VALUES (:region_name);");
  12.                
  13. $sth -> bindValue(':region_name', $region);
  14.        
  15. $sth -> execute();
  16.                
  17. $region_id = $dbh -> lastInsertId();
  18.  
  19.  
  20.  




Я уже кое-что понял

lastInsertId() скидывается в ноль после испольнения комманды

$this -> connection() -> query("SHOW STATUS;") -> execute();

которая всегда исполняется для прозвона базы на обрыв подключения, если эту строку закоментировать, то все нормально становится

почему так, ума не приложу

(Отредактировано автором: 19 Мая, 2015 - 21:00:54)

 
 Top
DeepVarvar Супермодератор
Отправлено: 19 Мая, 2015 - 21:45:23
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Потому что так и есть. Если ты хочешь забрать последний автоинкрементный айдишник, то забирай его сразу после успешного выполнения запроса, т.к. в следующем любом запросе там будет ноль.
Еще не хватало чтобы за тебя пдо ванговала когда ж ты соизволишь забрать значение айдишника.
 
 Top
RUOK
Отправлено: 19 Мая, 2015 - 21:53:37
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Июль 2014  


Помог: 0 раз(а)




Я разобрался, всем спасибо.
Дело в том что lastInsertId() не совсем адекватно работает, если после INSERT с автоинкрементом вам нужно узнать с каким ID добавлена запись, то нужно использовать lastInsertId() СРАЗУ после INSERT, иначе он будет возвращать 0, не важно что вы между делом используете запросы не связанные с INSERT.

Альтернатива - использование стандартной функции MYSQL - LAST_INSERT_ID()
в этом случае всё работает логично и после добавления записей через INSERT можно давать запросы не связаные с INSERT и получать ID последней записи.
(Добавление)
DeepVarvar пишет:
Потому что так и есть. Если ты хочешь забрать последний автоинкрементный айдишник, то забирай его сразу после успешного выполнения запроса, т.к. в следующем любом запросе там будет ноль.
Еще не хватало чтобы за тебя пдо ванговала когда ж ты соизволишь забрать значение айдишника.



А что PDO не в состоянии запустить стандартый мускулевский LAST_INSERT_ID()?

Вот описание:

PDO::lastInsertId — Возвращает ID последней вставленной строки или последовательное значение

Если объект последовательности для name не задан, PDO::lastInsertId() вернет строку представляющую ID последней добавленной в базу записи.

Тут нигде не сказано что нельзя запускать никакие запросы.

Я несколько часов бился как рыба об лед, хотя делал всё по инструкции.
В инструкции написано черным по белому что lastInsertId выдает ID последней вставленной строки. Почему SELECT или SHOW STATUS должны скидывать в 0 ID то? После SHOW STATUS изменился последний ID? Нет. Вот и функция LAST_INSERT_ID() абсолютно корректно работает, не важно сколько селектов будет после добавления записи.

(Отредактировано автором: 19 Мая, 2015 - 22:06:42)

 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Работа с СУБД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB