Skip to content

Commit d984d0d

Browse files
committed
In MySQL, harvest last insert ID immediately after query is executed
1 parent db768e4 commit d984d0d

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

src/Illuminate/Database/MySqlConnection.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,47 @@
1414

1515
class MySqlConnection extends Connection
1616
{
17+
/**
18+
* The last inserted ID generated by the server
19+
*
20+
* @var string|int|null
21+
*/
22+
protected $lastInsertId;
23+
24+
/**
25+
* Run an insert statement against the database.
26+
*
27+
* @param string $query
28+
* @param array $bindings
29+
* @param string|null $sequence
30+
* @return bool
31+
*/
32+
public function insert($query, $bindings = [], $sequence = null)
33+
{
34+
return $this->run($query, $bindings, function ($query, $bindings) use ($sequence) {
35+
if ($this->pretending()) {
36+
return true;
37+
}
38+
39+
$statement = $this->getPdo()->prepare($query);
40+
41+
$this->bindValues($statement, $this->prepareBindings($bindings));
42+
43+
$this->recordsHaveBeenModified();
44+
45+
$result = $statement->execute();
46+
47+
$this->lastInsertId = $this->getPdo()->lastInsertId($sequence);
48+
49+
return $result;
50+
});
51+
}
52+
53+
public function getLastInsertId()
54+
{
55+
return $this->lastInsertId;
56+
}
57+
1758
/**
1859
* Escape a binary value for safe SQL embedding.
1960
*

src/Illuminate/Database/Query/Processors/MySqlProcessor.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Illuminate\Database\Query\Processors;
44

5+
use Illuminate\Database\Query\Builder;
6+
57
class MySqlProcessor extends Processor
68
{
79
/**
@@ -19,6 +21,24 @@ public function processColumnListing($results)
1921
}, $results);
2022
}
2123

24+
/**
25+
* Process an "insert get ID" query.
26+
*
27+
* @param \Illuminate\Database\Query\Builder $query
28+
* @param string $sql
29+
* @param array $values
30+
* @param string|null $sequence
31+
* @return int
32+
*/
33+
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
34+
{
35+
$query->getConnection()->insert($sql, $values, $sequence);
36+
37+
$id = $query->getConnection()->getLastInsertId();
38+
39+
return is_numeric($id) ? (int) $id : $id;
40+
}
41+
2242
/**
2343
* Process the results of a columns query.
2444
*

tests/Integration/Database/MySql/DatabaseMySqlConnectionTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Illuminate\Tests\Integration\Database\MySql;
44

5+
use Illuminate\Database\Events\QueryExecuted;
56
use Illuminate\Database\Schema\Blueprint;
67
use Illuminate\Support\Facades\DB;
78
use Illuminate\Support\Facades\Schema;
@@ -151,4 +152,27 @@ public static function jsonContainsKeyDataProvider()
151152
'null value' => [1, 'json_col->bar'],
152153
];
153154
}
155+
156+
public function testLastInsertIdIsPreserved()
157+
{
158+
if (! Schema::hasTable('auto_id_table')) {
159+
Schema::create('auto_id_table', function (Blueprint $table) {
160+
$table->id();
161+
});
162+
}
163+
164+
try {
165+
static $callbackExecuted = false;
166+
DB::listen(function (QueryExecuted $event) use (&$callbackExecuted) {
167+
DB::getPdo()->query('SELECT 1');
168+
$callbackExecuted = true;
169+
});
170+
171+
$id = DB::table('auto_id_table')->insertGetId([]);
172+
$this->assertTrue($callbackExecuted, 'The query listener was not executed.');
173+
$this->assertEquals(1, $id);
174+
} finally {
175+
Schema::drop('auto_id_table');
176+
}
177+
}
154178
}

0 commit comments

Comments
 (0)