cakephp: QueryBuilder - lastInsertId() returns "0"

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • CakePHP Version: 3.4.7

  • Platform and Target: MariaDB (5.5.5-10.1.21), PHP Version 7.1.1, Apache, Windows 7

What you did

Trying to insert a new record and get the lastInsertId (AUTO_INCREMENT).

What happened

The result of lastInsertId() is always “0”.

Example code:

CREATE TABLE `users` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `username` VARCHAR (255),
  PRIMARY KEY (`id`)
) ENGINE = INNODB CHARSET = utf8 COLLATE = utf8_unicode_ci ;
// composer require cakephp/database
require_once __DIR__ . '/vendor/autoload.php';

// Database settings
$config = array(
    'driver' => 'mysql',
    'host' => '127.0.0.1',
    'port' => '3306',
    'username' => 'root',
    'password' => '',
    'database' => 'test',
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
);

$driver = new \Cake\Database\Driver\Mysql($config);
$db = new \Cake\Database\Connection(['driver' => $driver]);

$row = [
    'username' => 'max'
];

$result = $db->insert('users', $row);

$newId = $result->lastInsertId();
echo $newId;  // value is "0"

If I try the same with a native PDO query it works, but not with the CakePHP QueryBuilder.

$pdo = $db->getDriver()->connection();
$stmt = $pdo->query("SELECT LAST_INSERT_ID()");
$lastId = $stmt->fetchColumn(); // This works. Returns 1 or more.

What you expected to happen

Returns the ID of the last inserted row or sequence value.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18 (18 by maintainers)

Commits related to this issue

Most upvoted comments

Here is an update:

There is an issue with the magic method: __debugInfo() in Driver.php

https://github.com/cakephp/cakephp/blob/master/src/Database/Driver.php#L386

Xdebug uses PHP’s var_dump() function for displaying variables. https://xdebug.org/docs/display

Changing the xdebug.overload_var_dump value in php.ini has no positive effect. https://derickrethans.nl/xdebug-2.3-overload-vardump.html

Workaround / Fix: If you return just an empty array it works like expected.

image

This fix also works: image

The isConnected method starts a database query (SELECT 1) to check if the connection is available.

image

https://github.com/cakephp/cakephp/blob/b27ebbd6a4e9b6062bd45e13a439b7ab7f29d0af/src/Database/Driver/PDODriverTrait.php#L92

After every SELECT the lastInsertId() is 0. That’s the reason.

@lorenzo For me this is no more an Xdebug issue. What do you think?

Ok this is crazy… I’ve testet the same code on my home computer and here it works.

image

But then I enabled a breakpoint and started XDebug and the result is 0 again.

image

image

If I remove the debugger breakpoint in PHPStorm (XDebug is still running) everything works! How is that possible?

Connection != null is probably good enough for debug data. I wouldn’t change isConnected() though.

lastInsertId only works if the last query was an insert, if you query a select or another query lastInserId returns 0 I guess in your debugging some variable inspector would execute another query (like a count?) set lastinsertid to 0

I have stopped using lastInsertId for the same reason. When ever I want to get back the lastInsertedId I always query the database to find the record. It’s too unstable getting the id from lastInsertId and you might easily end up with race conditions.