Portal de soporte en PHP con base de conocimiento, FAQ dinámicas y sugerencias automáticas, seguro y responsive con gestión de usuarios y MySQL.
<?php
// config.php - configuración de base de datos y ajustes generales
return [
'db_host' => 'localhost',
'db_name' => 'assistenza_clienti',
'db_user' => 'root',
'db_pass' => '',
'base_url' => 'http://localhost/assistenza',
'session_name' => 'assistenza_session',
];
// db.php - clase para gestión de conexión DB con PDO
class Database {
private $pdo;
public function __construct(array $config) {
$dsn = "mysql:host={$config['db_host']};dbname={$config['db_name']};charset=utf8mb4";
try {
$this->pdo = new PDO($dsn, $config['db_user'], $config['db_pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
} catch (PDOException $e) {
die("Error de conexión DB: " . $e->getMessage());
}
}
public function query(string $sql, array $params = []) {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
}
public function fetchAll(string $sql, array $params = []) {
return $this->query($sql, $params)->fetchAll();
}
public function fetch(string $sql, array $params = []) {
return $this->query($sql, $params)->fetch();
}
}
// auth.php - gestión de autenticación de usuarios
class Auth {
private $db;
public function __construct(Database $db) {
$this->db = $db;
if(session_status() === PHP_SESSION_NONE) {
session_start();
}
}
// Login de usuario con verificación de contraseña
public function login(string $email, string $password): bool {
$user = $this->db->fetch("SELECT * FROM utenti WHERE email = ?", [$email]);
if ($user && password_verify($password, $user['password_hash'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_email'] = $user['email'];
return true;
}
return false;
}
// Logout de usuario
public function logout(): void {
session_unset();
session_destroy();
}
// Verifica si el usuario está logueado
public function isLogged(): bool {
return isset($_SESSION['user_id']);
}
// Recupera datos del usuario logueado
public function getUser() {
if ($this->isLogged()) {
return $this->db->fetch("SELECT id, email, nome FROM utenti WHERE id = ?", [$_SESSION['user_id']]);
}
return null;
}
}
// ricerca.php - endpoint para búsqueda con sugerencias automáticas
require_once 'config.php';
require_once 'db.php';
$config = require 'config.php';
$db = new Database($config);
// Recupera consulta de búsqueda desde GET
$query = $_GET['q'] ?? '';
header('Content-Type: application/json; charset=utf-8');
if (strlen($query) < 3) {
echo json_encode(['error' => 'Ingrese al menos 3 caracteres para la búsqueda']);
exit;
}
// Buscar artículos de base de conocimiento y FAQ con LIKE
$sql = "SELECT 'articolo' AS tipo, id, titolo, contenuto FROM articoli_base_conoscenza WHERE titolo LIKE :q OR contenuto LIKE :q
UNION
SELECT 'faq' AS tipo, id, domanda AS titolo, risposta AS contenuto FROM faq WHERE domanda LIKE :q OR risposta LIKE :q
LIMIT 10";
$params = [':q' => "%$query%"];
$results = $db->fetchAll($sql, $params);
// Respuesta JSON con resultados
echo json_encode(['results' => $results]);
// index.php - página principal con búsqueda y visualización de resultados
/*
Nota: para simplicidad el código HTML y PHP están en el mismo archivo.
En producción se recomienda separar lógica y presentación.
*/
require_once 'config.php';
require_once 'db.php';
require_once 'auth.php';
$config = require 'config.php';
$db = new Database($config);
$auth = new Auth($db);
// Gestión de login POST
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
if ($auth->login($email, $password)) {
header('Location: index.php');
exit;
} else {
$error_login = 'Credenciales no válidas';
}
}
// Gestión de logout
if (isset($_GET['logout'])) {
$auth->logout();
header('Location: index.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Portal de Soporte al Cliente</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="container mt-4">
<h1>Portal de Soporte al Cliente</h1>
<?php if ($auth->isLogged()): ?>
<p>Bienvenido, <strong><?=htmlspecialchars($auth->getUser()['nome'])?></strong> | <a href="?logout=1">Cerrar sesión</a></p>
<?php else: ?>
<form method="post" class="mb-4">
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Contraseña</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<?php if (!empty($error_login)): ?>
<div class="alert alert-danger"><?=htmlspecialchars($error_login)?></div>
<?php endif; ?>
<button type="submit" name="login" class="btn btn-primary">Acceder</button>
</form>
<?php endif; ?>
<div class="mb-3">
<label for="search" class="form-label">Buscar en la base de conocimiento y FAQ</label>
<input type="text" id="search" class="form-control" placeholder="Ingrese al menos 3 caracteres...">
<div id="suggestions" class="list-group mt-1"></div>
</div>
<div id="results"></div>
</div>
<script>
$(document).ready(function() {
let timeout = null;
$('#search').on('input', function() {
clearTimeout(timeout);
const query = $(this).val();
if (query.length < 3) {
$('#suggestions').empty();
$('#results').empty();
return;
}
timeout = setTimeout(function() {
$.getJSON('ricerca.php', { q: query }, function(data) {
if (data.error) {
$('#suggestions').html('<div class="list-group-item text-danger">' + data.error + '</div>');
$('#results').empty();
return;
}
let suggestionsHtml = '';
data.results.forEach(function(item) {
suggestionsHtml += '<a href="#" class="list-group-item list-group-item-action" data-id="' + item.id + '" data-tipo="' + item.tipo + '">' +
'<strong>[' + item.tipo.toUpperCase() + ']</strong> ' + item.titolo + '</a>';
});
$('#suggestions').html(suggestionsHtml);
$('#results').empty();
});
}, 300);
});
// Mostrar contenido seleccionado
$('#suggestions').on('click', 'a', function(e) {
e.preventDefault();
const id = $(this).data('id');
const tipo = $(this).data('tipo');
// Solicitud para recuperar contenido detallado
$.getJSON('contenuto.php', { id: id, tipo: tipo }, function(data) {
if (data.error) {
$('#results').html('<div class="alert alert-danger">' + data.error + '</div>');
return;
}
let html = '<h3>' + data.titolo + '</h3><p>' + data.contenuto + '</p>';
$('#results').html(html);
});
});
});
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
// contenuto.php - endpoint para recuperación de contenido detallado
require_once 'config.php';
require_once 'db.php';
$config = require 'config.php';
$db = new Database($config);
$id = $_GET['id'] ?? null;
$tipo = $_GET['tipo'] ?? null;
header('Content-Type: application/json; charset=utf-8');
if (!$id || !$tipo || !in_array($tipo, ['articolo', 'faq'])) {
echo json_encode(['error' => 'Parámetros no válidos']);
exit;
}
if ($tipo === 'articolo') {
$sql = "SELECT titolo, contenuto FROM articoli_base_conoscenza WHERE id = ?";
} else {
$sql = "SELECT domanda AS titolo, risposta AS contenuto FROM faq WHERE id = ?";
}
$item = $db->fetch($sql, [$id]);
if (!$item) {
echo json_encode(['error' => 'Contenido no encontrado']);
exit;
}
echo json_encode($item);
?>Backend PHP 8+ con PDO para conexión segura a base de datos MySQL
Base de datos MySQL con tablas: usuarios, articulos_base_conocimiento, faq, sugerencias
Sistema de autenticación de usuarios con contraseñas hasheadas (password_hash)
Interfaz frontend HTML5/CSS3/JavaScript con Bootstrap 5 para diseño responsive
Módulo de búsqueda con sugerencias automáticas basadas en consultas SQL LIKE y búsqueda de texto completo
API REST interna para recuperación dinámica de FAQ y sugerencias en JSON
Archivo de configuración config.php con parámetros de BD, sesiones y seguridad
Dependencias de software: PHP PDO, Bootstrap 5, jQuery 3.x
Configuración de wiring/pinout Arduino no aplicable (software basado en web)
Configuración del servidor: Apache/Nginx con PHP-FPM, MySQL 5.7+
Archivo .htaccess para reescritura de URL y seguridad
Gestión de errores y logging con try/catch y archivos de log