-1

I created two classes: a class called index.php for a user to input data such as: name, email, phone number and address. And the other class called model.php, which must send the information that the user typed into the MySQL database. However, when a user enters the information in the graphical interface, and then clicks the submit button, the localhost MySQL database is not receiving the data. The name of the database is called "crud", and the name of the database table inside the crud is called: "gravacoes".

Please, can anyone help me?

index.php code:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
    <title>Hello, world!</title>
  </head>
  <body>
  <div class = "container">
    <div class = "row">
      <div class = "col-md-12 mt-5">
        <h1 class = "text-center">PHP OOP CRUD TUTORIAL</h1>
        <hr style = "height: 1px; color: black; background-color:black;">
      </div>
    </div>
    <div class = "row">
      <div class = "col-md-5 mx-auto">
        <?php
        include 'model.php';
        $model = new Model();
        $insert = $model->insert();
        ?>
        <form action = "" method = "post">
          <div class = "form-group">
            <label for = "">Name</label>
            <input type = "text" name = "name" class = "form-control">
        </div>

          <div class = "form-group">
            <label for = "">Email</label>
            <input type = "email" name = "email" class = "form-control">
          </div>

          <div class = "form-group">
            <label for = "">Mobile No.</label>
            <input type = "text" name = "mobile" class = "form-control">
          </div>

          <div class = "form-group">
            <label for = "">Address</label>
            <textarea name ="address" id = "" cols = "" rows = "3" class = "form-control"></textarea>
            <br />
          </div>

          <div class = "form-group">
            <button type = "submit" name = "submit" class = "btn btn-primary">Submit</button>
          </div>
        </form>
      </div>
    </div>
  </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
  </body>
</html> 

Code of model.php:

<?php
class Model {
    private $server = "localhost";
    private $username ="root";
    private $password;
    private $db = "crud";
    private $conn;

    public function __construct(){
        try {
            $this->conn = new mysqli($this->server, $this->username, $this->password, $this->db);
        } catch (Exception $e){
            echo "Connection failed". $e->getMessage();
        }
    }

    public function insert() {
        if(isset($_POST['submit'])) {
            if(isset($_POST['name']) && isset($_POST['email']) && isset($_POST['mobile']) && isset($_POST['address'])) {
                if(!empty($_POST['name']) && !empty($_POST['email']) && !empty($_POST['mobile']) && !empty($_POST['address'])) {

                    $name =  $_POST['name'];
                    $mobile = $_POST['mobile'];
                    $email = $_POST['email'];
                    $address= $_POST['address'];    

                    $query = "INSERT INTO gravacoes (name, email, mobile, address) VALUES ('$name', '$email', '$mobile', '$address')";

                    if ($sql = $this->conn->query($query)) {
                        echo "<script>alert('Success');</script>";
                        echo "<script>window, location.href = 'index.php';</script>";
                    } else {
                        echo "<script>alert('Failed');</script>";
                        echo "<script>window.location.href='index.php';</script>";
                    }
                    
                } else {
                    echo "<script>alert('Empty');</script>";
                    echo "<script>window.location.href = 'index.php';</script>";
                }

            }
        }
    }
}
?>
  • I don't see a class in `index.php`. – Barmar May 31 '21 at 21:03
  • You have no code in `index.php` that calls the `Model` class when the form is submitted. – Barmar May 31 '21 at 21:04
  • 1
    Your code is wide open to SQL-injection. You should use prepared statements with parameters instead of substituting variables directly into the SQL string. – Barmar May 31 '21 at 21:06
  • Barmar, please, check the lines 19-23, in the index.php: insert(); ?> – Michael Stuart May 31 '21 at 21:09
  • Thanks, I missed that. Mixing the code into the middle of the HTML is confusing. – Barmar May 31 '21 at 21:10
  • You don't need to test both `isset()` and `!isempty()`. `isempty()` checks `isset()` first. – Barmar May 31 '21 at 21:11
  • Regarding SQL-injection: OK, I am humbly learning. – Michael Stuart May 31 '21 at 21:11
  • Are you getting either of the alerts? – Barmar May 31 '21 at 21:13
  • No, the code is not showing the alerts. Could you copy, paste and test to your IDE, please? :) – Michael Stuart May 31 '21 at 21:14
  • What do you see when you click the submit button? – Barmar May 31 '21 at 21:15
  • Check the browser console to see if there are any errors when it's submitting the form. Use the Network tab to see the form submission. – Barmar May 31 '21 at 21:16
  • When you click the submit button, the code does shows the message: "Failed". Just it. – Michael Stuart May 31 '21 at 21:16
  • Then maybe you should show something more useful than "failed" in your output. https://www.php.net/manual/en/mysqli.error.php – miken32 May 31 '21 at 21:35
  • Also, echoing javascript output from a controller method is really messy coding. You should be looking at better separation of your PHP and HTML. – miken32 May 31 '21 at 21:37
  • It's showing `Failed` in the HTML instead of displaying it as an alert? Do you have any JavaScript that's submitting the form using AJAX instead of doing normal form submission? – Barmar May 31 '21 at 21:49
  • Please, it is much better you copy and paste the code on your IDE, and then you check and fix the error, is it ok for you, my friends? – Michael Stuart May 31 '21 at 21:56
  • **Warning:** You are wide open to [SQL Injections](https://php.net/manual/en/security.database.sql-injection.php) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Jun 01 '21 at 09:02

1 Answers1

0

You are doing approximately everything right, one thing is not right is that your trying to catch Exception from database connection, and mysqli object do not throw any exceptions by default, so try first to enable error reporting:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$this->conn = new mysqli($this->server, $this->username, $this->password, $this->db);

SQL injection warning:

You should be using prepared statement to insert data to your database to prevent SQL injection like:

$query = "INSERT INTO gravacoes (name, email, mobile, address) VALUES (?, ?, ?, ?)";

$st = $this->conn->prepare($query);

$st->bind_param("ssss", $name, $email, $mobile, $address);

$st->execute();

That's could be enough, but I prefer using PDO for this kind of logic, and also you can separate validation from model, so I made you another implementation, not the best but just to put you on the road:

First your model: it's the same but would be better if you separate db connection from your model:

model.php

class Model
{
    private $server = "localhost";

    private $username = "root";

    private $password = '';

    private $db = "crudd";

    private $conn;

    public function __construct()
    {
        try {
            $this->conn = new PDO("mysql:host=$this->server;dbname=$this->db", $this->username, $this->password);
        } catch (PDOException $e) {
            die('DATABASE CONNECTION ERROR: ' . $e->getMessage());
            //or you can throw your own exception to catch later
        }
    }

    public function insert($data)
    {
        $query = "INSERT INTO gravacoes (name, email, mobile, address) VALUES (:name, :email, :mobile, :address)";

        $res = $this->conn->prepare($query);

        $res->execute($data);

        return $res->rowCount(); // return number of affected rows, in this case return 1
    }
}

then I added a file that handle your form logic

functions.php

function handle_form()
{
    if (empty($_POST['name']) || empty($_POST['email']) || empty($_POST['mobile']) || empty($_POST['address'])) {
        throw new Exception("All fields must be filled");
    }

    // all filed are filled we can now include the model:

    $data = []; //empty array will populate with data

    $data['name'] = $_POST['name'];

    $data['email'] = $_POST['email'];

    $data['mobile'] = $_POST['mobile'];

    $data['address'] = $_POST['address'];

    require_once 'model.php';

    $model = new Model();

    $model->insert($data);
}

Then in your HTML

index.php

....
<div class="container">
    <div class="row">
        <div class="col-md-12 mt-5">
            <h1 class="text-center">PHP OOP CRUD TUTORIAL</h1>
            <hr style="height: 1px; color: black; background-color:black;">
        </div>
    </div>
    <div class="row">
        <div class="col-md-5 mx-auto">
            <?php
            include 'functions.php';
            if (isset($_POST['submit'])) {
                try {
                    handle_form();
                } catch (Exception $e) {
                    echo "<script>alert('" . $e->getMessage() . "');</script>";
                    echo "<script>window.location.href='index.php';</script>";
                    return;
                }

                echo "<script>alert('Success');</script>";
                echo "<script>window, location.href = 'index.php';</script>";
            }

            ?>
            <form action="" method="post">
                <div class="form-group">
                    <label for="">Name</label>
                    <input type="text" name="name" class="form-control">
                </div>
          ....
Dharman
  • 30,962
  • 25
  • 85
  • 135
butalin
  • 327
  • 3
  • 9
  • mysqli does throw exeptions. It's the recommended mode. Please do not check for errors manually. Read https://stackoverflow.com/questions/14578243/turning-query-errors-to-exceptions-in-mysqli – Dharman Jun 01 '21 at 09:03
  • FYI, catching exceptions is generally a bad idea if you are not going to recover from the error. I removed them. I left the one where you actually recover from it, but it's a terrible practice as you are basically losing the information. You should never catch exceptions like this – Dharman Jun 01 '21 at 09:11
  • So if the execute fails? – butalin Jun 01 '21 at 09:17
  • If the execute fails then PHP will throw an error. The user doesn't need to know what's the syntax error. All they need to know that the error was logged on the server and the administrators will take a look at it – Dharman Jun 01 '21 at 09:20
  • Sure the user doesn't need to know about the exception PDO is throwing and in your edited answer you are not catching it so it will be thrown and there is nothing can catch it, so if we use your code in production we will have security issues (un caught exception PDO...) – butalin Jun 01 '21 at 11:26
  • It will only be a security issue because you still catch the exception and display it to the user. If you remove the last try-catch there will be no security issue. If you want to add it back to your answer then show how to log the exception. It would be a better use. Or just remove all try-catch altogether. – Dharman Jun 01 '21 at 11:29