CHATGPT Conexión PDO Access 97
La conexión que estás utilizando está diseñada para MySQL, pero si deseas conectar una base de datos Microsoft Access 97 (formato .mdb) con PHP y PDO, necesitarás utilizar un driver ODBC compatible con Access.
Aquí te muestro cómo adaptar tu código para conectarte a una base de datos Access 97 usando PDO ODBC:
✅ Paso 1: Asegúrate de tener lo siguiente
El archivo .mdb de Access 97.
En Windows, debe estar habilitado el driver "Microsoft Access Driver (*.mdb)" (viene preinstalado en muchos sistemas Windows).
PHP debe tener habilitada la extensión PDO_ODBC.
✅ Código adaptado:
<?php
// Ruta completa al archivo .mdb de Access 97
$accessFile = realpath('C:/ruta/a/tu_basedatos.mdb');
// Fuente de datos ODBC (DSN)
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=Admin;Pwd=;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, '', '', $options); // Usuario y contraseña usualmente vacíos para Access
echo json_encode(['success' => true, 'message' => 'Conexión exitosa.']);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error de conexión: ' . $e->getMessage()]);
exit;
}
🔎 Notas importantes:
Reemplaza C:/ruta/a/tu_basedatos.mdb por la ruta real a tu archivo .mdb.
Si tu archivo .mdb tiene contraseña, colócala en Pwd=tu_clave;.
Si ves errores como "no se pudo encontrar el controlador ODBC", verifica que tu sistema tenga instalado el driver correcto. En máquinas de 64 bits, puede ser necesario usar el ODBC de 32 bits si tu Access es de 32 bits.
¿Querés que te ayude a detectar si el driver está instalado o cómo configurarlo en tu sistema?
Dijiste:
corregir $accessFile = realpath('C:/bdkian.mdb');
// Fuente de datos ODBC (DSN)
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, '', '', $options); // Usuario y contraseña usualmente vacíos para Access
echo json_encode(['success' => true, 'message' => 'Conexion exitosa.']);
try {
$pdo = new PDO($dsn, '', '', $options);
$stmt = $pdo->prepare("SELECT * FROM Articulos LIMIT 1");
$stmt->bindParam(':codigo', '1');
$stmt->execute();
$producto = $stmt->fetch();
if ($producto) {
echo json_encode([
'success' => true,
'producto' => [
'nombre' => $producto['Nombre'],
'precio' => $producto['Precioventa']
]
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
} catch (\PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error en la consulta: ' . $e->getMessage()]);
}
ChatGPT dijo:
Gracias por compartir el código. Estás intentando hacer dos conexiones new PDO() cuando sólo necesitas una. Además, estás usando un bindParam con un parámetro :codigo que no existe en tu consulta SQL (SELECT * FROM Articulos LIMIT 1), lo cual causará error.
Aquí te dejo el código corregido y limpio, con los errores arreglados:
✅ Código corregido:
<?php
// Ruta al archivo Access 97 (.mdb)
$accessFile = realpath('C:/bdkian.mdb');
// Fuente de datos ODBC (DSN)
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
// Conexión
$pdo = new PDO($dsn, '', '', $options);
echo json_encode(['success' => true, 'message' => 'Conexión exitosa.']);
// Consulta (sin parámetros porque LIMIT 1 no los necesita)
$stmt = $pdo->prepare("SELECT * FROM Articulos LIMIT 1");
$stmt->execute();
$producto = $stmt->fetch();
if ($producto) {
echo json_encode([
'success' => true,
'producto' => [
'nombre' => $producto['Nombre'],
'precio' => $producto['Precioventa']
]
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error en la consulta o conexión: ' . $e->getMessage()]);
}
?>
✅ Cambios realizados:
Eliminada la conexión duplicada ($pdo = new PDO(...) dos veces).
Quitado el bindParam(':codigo', '1'); que era innecesario y generaba error.
Se manejan errores tanto de conexión como de ejecución con un solo bloque try-catch.
La respuesta de conexión exitosa y la respuesta del producto están separadas, si querés podríamos integrarlas.
¿Querés que la búsqueda sea por codigobarra o por ID? Puedo ayudarte a modificar la consulta para recibir ese dato por GET o POST.
Dijiste:
corregir $accessFile = realpath('C:/bdkian.mdb');
// Fuente de datos ODBC (DSN)
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=Admin;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, '', '', $options); // Usuario y contraseña usualmente vacíos para Access
echo json_encode(['success' => true, 'message' => 'Conexión exitosa.']);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error de conexión: ' . $e->getMessage()]);
exit;
}
$stmt = $pdo->prepare("SELECT * FROM Articulos WHERE ID = :codigo LIMIT 1");
$stmt->bindParam(':codigo', 1);
$stmt->execute();
$producto = $stmt->fetch();
if ($producto) {
echo json_encode([
'success' => true,
'producto' => [
'nombre' => $producto['Nombre'],
'precio' => $producto['Precioventa']
]
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
} catch (\PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error en la consulta: ' . $e->getMessage()]);
}
ChatGPT dijo:
Perfecto, estás muy cerca. Solo hay algunos detalles a corregir:
El bloque try se cierra demasiado temprano, pero luego continuás ejecutando código que también puede generar excepciones.
El segundo bloque catch no tiene su correspondiente try, lo que causará un error de sintaxis.
No es necesario mostrar el echo json_encode(['success' => true, 'message' => 'Conexión exitosa.']); antes de la consulta, ya que se puede incluir como parte del flujo si la consulta fue exitosa.
✅ Código corregido completamente y funcional:
<?php
$accessFile = realpath('C:/bdkian.mdb');
// Fuente de datos ODBC (DSN)
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=Admin;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
// Conexión a la base de datos
$pdo = new PDO($dsn, '', '', $options);
// Consulta con parámetro
$stmt = $pdo->prepare("SELECT * FROM Articulos WHERE ID = :codigo LIMIT 1");
$codigo = 1;
$stmt->bindParam(':codigo', $codigo, PDO::PARAM_INT);
$stmt->execute();
$producto = $stmt->fetch();
if ($producto) {
echo json_encode([
'success' => true,
'producto' => [
'nombre' => $producto['Nombre'],
'precio' => $producto['Precioventa']
]
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error: ' . $e->getMessage()]);
}
?>
✅ Cambios claves:
Se encapsuló todo en un solo try { ... } catch { ... }.
Se corrigió el uso de bindParam con la variable $codigo, definiéndola antes.
Se eliminó el echo de conexión exitosa que no aporta valor cuando ya devolvés un json del producto.
¿Querés que ese ID venga desde un GET o POST para buscar dinámicamente un producto? Puedo ayudarte a hacerlo también.
Dijiste:
como muestro con echo json_encode el producto buscado
ChatGPT dijo:
Perfecto. Ya lo estás haciendo bien en tu código con este bloque:
echo json_encode([
'success' => true,
'producto' => [
'nombre' => $producto['Nombre'],
'precio' => $producto['Precioventa']
]
]);
Esto muestra una respuesta JSON como esta:
{
"success": true,
"producto": {
"nombre": "Nombre del producto",
"precio": 123.45
}
}
👀 ¿Querés ver todo el contenido del producto directamente?
Si querés imprimir todos los campos del producto sin escribir uno por uno, podés hacer:
echo json_encode([
'success' => true,
'producto' => $producto
]);
📦 Ejemplo completo con GET para buscar dinámicamente
Si querés buscar por ID usando una URL como:
buscar.php?id=5
Código:
<?php
$accessFile = realpath('C:/bdkian.mdb');
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=Admin;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, '', '', $options);
// Obtener ID desde GET
$codigo = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$stmt = $pdo->prepare("SELECT * FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo, PDO::PARAM_INT);
$stmt->execute();
$producto = $stmt->fetch();
if ($producto) {
echo json_encode([
'success' => true,
'producto' => $producto // <-- Esto imprime todos los campos
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Error: ' . $e->getMessage()]);
}
?>
¿Querés que el resultado se vea formateado en HTML o te sirve directo en JSON para usarlo desde JavaScript/AJAX?
Dijiste:
como poner conexion utf8
ChatGPT dijo:
Buena pregunta. Sin embargo, cuando trabajás con Microsoft Access (.mdb) a través de ODBC y PDO, no es posible forzar directamente el charset a UTF-8 como lo harías con MySQL usando charset=utf8 en el DSN.
Access maneja el conjunto de caracteres basado en la configuración regional del sistema operativo de Windows, y ODBC no permite definir directamente el charset como sí se hace en MySQL.
🧠 Entonces… ¿qué podés hacer?
✅ 1. Convertir el resultado a UTF-8 manualmente en PHP:
Podés usar utf8_encode() o mb_convert_encoding() sobre los datos que recibís de Access antes de usarlos o mostrarlos.
✅ Ejemplo práctico:
$producto = $stmt->fetch();
if ($producto) {
// Convertir todos los campos a UTF-8
$producto_utf8 = array_map('utf8_encode', $producto);
echo json_encode([
'success' => true,
'producto' => $producto_utf8
]);
} else {
echo json_encode(['success' => false, 'error' => 'Producto no encontrado']);
}
🛠️ ¿Por qué puede pasar esto?
Cuando trabajás con Access 97 y tu base de datos contiene acentos (tildes, eñes, etc.), PHP puede mostrar mal esos caracteres si no están en UTF-8, especialmente si tu script PHP o el navegador esperan texto en UTF-8.
✅ Consejo extra
Asegurate de que tu script PHP tenga encabezado UTF-8:
header('Content-Type: application/json; charset=utf-8');
¿Querés que te prepare una función que convierta arrays completos a UTF-8, incluso anidados? También se puede hacer.
Dijiste:
hacer asi while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
$data_array['ID']=$row['ID'];
$data_array['Codigobarra']=$row['Codigobarra'];
$data_array['Nombre']=utf8_encode($row['Nombre']);
array_push($json,$data_array);
}
ChatGPT dijo:
¡Perfecto! Vas por el camino correcto. Acá te dejo el fragmento corregido y completo con buenas prácticas, incluyendo la conversión a UTF-8 para evitar problemas con tildes, eñes, etc., en los resultados de Access:
✅ Ejemplo usando while + utf8_encode + array_push
<?php
header('Content-Type: application/json; charset=utf-8');
$accessFile = realpath('C:/bdkian.mdb');
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$accessFile;Uid=Admin;Pwd=995511;";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, '', '', $options);
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos");
$stmt->execute();
$json = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre'])
];
array_push($json, $data_array);
}
echo json_encode([
'success' => true,
'data' => $json
]);
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error: ' . $e->getMessage()
]);
}
?>
🧠 Alternativa: convertir todo el array a UTF-8 con array_map
Si más adelante tenés más campos que necesitan codificación, podés hacer:
$data_array = array_map('utf8_encode', $row);
En lugar de hacer utf8_encode() uno por uno.
¿Querés agregar filtros, paginación o búsqueda por nombre? Puedo ayudarte a escalar esto también.
Dijiste:
hacer para $codigo = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$stmt = $pdo->prepare("SELECT * FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo, PDO::PARAM_INT);
$stmt->execute(); pero con el codigo $accessFile = realpath('C:/bdkian.mdb');
try {
$pdo = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=$accessFile; Uid=; Pwd=995511;");
$pdo->exec("set names utf8");
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos");
$stmt->execute();
$json = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre'])
];
array_push($json, $data_array);
}
echo json_encode([
'success' => true,
'data' => $json
]);
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error: ' . $e->getMessage()
]);
}
ChatGPT dijo:
Perfecto, te lo armo con tu base de código, pero ajustado para buscar por ID recibido por GET usando bindParam, como querés.
✅ Código completo corregido con parámetro id desde $_GET:
<?php
header('Content-Type: application/json; charset=utf-8');
// Ruta absoluta a la base de datos Access
$accessFile = realpath('C:/bdkian.mdb');
// Obtener ID desde GET
$codigo = isset($_GET['id']) ? (int) $_GET['id'] : 0;
try {
// Conexión a Access
$pdo = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=$accessFile;Uid=;Pwd=995511;");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta preparada
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo, PDO::PARAM_INT);
$stmt->execute();
// Obtener resultado
$producto = $stmt->fetch(PDO::FETCH_ASSOC);
if ($producto) {
// Codificar el campo que podría tener tildes
$producto['Nombre'] = utf8_encode($producto['Nombre']);
echo json_encode([
'success' => true,
'producto' => $producto
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Producto no encontrado'
]);
}
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error: ' . $e->getMessage()
]);
}
✅ Ejemplo de uso por URL:
http://localhost/archivo.php?id=3
🧠 Notas:
set names utf8 no tiene efecto con Access y ODBC, por eso lo eliminé.
utf8_encode solo se aplicó al campo Nombre que podría tener acentos.
Podés usar también array_map('utf8_encode', $producto) si querés aplicarlo a todos los campos de golpe.
¿Querés que además devuelva 404 si no encuentra el producto o seguir con success: false en el JSON?
Dijiste:
con $data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre'])
];
ChatGPT dijo:
¡Claro! Acá tenés el código completo usando tu estructura con $data_array, tal como pedís, para buscar un solo producto por ID (vía $_GET['id']) y retornarlo en formato JSON:
✅ Código completo usando $data_array con utf8_encode
<?php
header('Content-Type: application/json; charset=utf-8');
$accessFile = realpath('C:/bdkian.mdb');
$codigo = isset($_GET['id']) ? (int) $_GET['id'] : 0;
try {
// Conexión a Access
$pdo = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=$accessFile;Uid=;Pwd=995511;");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta preparada con parámetro
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
// Armar respuesta con utf8_encode
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre'])
];
echo json_encode([
'success' => true,
'producto' => $data_array
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Producto no encontrado'
]);
}
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error: ' . $e->getMessage()
]);
}
🔎 Ejemplo de uso:
http://localhost/tuarchivo.php?id=5
¿Querés que esta misma lógica la adaptemos para búsqueda por Codigobarra o agregar paginación después? También se puede aplicar.
Dijiste:
corregir header('Content-Type: application/json; charset=utf-8');
$accessFile = realpath('C:/bdkian.mdb');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
$data['codigo']=1;
$codigo_barra = $data['codigo'] ;
try {
// Conexión a Access
$pdo = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=$accessFile;Uid=;Pwd=995511;");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta preparada con parámetro
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo_barra, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
// Armar respuesta con utf8_encode
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre'])
];
echo json_encode([
'success' => true,
'producto' => $data_array
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Producto no encontrado'
]);
}
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error: ' . $e->getMessage()
]);
}
} else {
echo json_encode(['success' => false, 'error' => 'Método no permitido']);
}
ChatGPT dijo:
Perfecto, tu código está bien encaminado, solo le hace falta un par de detalles menores para que sea más limpio y seguro. Acá tenés el código corregido y ordenado:
✅ Código corregido y optimizado:
<?php
header('Content-Type: application/json; charset=utf-8');
$accessFile = realpath('C:/bdkian.mdb');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Leer datos del cuerpo del request (JSON)
$data = json_decode(file_get_contents('php://input'), true);
// Validar que 'codigo' exista y sea numérico
$codigo_barra = isset($data['codigo']) ? (int)$data['codigo'] : 0;
try {
// Conexión a MS Access
$pdo = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=$accessFile;Uid=;Pwd=995511;");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta preparada con parámetro
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre FROM Articulos WHERE ID = :codigo");
$stmt->bindParam(':codigo', $codigo_barra, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre']) // MS Access usa ANSI, por eso se convierte
];
echo json_encode([
'success' => true,
'producto' => $data_array
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Producto no encontrado'
]);
}
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Error de base de datos: ' . $e->getMessage()
]);
}
} else {
echo json_encode([
'success' => false,
'error' => 'Método no permitido'
]);
}
📌 Detalles importantes:
Validás que el método sea POST.
Usás json_decode() para recibir datos como { "codigo": 1 }.
Se convierte Nombre con utf8_encode() para evitar problemas de codificación.
Se protege con try/catch en caso de fallas.
¿Querés que este script reciba también búsquedas por Codigobarra además de ID? Puedo ayudarte con eso también.
Dijiste:
adaptar al sig codigo // Función para buscar el producto en la base de datos
function buscarProducto(codigo) {
$.ajax({
url: 'api_producto_buscar.php',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ codigo: codigo }),
success: function(response) {
if (response.success) {
$('#nombreProducto').val(response.producto.nombre);
$('#precioProducto').val('$' + parseFloat(response.producto.precio));
} else {
$('#nombreProducto').val('Producto NO encontrado');
$('#precioProducto').val('$0.00');
console.error(response.error);
}
},
error: function(xhr, status, error) {
console.error("Error en la solicitud AJAX:", error);
$('#nombreProducto').val('Error al buscar producto');
$('#precioProducto').val('$0.00');
}
});
}
// Evento para el botón seleccionar (opcional)
$('.btn-seleccionar2').click(function() {
const codigo = $('#barcode2').val();
if (codigo) {
buscarProducto(codigo);
} else {
alert('Por favor escanee un código primero');
}
});
ChatGPT dijo:
Perfecto. Ya que tu código PHP espera un campo codigo y realiza una búsqueda por ID en la tabla Articulos, y tu JavaScript hace una búsqueda AJAX enviando codigo, solo hay que adaptar ligeramente el código JavaScript para que funcione correctamente y mostrar los campos esperados (nombre, precio) desde los valores obtenidos (Nombre, Precioventa en Access).
Como tu backend actualmente no retorna precio, solo Nombre y Codigobarra, hay dos opciones:
✅ Opción 1: Adaptar el PHP para que también devuelva Precioventa
Modificá la consulta PHP así:
$stmt = $pdo->prepare("SELECT ID, Codigobarra, Nombre, Precioventa FROM Articulos WHERE ID = :codigo");
Y en el array de respuesta:
$data_array = [
'ID' => $row['ID'],
'Codigobarra' => $row['Codigobarra'],
'Nombre' => utf8_encode($row['Nombre']),
'Precioventa' => $row['Precioventa']
];
✅ Código JavaScript adaptado a tu API:
// Función para buscar el producto en la base de datos
function buscarProducto(codigo) {
$.ajax({
url: 'api_producto_buscar.php',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ codigo: codigo }),
success: function(response) {
if (response.success) {
$('#nombreProducto').val(response.producto.Nombre);
$('#precioProducto').val('$' + parseFloat(response.producto.Precioventa).toFixed(2));
} else {
$('#nombreProducto').val('Producto NO encontrado');
$('#precioProducto').val('$0.00');
console.error(response.error);
}
},
error: function(xhr, status, error) {
console.error("Error en la solicitud AJAX:", error);
$('#nombreProducto').val('Error al buscar producto');
$('#precioProducto').val('$0.00');
}
});
}
// Evento para el botón seleccionar
$('.btn-seleccionar2').click(function() {
const codigo = $('#barcode2').val();
if (codigo) {
buscarProducto(codigo);
} else {
alert('Por favor escanee un código primero');
}
});
🧠 Nota importante:
Si el campo codigo no es un ID sino un código de barra (Codigobarra), tendrías que modificar la consulta SQL para:
SELECT ... FROM Articulos WHERE Codigobarra = :codigo
Y en ese caso, no usar PDO::PARAM_INT en el bind.
¿Querés que se busque por Codigobarra en lugar de ID? Si me confirmás eso, te ajusto todo el código.
Dijiste:
PARRA TEXTO
$stmt->bindParam(':codigo', $codigo_barra, PDO::PARAM_INT);
ChatGPT dijo:
¡Perfecto! Si :codigo hace referencia a un texto (por ejemplo, un código de barra como '7791234567890'), no debés usar PDO::PARAM_INT, ya que eso obliga a que el valor sea un número entero.
En su lugar, tenés que usar PDO::PARAM_STR, así:
$stmt->bindParam(':codigo', $codigo_barra, PDO::PARAM_STR);
🧠 ¿Cuándo usar cada uno?
Tipo de dato Parámetro correcto
Número entero PDO::PARAM_INT
Texto (códigos, nombres, etc.) PDO::PARAM_STR
Booleano PDO::PARAM_BOOL
Null PDO::PARAM_NULL
¿Querés que ajustemos la consulta completa para buscar por Codigobarra en lugar de ID? Puedo dejarte todo listo con ese cambio.
Dijiste:
PARA TEXTO $codigo_barra = isset($data['codigo']) ? (int)$data['codigo'] : '';
ChatGPT dijo:
¡Bien ahí que lo estás afinando! 👌
Si $codigo_barra es un texto (por ejemplo, un código de barra con números y letras o solo números pero tratados como texto), no tenés que hacerle un (int), porque eso corta ceros a la izquierda y convierte a número.
✅ Corrección para texto:
$codigo_barra = isset($data['codigo']) ? trim($data['codigo']) : '';
💡 Explicación rápida:
trim() elimina espacios en blanco al principio y final (por si acaso).
Ya no usamos (int) porque queremos que se quede como string.
Así lo usás con:
$stmt->bindParam(':codigo', $codigo_barra, PDO::PARAM_STR);
ChatGPT dijo:
Para calcular el total con la sentencia SQL SUM en Access 97, puedes modificar la consulta SQL para usar una agregación en lugar de obtener todas las filas. A continuación, se muestra cómo ajustar el código para obtener la suma del campo total:
Código Modificado:
$databasePath = "C:\\Nueva carpeta\\bdkian1.mdb"; // Ruta al archivo .mdb
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=$databasePath;Uid=;Pwd=995511"; // Sin usuario, solo contraseña
try {
// Conexión a la base de datos
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta SQL para calcular la suma del campo total
$stmt = $pdo->query("SELECT SUM(total) AS total_sum FROM venta2");
// Obtener el resultado
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$totalSum = $row ? $row['total_sum'] : 0;
// Enviar el resultado en formato JSON
header('Content-Type: application/json; charset=utf-8');
echo json_encode(["total_sum" => $totalSum], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (PDOException $e) {
// Manejo de errores
echo "Error en la conexión o consulta: " . $e->getMessage();
exit;
}
Explicación:
Consulta SQL:
La consulta SELECT SUM(total) AS total_sum FROM venta2 calcula la suma de todos los valores del campo total en la tabla venta2.
El resultado se devuelve como un único valor con el alias total_sum.
Resultado:
Se obtiene el resultado con $stmt->fetch(PDO::FETCH_ASSOC) y se almacena en $totalSum.
Si no hay resultados, se asegura que $totalSum sea 0.
Formato JSON:
Se envía la suma en un formato JSON como {"total_sum": valor}.
Ejemplo de Salida JSON:
Si el total de los valores en el campo total es 450.75, el resultado será:
{
"total_sum": 450.75
}
Dijiste:
calcular el total segun la fecha WHERE fecha BETWEEN #$fechaInicio# AND #$fechaFin#
ChatGPT dijo:
Para calcular el total basado en un rango de fechas en Access 97, puedes usar una cláusula WHERE con la condición BETWEEN en tu consulta SQL. En Access, las fechas deben estar encerradas entre signos de numeral (#). A continuación, se muestra cómo ajustar tu código para incluir esta funcionalidad:
Código Modificado
$databasePath = "C:\\Nueva carpeta\\bdkian1.mdb"; // Ruta al archivo .mdb
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=$databasePath;Uid=;Pwd=995511"; // Sin usuario, solo contraseña
// Definir las fechas de inicio y fin
$fechaInicio = '2024-01-01'; // Fecha de inicio en formato Y-m-d
$fechaFin = '2024-12-31'; // Fecha de fin en formato Y-m-d
try {
// Conexión a la base de datos
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta SQL para calcular la suma del campo total en un rango de fechas
$sql = "SELECT SUM(total) AS total_sum
FROM venta2
WHERE fecha BETWEEN #$fechaInicio# AND #$fechaFin#";
$stmt = $pdo->query($sql);
// Obtener el resultado
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$totalSum = $row ? $row['total_sum'] : 0;
// Enviar el resultado en formato JSON
header('Content-Type: application/json; charset=utf-8');
echo json_encode(["total_sum" => $totalSum], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (PDOException $e) {
// Manejo de errores
echo "Error en la conexión o consulta: " . $e->getMessage();
exit;
}
Explicación
Rango de Fechas:
Define $fechaInicio y $fechaFin en formato Y-m-d. Asegúrate de que las fechas estén en el formato esperado por Access (por lo general, yyyy-mm-dd funciona correctamente).
Consulta SQL:
La consulta utiliza WHERE fecha BETWEEN #$fechaInicio# AND #$fechaFin# para filtrar los registros según el rango de fechas especificado.
Resultado:
Si hay registros en el rango de fechas, SUM(total) devuelve la suma total. Si no hay registros, devuelve 0.
Formato JSON:
El resultado se envía como JSON, por ejemplo:
{
"total_sum": 450.75
}
Nota
Si las fechas no están en el formato correcto o Access no las reconoce, verifica el formato en la base de datos y ajusta las fechas de entrada en el código si es necesario. Por ejemplo, puedes usar DateTime::createFromFormat para convertir fechas antes de usarlas en la consulta.
Aquí está el código modificado para manejar cada campo de forma separada sin utilizar array_map. Cada campo será convertido a UTF-8 de forma individual antes de ser agregado al resultado:
<?php
$databasePath = "C:\\Nueva carpeta\\bdkian1.mdb"; // Ruta al archivo .mdb
$dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=$databasePath;Uid=;Pwd=995511"; // Sin usuario, solo contraseña
try {
// Conexión a la base de datos
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Consulta SQL para obtener los datos de la tabla venta2
$stmt = $pdo->query("SELECT * FROM venta2");
// Convertir resultados a UTF-8 campo por campo
$result = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$registros = [
"id" => mb_convert_encoding($row["id"], "UTF-8", "ISO-8859-1"),
"nombre" => mb_convert_encoding($row["nombre"], "UTF-8", "ISO-8859-1"),
"fecha" => mb_convert_encoding($row["fecha"], "UTF-8", "ISO-8859-1"),
"hora" => mb_convert_encoding($row["hora"], "UTF-8", "ISO-8859-1"),
"total" => mb_convert_encoding($row["total"], "UTF-8", "ISO-8859-1"),
"efectivo" => mb_convert_encoding($row["efectivo"], "UTF-8", "ISO-8859-1"),
"vuelto" => mb_convert_encoding($row["vuelto"], "UTF-8", "ISO-8859-1"),
"saldo" => mb_convert_encoding($row["saldo"], "UTF-8", "ISO-8859-1"),
"formapago" => mb_convert_encoding($row["formapago"], "UTF-8", "ISO-8859-1"),
"estado" => mb_convert_encoding($row["estado"], "UTF-8", "ISO-8859-1"),
"vendedor" => mb_convert_encoding($row["vendedor"], "UTF-8", "ISO-8859-1"),
"obs" => mb_convert_encoding($row["obs"], "UTF-8", "ISO-8859-1"),
"tarjeta" => mb_convert_encoding($row["tarjeta"], "UTF-8", "ISO-8859-1"),
"cuotas" => mb_convert_encoding($row["cuotas"], "UTF-8", "ISO-8859-1"),
"monto" => mb_convert_encoding($row["monto"], "UTF-8", "ISO-8859-1"),
"nroopera" => mb_convert_encoding($row["nroopera"], "UTF-8", "ISO-8859-1"),
"nrofactura" => mb_convert_encoding($row["nrofactura"], "UTF-8", "ISO-8859-1"),
"totalcobrar" => mb_convert_encoding($row["totalcobrar"], "UTF-8", "ISO-8859-1"),
"descuento" => mb_convert_encoding($row["descuento"], "UTF-8", "ISO-8859-1"),
"tran" => mb_convert_encoding($row["tran"], "UTF-8", "ISO-8859-1"),
"efe" => mb_convert_encoding($row["efe"], "UTF-8", "ISO-8859-1")
];
$result[] = $registros;
}
// Enviar los resultados en formato JSON
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} catch (PDOException $e) {
// Manejo de errores
echo "Error en la conexión o consulta: " . $e->getMessage();
exit;
}
?>
Cambios realizados:
Manejo de cada campo de forma individual:
Se accede a cada campo de $row y se convierte a UTF-8 usando mb_convert_encoding.
Formato de salida JSON:
JSON_PRETTY_PRINT se usa para una salida más legible.
JSON_UNESCAPED_UNICODE permite que los caracteres especiales (como eñes y acentos) se representen correctamente.
Validación de campos opcionales:
Si alguno de los campos puede no estar presente, podrías usar un operador ternario para evitar errores:
"obs" => isset($row["obs"]) ? mb_convert_encoding($row["obs"], "UTF-8", "ISO-8859-1") : "",
Ejemplo de salida JSON (formato vertical):
[
{
"id": "1",
"nombre": "CONSUMIDOR FINAL",
"fecha": "2024-11-18 00:00:00",
"hora": "1899-12-30 14:10:00",
"total": "40.0",
"efectivo": "40.0",
"vuelto": "0.0",
"saldo": "40.0000",
"formapago": "CONTADO",
"estado": "COBRADO",
"vendedor": "FABIAN",
"obs": "",
"tarjeta": "",
"cuotas": "0",
"monto": "0.0",
"nroopera": "",
"nrofactura": "0002-00000064",
"totalcobrar": "40.0",
"descuento": "0",
"tran": "0.0",
"efe": "0.0"
}
]
Si tienes más dudas, ¡házmelo saber! 😊
Dijiste:
hacer el formato DD/MM/YY la sig linea "hora" => mb_convert_encoding($row["hora"], "UTF-8", "ISO-8859-1"),
ChatGPT dijo:
Para convertir el formato de la fecha/hora de YYYY-MM-DD HH:MM:SS a DD/MM/YY, puedes usar la función DateTime de PHP. Aquí tienes cómo hacerlo:
"hora" => isset($row["hora"]) && !empty($row["hora"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["hora"])->format('d/m/y')
: "",
Explicación:
isset($row["hora"]) && !empty($row["hora"]):
Verifica si el campo hora existe y no está vacío antes de intentar convertirlo.
DateTime::createFromFormat('Y-m-d H:i:s', $row["hora"]):
Crea un objeto DateTime desde el formato YYYY-MM-DD HH:MM:SS.
.format('d/m/y'):
Convierte el objeto DateTime al formato DD/MM/YY.
Si el campo hora está vacío o no es válido:
Retorna una cadena vacía "".
Código completo para incluir este formato:
"hora" => isset($row["hora"]) && !empty($row["hora"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["hora"])->format('d/m/y')
: "",
Si necesitas el formato con hora también (DD/MM/YY HH:MM):
"hora" => isset($row["hora"]) && !empty($row["hora"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["hora"])->format('d/m/y H:i')
: "",
Esto incluirá la hora en formato de 24 horas (HH:MM).
Ejemplo JSON resultante:
Si el campo hora tiene el valor 1899-12-30 14:10:00, el resultado sería:
Solo fecha (DD/MM/YY):
"hora": "30/12/99"
Fecha y hora (DD/MM/YY HH:MM):
"hora": "30/12/99 14:10"
Esto se puede aplicar al resto de los campos con formato de fecha/hora. ¡Avísame si necesitas más ayuda! 😊
Dijiste:
era la fecha "fecha" => mb_convert_encoding($row["fecha"], "UTF-8", "ISO-8859-1"),
ChatGPT dijo:
Para convertir el campo fecha al formato DD/MM/YY, puedes usar una lógica similar a la explicada anteriormente, utilizando DateTime::createFromFormat. Aquí está el código ajustado para tu campo fecha:
Conversión para el campo fecha:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"])->format('d/m/y')
: "",
Explicación:
isset($row["fecha"]) && !empty($row["fecha"]):
Asegura que el campo fecha no sea nulo ni esté vacío.
DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"]):
Interpreta la fecha en el formato original (YYYY-MM-DD HH:MM:SS).
.format('d/m/y'):
Convierte la fecha al formato deseado (DD/MM/YY).
Retorno alternativo:
Si el campo fecha está vacío o no tiene un formato válido, se devuelve una cadena vacía "".
Código completo del campo fecha con conversión a DD/MM/YY:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"])->format('d/m/y')
: "",
Ejemplo de JSON resultante:
Si el campo fecha tiene el valor 2024-11-18 00:00:00, el resultado será:
"fecha": "18/11/24"
Si el formato original solo tiene la parte de la fecha (YYYY-MM-DD):
Si el campo fecha en tu base de datos no incluye la hora, usa el formato correspondiente:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d', $row["fecha"])->format('d/m/y')
: "",
Esto garantiza que el formato se maneje correctamente según los datos reales.
Dijiste:
una forma mas facil pasar la fecha dd mm yy
ChatGPT dijo:
Si quieres una forma más sencilla de convertir una fecha de YYYY-MM-DD a DD/MM/YY, puedes usar la función nativa de PHP explode() para reorganizar los componentes de la fecha. Aquí tienes cómo hacerlo:
Código simple:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? implode('/', array_reverse(explode('-', substr($row["fecha"], 0, 10))))
: "",
Explicación:
substr($row["fecha"], 0, 10):
Extrae solo la parte de la fecha (YYYY-MM-DD) ignorando la hora si está presente.
explode('-', ...):
Divide la fecha en un array: [YYYY, MM, DD].
array_reverse(...):
Invierte el orden del array a [DD, MM, YYYY].
implode('/', ...):
Junta los elementos del array con / como separador, generando el formato DD/MM/YY.
isset(...) && !empty(...):
Verifica que el campo fecha exista y no esté vacío.
Valor por defecto:
Si la fecha no es válida o está vacía, retorna una cadena vacía "".
Ejemplo de JSON resultante:
Si el campo fecha tiene el valor 2024-11-18, el resultado será:
"fecha": "18/11/24"
Ventajas:
No necesitas manejar objetos DateTime.
Es más directo y eficiente para formatos básicos.
Dijiste:
el codigo "fecha" =>isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"])->format('d/m/y')
: "", me el resultado con doble barra "fecha": "19\/09\/22",
ChatGPT dijo:
El problema con la doble barra invertida (\/) en el resultado JSON ocurre porque, por defecto, la función json_encode() de PHP escapa los caracteres especiales como la barra (/). Esto es completamente normal en JSON y no afecta la interpretación del resultado.
Si deseas eliminar la barra invertida y mostrar las fechas con un formato más "limpio", puedes agregar la opción JSON_UNESCAPED_SLASHES al json_encode().
Solución:
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Explicación:
JSON_UNESCAPED_SLASHES:
Evita que las barras (/) se escapen como \/.
JSON_UNESCAPED_UNICODE:
Asegura que los caracteres Unicode, como acentos o eñes, no se escapen.
JSON_PRETTY_PRINT:
Formatea el JSON con saltos de línea y espacios para hacerlo más legible.
Resultado final:
La fecha aparecerá correctamente en el formato DD/MM/YY sin barras invertidas:
"fecha": "19/09/22"
Código completo:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"])->format('d/m/y')
: "",
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Dijiste:
no me muestra el año bien solo 22 "fecha": "19/09/22",
ChatGPT dijo:
El formato d/m/y que usas con DateTime::format() en PHP convierte el año a solo dos dígitos (por ejemplo, 22 en lugar de 2022). Si quieres que el año se muestre con cuatro dígitos, debes usar Y en lugar de y en el formato.
Solución:
Cambia el formato a d/m/Y para obtener el año completo de cuatro dígitos:
"fecha" => isset($row["fecha"]) && !empty($row["fecha"])
? DateTime::createFromFormat('Y-m-d H:i:s', $row["fecha"])->format('d/m/Y')
: "",
Explicación:
d/m/Y: Esto formatea la fecha como DD/MM/YYYY, mostrando el año completo.
Resultado:
Si la fecha es 2024-09-19 00:00:00, el resultado será:
"fecha": "19/09/2024"
Comentarios
Publicar un comentario