returns - PHP/MySQLi en Windows: inserta en MySQL la tabla innoDB aumenta la columna AUTO_INCREMENT en 2
mysqli_insert_id returns 0 (1)
De acuerdo. Finalmente lo tengo. El problema es: redirijo todas las solicitudes a mi index.php y hago todo el resto con PHP. Probé el comportamiento de algunas clases con salidas simples. Una de las pruebas conduce al problema anterior. Revisé el registro de acceso de Apache y noté repetidas solicitudes de favicon.ico. Estas solicitudes, producidas automáticamente por los principales navegadores (ver también ¿Cómo prevenir las solicitudes de favicon.ico? ), También llegaron a index.php y parecen redirigir al navegador? normalmente todo esto se maneja en mi marco de aplicación, pero lo desactivé mientras lo probé.
Cuando hago un simple inserto a través de la API de PHP mysqli
con instrucciones preparadas en Windows dentro de un proceso de PHP, la columna AUTO_INCREMENT definida se incrementa en 2 en lugar de 1:
INSERT INTO `table` (`name`) VALUES (?)
Aumenta en 1 cuando se realizan inserciones múltiples (una por una en transacciones separadas) dentro de un proceso de PHP.
Siempre aumenta en 1 cuando uso la misma consulta SQL a través de phpmyadmin.
No hay otras INSERT
o UPDATE
antes o después del INSERT
mencionado. Solo un SHOW
y algunas declaraciones SELECT
antes.
No puedo encontrar la causa de este problema. ¿Cuáles pueden ser las causas de tal comportamiento?
Aquí las partes principales del código:
<?php
class DB
{
private function __construct($host, $username, $password, $schema, $port, $socket)
{
if(is_null(self::$DB))
{
self::$DB = new /MySQLi((string) $host, (string) $username, (string) $password, (string) $schema, (int) $port, (string) $socket);
self::$DB->set_charset(''utf8'');
}
}
// [...]
public function __destruct()
{
if(!is_null(self::$DB))
self::$DB->close();
}
// [...]
public static function connect($host = '''', $username = '''', $password = '''', $schema = '''', $port = 0, $socket = '''')
{
if(is_null(self::$instance))
{
$MD = new /MySQLi_driver();
$MD->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
// [...]
self::$instance = new self($host, $username, $password, $schema, $port, $socket);
}
return self::$instance;
}
// [...]
public static function __callStatic($name, $args)
{
self::connect();
switch(true)
{
case in_array($name, array(''insert'', ''select'', ''update'', ''delete'', ''show'', ''describe'', ''explain'')):
$query = isset($args[0]) ? (string) $args[0] : '''';
$vals = isset($args[1]) ? $args[1] : array();
$select = isset($args[2]) ? trim((string) $args[2]) : ''array'';
$empty = isset($args[3]) ? $args[3] : array();
$types = isset($args[4]) ? trim((string) $args[4]) : '''';
return self::dml(in_array($name, array(''show'', ''describe'', ''explain'')) ? ''select'' : $name, $query, $vals, $select, $empty, $types);
break;
}
//[...]
}
// [...]
public static function dml($type, $query, $vals = array(), $select = ''array'', $empty = array(), $types = '''')
{
// [...]
if(!empty($vals) || mb_strpos($query,''?'') !== false)
{
if(!$stmt = self::$DB->prepare($query))
throw new DBException(''Failed to prepare statement ''.htmlspecialchars($query).PHP_EOL.self::$DB->error.'' (''.self::$DB->sqlstate.'').'');
$args = array();
if(empty($types))
{
foreach($vals as &$val)
{
$t = gettype($val);
if($t == ''string'' || $t == ''NULL'')
$types.= ''s'';
elseif($t == ''integer'' || $t == ''boolean'')
$types.= ''i'';
elseif($t == ''double'' || $t == ''float'')
$types.= ''d'';
else
throw new DBException(''Its not possible to automatically assign a value of type ''.$t.''. Please specify the corresponding types manually.'');
$args[] = $val;
}
}
else
{
foreach($vals as &$val)
$args[] = $val;
}
array_unshift($args, $types);
$RC = new /ReflectionClass($stmt);
$RM = $RC->getMethod(''bind_param'');
if(!$RM->invokeArgs($stmt, $args))
throw new DBException(''Failed to bind params.''.PHP_EOL.self::$DB->error.'' (''.self::$DB->sqlstate.'').'');
if(!$stmt->execute())
throw new DBException(''Failed to execute Statement.''.PHP_EOL.self::$DB->error.'' (''.self::$DB->sqlstate.'').'');
if($type == ''select'')
{
// [...]
}
else
{
$return = $type == ''insert'' && self::$DB->insert_id > 0 ? self::$DB->insert_id : self::$DB->affected_rows;
$stmt->close();
return $return;
}
}
else
{
// [...]
}
}
}
?>
Y:
echo DB::insert("INSERT INTO `table` (`name`) VALUES (?)", ["test"]);
El Query-Log muestra 2 inserciones. Esto causa el incremento adicional. Pero cuando pongo un eco en el método DB :: dml () correspondiente, solo se emite una vez, por lo que se lo llama una vez. El mysql-query-log:
151026 12:54:49 3 Connect XXX@localhost on XXX
3 Query SET NAMES utf8
3 Query SELECT DATABASE() AS `schema`
3 Query SHOW GRANTS FOR CURRENT_USER
3 Prepare INSERT INTO `table` (`name`) VALUES (?)
3 Execute INSERT INTO `table` (`name`) VALUES (''testinsert22'')
3 Close stmt
3 Quit
4 Connect XXX@localhost on XXX
4 Query SET NAMES utf8
4 Query SELECT DATABASE() AS `schema`
4 Query SHOW GRANTS FOR CURRENT_USER
4 Prepare INSERT INTO `table` (`name`) VALUES (?)
4 Execute INSERT INTO `table` (`name`) VALUES (''testinsert22'')
4 Close stmt
4 Quit