0

the problem I have is the following: I have a form to register in a web, which must send data to two tables (users_data and users_login). The users_data table has as PK idUser The users_login table has as FK idUser, to relate it with users_data. How can I do so that when filling the form, it sends each data to its corresponding table? I attach the code below

HTML - FORM

<div class="container-form">
            <h4>REGISTRO DE USUARIO</h4>
            <form class="form" method="post" action="./router.php">
                <label>Nombre</label>
                <input class="controls" type="text" name="nombre" placeholder="Ingrese su nombre" required>
                <label>Apellidos</label>
                <input class="controls" type="text" name="apellidos" placeholder="Ingrese sus apellidos" required>
                <label>Correo electrónico</label>
                <input class="controls" type="email" name="email" placeholder="Ingrese su correo electrónico" title="example@example.com" required>
                <label>Teléfono</label>
                <input class="controls" maxlength="9" minlength="9" name="telefono" title="Sólo números" type="tel"  placeholder="Ingrese su número de teléfono" required pattern="[0-9]+">
                <label>Fecha de nacimiento</label>
                <input class="controls" type="date" name="fnac" placeholder="Ingrese su fecha de nacimiento" required title="DD/MM/YYYY">
                <label>Dirección</label>
                <input class="controls" type="text" name="direccion" placeholder="Ingrese su dirección">
                <label>Sexo</label>
                <input class="controls" type="text" name="sexo" placeholder="Ingrese su sexo">
                <label>Contraseña</label>
                <input class="controls" type="password" name="contrasena" required>
                <input class="btn btn-outline-primary btn-lg w-100 mt-4" type="submit" name="registrarse" value="Registrarme">
            </form>
            <div class="text-center mt-3">
                <p>¿Ya tienes una cuenta?</p>
                <a class="text-center" href="./login.php">Inicia sesión aqui</a>
            </div>
        </div>

const SERVIDOR = 'localhost';
const BD = 'trabajo_final_php';
const USUARIO = 'root';
const PASSWORD = 'root';

class DB
{

    public static function conn()
    {
        // conexión a la base de datos
        try {
            $conn = new PDO("mysql:host=" . SERVIDOR . ";dbname=" . BD, USUARIO, PASSWORD);
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $conn;
        } catch (PDOException $e) {
            echo 'HA FALLADO LA CONEXIÓN: ' . $e->getMessage();
        }
    }

    /**
     * Comprueba que un usuario existe en la DB y devuelve un array de objetos con los registros de la tupla (id,nombre,email,contrasena,rol)
     * @param type $email;
     * @return array 
     */

    public static function comprobarUsuario($email)
    {
        $result = [];
        $conexion = self::conn();
        $sentencia = "SELECT * FROM users_data WHERE email = :email";
        $consulta = $conexion->prepare($sentencia);
        $consulta->execute(array(":email" => $email));
        while ($fila = $consulta->fetch(PDO::FETCH_OBJ)) {
            array_push($result, $fila);
        }
        $consulta->closeCursor();
        $conexion = null;
        return $result;
    }

    /**
     * Comprueba que un usuario existe en la DB y devuelve un array de objetos con los registros de la tupla (id,nombre,email,contrasena,rol)
     * @param type $id;
     * @return array 
     */

    public static function buscarId($id)
    {
        $result = [];
        $conexion = self::conn();
        $sentencia = "SELECT * FROM users_data WHERE id = :id";
        $consulta = $conexion->prepare($sentencia);
        $consulta->execute(array(":id" => $id));
        while ($fila = $consulta->fetch(PDO::FETCH_OBJ)) {
            array_push($result, $fila);
        }
        $consulta->closeCursor();
        $conexion = null;
        return $result;
    }

  

    /**
     * inserta usuario en la tabla users_data (registro)
     * @param type $nombre; @param type $apellidos; @param type $email; @param type $telefono;
     * @param type $fnac; @param type $direccion; @param type $sexo; @param type $contrasena;
     */

    public static function registrar($nombre, $apellidos, $email, $telefono, $fnac, $direccion, $sexo)
    {
        $conexion = self::conn();
        $sentencia = "INSERT INTO users_data (nombre, apellidos, email, telefono, fnac, direccion, sexo) VALUES (:nombre, :apellidos, :email, :telefono, :fnac, :direccion, :sexo)";
        $consulta = $conexion->prepare($sentencia);
        $consulta->bindParam(":nombre", $nombre);
        $consulta->bindParam(":apellidos", $apellidos);
        $consulta->bindParam(":email", $email);
        $consulta->bindParam(":telefono", $telefono);
        $consulta->bindParam(":fnac", $fnac);
        $consulta->bindParam(":direccion", $direccion);
        $consulta->bindParam(":sexo", $sexo);
        $consulta->execute();
        $consulta->closeCursor();
        $conexion = null;
    }

    /**
     * inserta en la tabla users_login
     * @param type $contrasena
     * @param type $rol
     */

    public static function loginUsers($contrasena, $rol) 
    {
        $conexion = self::conn();
        $sentencia = "INSERT INTO users_login (contrasena, rol) VALUES (:contrasena, :rol)";
        $rol = "user";
        $consulta = $conexion->prepare($sentencia);
        $consulta->bindParam(":contrasena", $contrasena);
        $consulta->bindParam(":rol", $rol);
        $consulta->execute();
        $consulta->closeCursor();
        $conexion = null;
    }


}

include './DB.php';

class ControllerLogin
{

    public function __construct()
    {
        session_start();
    }

    /**
     * inserta usuario en users_data (registro) si no lo esta ya registrado
     * @param type $nombre; @param type $apellidos; @param type $email; @param type $telefono;
     * @param type $fnac; @param type $direccion; @param type $sexo; @param type $contrasena;
     */

    public function registrarUsuario($nombre, $apellidos, $email, $telefono, $fnac, $direccion, $sexo, $contrasena, $rol)
    {
        $result = $this->buscarUsuario($email);
        if ($result[0]) {
            header('location:registro.php?registro=ko');
            exit();
        } else {
            DB::registrar($nombre, $apellidos, $email, $telefono, $fnac, $direccion, $sexo, $contrasena);
            DB::loginUsers($contrasena, $rol);
            $user = DB::comprobarUsuario($email);
            $_SESSION['usuario'] = [$user[0]->id, $user[0]->nombre, $user[0]->rol];
            header('location:./ControlPanel.php?registro=ok');
        }
    }

    /**
     * comprueba el login con el email y la contraseña
     * @param type $email;
     * @param type $contrasena;
     * @return type
     */

    public function comprobarUsuario($email, $contrasena = null)
    {
        // si encuentra el usuario la variable found devuelve true
        $found = false;
        $result = DB::comprobarUsuario($email);
        if (count($result) === 1) {
            if ($email === $result[0]->email && password_verify($contrasena, $result[0]->contrasena)) {
                $found = true;
            }
        }
        return [$found, ['id' => $result[0]->id, 'rol' => $result[0]->rol]];
    }

    /**
     * devuelve true si encuentra el usuario mediante el email
     * @param type $email;
     * @return type
     */

    public function buscarUsuario($email)
    {
        $found = false;
        $result = DB::comprobarUsuario($email);
        if (count($result) === 1) {
            $found = true;
        }
        return [$found];
    }
}

include './controllerLogin.php';

if (isset($_POST['registrarse'])) {
   $nombre = htmlspecialchars($_POST['nombre']);
   $apellidos = htmlspecialchars($_POST['apellidos']);
   $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
   $telefono = filter_input(INPUT_POST, 'telefono', FILTER_SANITIZE_NUMBER_INT);
   $fnac = htmlspecialchars($_POST['fnac']);
   $direccion = htmlspecialchars($_POST['direccion']);
   $sexo = htmlspecialchars($_POST['sexo']);
   $pass = htmlspecialchars($_POST['contrasena']);
   $contrasena = password_hash($pass, PASSWORD_BCRYPT);

   $reg = new ControllerLogin();
   $reg->registrarUsuario($nombre, $apellidos, $email, $telefono, $fnac, $direccion, $sexo, $contrasena, $rol);
   unset($reg);
}

MYSQL

users_data contains the following data: idUser(PK), nombre, apellidos, email, telefono, fecha de nacimiento, direccion, sexo

users-login contains the following data: idLogin(PK), idUser(FK), usuario, contrasena, rol

in the users_login table, I would like the 'usuario' data to be the 'email' with which you register and insert in the users_data table

How can I insert each data in its corresponding table? thank you in advance :)

I don't understand how to do this

Miguel
  • 9
  • 5
  • You can simply run two separate INSERT queries, one after the other. It's not clear what the problem is, as your question is very broad / vague. Are you, perhaps, actually asking how to get the new idUser value back from the database so you can re-use it when inserting into users-login as the foreign key? If so, mysql (and mysqli and PDO libraries in PHP) contain functions to get the last inserted ID, they are quite easy to find out about online already. If that's not your question, then it's unclear exactly where you're stuck. – ADyson Dec 14 '22 at 12:56
  • 1
    use a stored procedure. Pass in values needing to be updated wrap it in transaction logic and issue two updates. if one fails both rollback. https://dev.mysql.com/doc/refman/8.0/en/commit.html and https://stackoverflow.com/questions/19905900/mysql-transaction-roll-back-on-any-exception for example The point of a sp and transaction logic is to ensure everything can execute before committing the results. if something fails; none of it should be updated and everything should be rolled back. All, or nothing is what transaction logic CAN do for you. – xQbert Dec 14 '22 at 13:09
  • You can also start, commit and rollback a transaction directly from PHP, without needing a stored procedure. So that is another option. Either way, as xQbert says, transactions can help with data integrity in the event of one of your queries failing. – ADyson Dec 14 '22 at 13:23
  • @ADyson I have updated the question with the code that I have, to see if this way it is better understood. I want that when the registration form is filled, each data of the form fills its corresponding field in each table. the users_data table is filled, but the users_login table is not and I don't know why. – Miguel Dec 14 '22 at 14:24
  • I have updated the question with the code that I have, to see if this way it is better understood. I want that when the registration form is filled, each data of the form fills its corresponding field in each table. the users_data table is filled, but the users_login table is not and I don't know why. – Miguel Dec 14 '22 at 14:24
  • We can't really tell, just from that. Read about [PDO error handling](https://stackoverflow.com/questions/32648371/why-does-this-pdo-statement-silently-fail) and see if you can get some information about the failure - if PDO is throwing an error, you need to see the error details to find out what the database is complaining about. – ADyson Dec 14 '22 at 14:27
  • P.S. `$conexion = self::conn();` is everywhere....why are you making a new connection to the database each time you run a query? That is not necessary. It's a crazy way to program, and you will soon overload your database server with too many connections, if you go live with such code. Instead, make the connection object as a property of your DB class, and in the DB class constructor, you should connect _once_ to mysql, and store the resulting PDO object in the class property. Then, all the other functions (which really shouldn't be static) can re-use it for every query. – ADyson Dec 14 '22 at 14:29
  • Anyway, my _guess_ (until you tell us a clear error message) is that because you are only inserting `contrasena` and `rol` into the users-login table, it's going to complain that there is no value provided for either idUser or usario (or possibly both)...I'd imagine that at least one of those is not allowed to be NULL. – ADyson Dec 14 '22 at 14:32
  • @ADyson Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 1364 Field 'idUser' doesn't have a default value in C:\xampp\htdocs\MASTER-D\trabajo_final_php\php\DB.php:114 Stack trace: #0 C:\xampp\htdocs\MASTER-D\trabajo_final_php\php\DB.php(114): PDOStatement->execute() #1 C:\xampp\htdocs\MASTER-D\trabajo_final_php\php\controllerLogin.php(27): DB::loginUsers('$2y$10$eDSA9KxH...', 'user' – Miguel Dec 14 '22 at 14:40
  • @ADyson #2 C:\xampp\htdocs\MASTER-D\trabajo_final_php\php\router.php(18): ControllerLogin->registrarUsuario('ss', 'ss', 'ss@ss.ss', '123987124', '1987-03-23', 'Calle Los Pinos...', 'F', '$2y$10$eDSA9KxH...', NULL) #3 {main} thrown in C:\xampp\htdocs\MASTER-D\trabajo_final_php\php\DB.php on line 114 – Miguel Dec 14 '22 at 14:41
  • It's exactly what I thought, then. You need to provide a value for idUser (because it can't be NULL, and there's no default value set in the database config). Which goes back to what I said in my very first comment. – ADyson Dec 14 '22 at 14:42
  • @ADyson but the idUser (FK) of the users_login table has to be taken from the idUser(PK) of the users_data table, how do I do it? – Miguel Dec 14 '22 at 14:53
  • Read my first comment again. _"mysql (and mysqli and PDO libraries in PHP) contain functions to get the last inserted ID, they are quite easy to find out about online already"_ – ADyson Dec 14 '22 at 14:54
  • (N.B. This will require you to use the same PDO connection object for all the queries, because the last inserted ID it returns is specific to that connection. See [another earlier comment](https://stackoverflow.com/questions/74798594/how-can-i-insert-data-to-two-different-tables-from-the-same-form?noredirect=1#comment132008919_74798594) regarding that issue in your code.) – ADyson Dec 14 '22 at 14:55
  • P.S. this isn't good: `} catch (PDOException $e) { echo 'HA FALLADO LA CONEXIÓN: ' . $e->getMessage(); }`...why are you catching a connection error? It's not like you can recover from it and carry on - but because of your `catch`, that's exactly what the code will try and do! There's no need to catch it. Just let it fail, and let PHP handle it however it's been configured to (e.g. by logging the error to a file). That's safer, too, than echoing potentially sensitive connection and error data onto the screen for anyone to see (in a live system). Don't expose this data to potential hackers! – ADyson Dec 14 '22 at 14:57
  • P.P.S. Your usage of `htmlspecialchars()` is inappropriate and potentially problematic. `htmlspecialchars()` is an _output_ filter, only to be used _specifically_ when _outputting_ data into a HTML document. It is designed only to help protect against XSS. It should not be used at any other time, such as when receiving input data -in the worst case it can change or corrupt your data in that situation. It also has nothing to do with preventing SQL injection. See [when to use htmlspecialchars() function?](https://stackoverflow.com/questions/4882307/when-to-use-htmlspecialchars-function) – ADyson Dec 14 '22 at 14:58
  • Hint, regarding the idUser problem: https://www.php.net/manual/en/pdo.lastinsertid.php – ADyson Dec 14 '22 at 14:59
  • @ADyson What do you recommend me to use to replace htmlspecialchars()? Thank you for your time, it is helping me a lot and I really appreciate it. – Miguel Dec 14 '22 at 15:29
  • Nothing. You don't need to replace it at all in the place you're using it. Simply remove it from there. What you do need to do though, is use it in your UI at the appropriate moments (as I described above). – ADyson Dec 14 '22 at 15:40

0 Answers0