MySQL Update

Revamping Data with Precision

The next logical step in our MySQL progression is updating an existing resource. We’re going to introduce the differences between PUT and PATCH and put it to rest once and for all. It really is a simple concept and I’m not sure why people find it so confusing.

PUT vs PATCH

Let’s take a look at our authors table. It contains the following fields:

  • id
  • first_name
  • last_name
  • email

If we update a resource with the PUT request, we need to send all of the fields. That means that if we update the email, we need to send the idfirst_namelast_name, and email.

If we update a resource with the PATCH request, we need to send only the field that we’re updating. That means that if we update the email, we need to send the email and the identifier (usually the id).

Can We Use a POST?

Actually, there’s no way for us to send a PUT or PATCH request. We can only specify POST or GET requests in the form method. We need to get creative if we want to send put and patch requests.

<form method="post">
  <input type="hidden" name="_method" value="put">
  ... 
</form>

The server side script then needs to decipher the request that came in. For example:

if ( $_POST['_method'] == 'put' ) 
{
  // Do something with the put request
}

The same goes for the DELETE request.

Outlining the Plan

Before we can update the resource, we first need to retrieve the retrieve the resource. Let’s outline a plan on what we need to do in order to update our resource.

  • Retrieve a resource based on id.
  • Show the resource fields in a form.
  • Allow the user to update form fields and click on the Update button.
  • Send the data to a route file that will direct the data.
  • The information is sent along with the id to the server where the server will update the resource.

Based on this information, we can tell that this will be a put request.

Retrieve a resource based on id

We need to retrieve a resource that we’re going to update. We have our select statement from the previous article. That will come in handy now.

<?php
require_once("./Author.php");

use Authors\Author;

$author = new Author;
$update_author = $author->select(1);
The select method returns an array of data, so our $update_author now contains an array of data.
/app/87 MySQL Update/SelectAuthor.php:8:
array (size=6)
  'id' => string '1' (length=1)
  'first_name' => string 'Dino' (length=4)
  'last_name' => string 'Cajic' (length=5)
  'email' => string 'dino@example.com' (length=16)
  'updated_at' => string '2022-11-03 21:56:16' (length=19)
  'created_at' => string '2022-11-03 21:56:16' (length=19)

Show the resource fields in a form

We need to echo that data inside of our form next.

<?php
require_once("./Author.php");

use Authors\Author;

$author = new Author;
$update_author = $author->select(1);
?>

<form action="index.php?page=author" method="post">
    <input type="hidden" name="_method" value="put">
    <input type="hidden" name="id" value="<?php echo $update_author['id']; ?>">
    <div>
        First Name: <input type="text" name="first_name" value="<?php echo $update_author['first_name']; ?>">
    </div>
    <div>
        Last Name: <input type="text" name="last_name" value="<?php echo $update_author['last_name']; ?>">
    </div>
    <div>
        Email: <input type="text" name="email" value="<?php echo $update_author['email']; ?>">
    </div>
    <div>
        <input type="submit" value="Update">
    </div>
</form>

We’ve added two hidden fields. The first one is our _method and the second one is our id. Even though we might just need to update the first_name, we’re going to pass all of the data to our update.php file.

The Route File

What does the index.php?page=author do? The index.php file will serve as our route file. The page parameter tells the server which file to serve up. In this case, it’s the author. We are also passing the put method. Let’s see how we can take all of that and make sense of it.

<?php

$page   = $_GET['page'];
$method = $_POST['_method'];

if ( $page == "author" ) {
    if ( $method == "put" ) {
        // Call Authors object to update resource
    }
}
There is currently no check for what happens if the user removes the page parameter from the url, and that’s okay. There’s also no check for what happens if $_POST is manipulated and the put request is removed. Again, that’s okay. We’re focusing on the update functionality and this is overkill already.
<?php
require_once("./Author.php");

use Authors\Author;

$page   = $_GET['page'];
$method = $_POST['_method'];

if ( $page == "author" ) {
    if ( $method == "put" ) {
        $author = new Author;
        $author->update($_POST);
    }
}

We’ll just need to pass the $_POST to the update method so that we can update the resource.

Adding Update Functionality to our Author Class

Once we receive the $_POST array, we can extract the details out of it to update our resource.

<?php
namespace Authors;

require_once("DB.php");

use Database\DB;

class Author
{
    //...

    public function update( array $author )
    {
        $sql = "UPDATE authors SET first_name = ?, last_name = ?, email = ? WHERE id = ?";

        $db = new DB;
        $mysqli = $db->_connection;

        $statement = $mysqli->prepare( $sql );
        $statement->bind_param(
            "sssi",
            $author['first_name'],
            $author['last_name'],
            $author['email'],
            $author['id']
        );
        $statement->execute();
        $error = $statement->error;

        $statement->close();
        $db->close();

        if ( $error ) {
            return false;
        }

        return true;
    }
}

Although we could just update our resource without preparing it, it’s just as easy to prepare the statement, bind the parameters, and update the resource securely.

We’re going to store error details if it fails and return false if the update fails.

Route Cleanup

Since our update method returns either true or false, we can use that to return to our form.

<?php
require_once("./Author.php");

use Authors\Author;

$page   = $_GET['page'];
$method = $_POST['_method'];

if ( $page == "author" ) {
    if ( $method == "put" ) {
        $author = new Author;
        $update_success = $author->update($_POST);

        if ( $update_success ) {
            header("Location: UpdateEntireAuthor.php");
            die();
        } else {
            die("Could not update");
        }
    }
}

If the update was successful, it will redirect us back to our form, otherwise, the application will terminate. Not the cleanest looking code, but it serves its purpose.

How About Patch?

Not a big deal whatsoever. Let’s create another form that only updates the email address.

<?php
require_once("./Author.php");

use Authors\Author;

$author = new Author;
$update_author = $author->select(1);
?>

<form action="index.php?page=author" method="post">
    <input type="hidden" name="_method" value="patch">
    <input type="hidden" name="id" value="<?php echo $update_author['id']; ?>">
    <div>
       Update Email Address for <?php echo $update_author['first_name'] . " " . $update_author['last_name']; ?>
    </div>
    <div>
        Email: <input type="text" name="email" value="<?php echo $update_author['email']; ?>">
    </div>
    <div>
        <input type="submit" value="Update">
    </div>
</form>
We’re echoing out the first_name and last_name, but we’re not sending it over. We’re just sending the id and email fields. Now it’s time to modify our route file.
<?php
require_once("./Author.php");

use Authors\Author;

$page   = $_GET['page'];
$method = $_POST['_method'];

if ( $page == "author" ) {
    if ( $method == "put" ) {
        $author = new Author;
        $update_success = $author->update($_POST);

        if ( $update_success ) {
            header("Location: UpdateEntireAuthor.php");
            die();
        } else {
            die("Could not update");
        }
    }

    if ( $method == "patch" ) {
        $author = new Author;
        $update_success = $author->update_email($_POST);

        if ( $update_success ) {
            header("Location: UpdateAuthorEmail.php");
            die();
        } else {
            die("Could not update email");
        }
    }
}
The last thing to do is to create our update_email method in our Author class.
<?php
namespace Authors;

require_once("DB.php");

use Database\DB;

class Author
{
    // ...

    public function update_email( array $author )
    {
        $sql = "UPDATE authors SET email = ? WHERE id = ?";

        $db = new DB;
        $mysqli = $db->_connection;

        $statement = $mysqli->prepare( $sql );
        $statement->bind_param(
            "si",
            $author['email'],
            $author['id']
        );
        $statement->execute();
        $error = $statement->error;

        $statement->close();
        $db->close();

        if ( $error ) {
            return false;
        }

        return true;
    }
}

The script is nearly identical with the exception that it only updates the email address.

Final Touches

Let’s add a page check in our route file that checks to see if we have a page parameter in our URL. If not, we’ll display the links to our two pages.

And that’s it. Update functionality integrated. No changes to the DB class. The full code can be seen below. We killed two birds with one stone here: looked at update functionality and identified the difference between put and patch.

MySQL Select

THE ART OF DATA RETRIEVAL

PHP – P88: MYSQL SELECT

A common task is to retrieve those entries and display them on the screen. That’s where the MySQL SELECT statement comes through.

MySQL Update

Revamping Data with Precision

PHP – P89: mysql update

The next logical step in our MySQL progression is updating an existing resource. We’re going to introduce the differences between PUT and PATCH and put it to rest once and for all.

MySQL Delete

ERASING DATA WITH SURGICAL PRECISION

PHP – P90: mysql delete

The last MySQL topic is delete. Just like with our update functionality, there is no delete method. We can submit a hidden method with delete as the value.

Leave a Reply