Foolproof Methods to Secure Older WordPress Sites – Utilizing PHP to Find Missing Database Primary Keys

Reading Time: 3 minutes
Dealing with older WordPress websites can present unique challenges, one such being missing primary keys in your MySQL databases. Discover the importance of primary keys for maintaining database order and integrity, and learn how a simple PHP script can help in identifying and remedying these missing primary keys in your 'wp_' tables, ensuring that your data integrity and website performance remain top-notch.
find missing primary keys in wordpress database

Table of Contents

Why are Primary Keys on WordPress so Important?

Dealing with old WordPress websites can be tricky, primarily if not maintained properly. I stumbled upon an unusual issue related to missing primary keys during a migration between MySQL databases and realized the significance of primary keys in the database structure. Let’s take a deep dive into why primary keys can make or break your databases and how a handy PHP tool can help you fix the problem.

An Introduction to Primary Keys

Primary keys play an essential role in maintaining database order and integrity. Tables without primary keys can cause severe data anomalies and impact the database’s efficiency adversely. So, while migration seemed like a standard task, the missing primary keys in the older WordPress installations surfaced as a considerable challenge. Turns out, the effective use of a PHP script comes in handy in such situations.

Understanding the PHP Database Audit Script

Going the extra mile to solve the issue, I came up with a PHP script that audits MySQL databases specifically for older WordPress installations. The script identifies the set of tables starting with “wp_” lacking primary keys.

				
					$hostname = '';
$username = '';
$password = '';

// connect to your database
$mysqli = new mysqli($hostname, $username, $password);

// Get the tables without a primary key
$query = "
    SELECT 
        t.table_schema, 
        t.table_name, 
        t.engine
    FROM
        information_schema.tables t 
            LEFT JOIN (
                SELECT 
                    table_schema, table_name
                FROM
                    information_schema.statistics
                WHERE
                    index_name = 'PRIMARY'
            ) s ON
                t.table_schema = s.table_schema
                AND t.table_name = s.table_name
    WHERE
            s.table_name IS NULL
            AND t.table_name LIKE 'wp_%'
            AND t.table_type != 'VIEW';
";

$result = $mysqli->query($query);

if($result === false) {
    echo "Failed to get tables without primary keys: (" . $mysqli->errno . ") " . $mysqli->error;
    exit(1);
}

// loop through the result set
while ($row = $result->fetch_assoc()) {
    // get the table schema and name
    $tableSchema = $row["TABLE_SCHEMA"];
    $tableName = $row["TABLE_NAME"];

    // get the table name
    $query = "
        SELECT *
        FROM information_schema.columns
        WHERE
            table_schema = '$tableSchema'
            AND table_name = '$tableName'
            AND column_name = 'id';
    ";

    // check if an id column exists
    $columnResult = $mysqli->query($query);

    if ($columnResult->num_rows === 0) {
        continue;
    }

    echo "Adding primary key on 'id' column for table table_name...".PHP_EOL;

    // add the primary key
    $query = "
        ALTER TABLE `$tableSchema`.`$tableName` 
        CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT ,
        ADD PRIMARY KEY (`id`);
    ";

    $alter_result = $mysqli->query($query);

    if (! $alter_result) {
        echo "Failed to add primary key to $tableName: (" . $mysqli->errno . ") " . $mysqli->error;
        continue;
    }

    echo "Success.".PHP_EOL;
    echo "Adding primary key on 'id' column for table table_name...".PHP_EOL;

    // add the primary key without auto increment
    // Then add auto increment
    $query = "
        ALTER TABLE `$tableSchema`.`$tableName` ADD PRIMARY KEY (`id`);
        ALTER TABLE `$tableSchema`.`$tableName` CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT;
    ";

    $alter_result = $mysqli->query($query);

    if (! $alter_result) {
        echo "Failed to add primary key to $tableName: (" . $mysqli->errno . ") " . $mysqli->error.PHP_EOL;
        continue;
    }

    echo "Success.".PHP_EOL;
}


// Get the tables without a primary key
$query = "
    SELECT 
        t.table_schema, 
        t.table_name, 
        t.engine
    FROM
        information_schema.tables t 
            LEFT JOIN (
                SELECT 
                    table_schema, table_name
                FROM
                    information_schema.statistics
                WHERE
                    index_name = 'PRIMARY'
            ) s ON
                t.table_schema = s.table_schema
                AND t.table_name = s.table_name
    WHERE
            s.table_name IS NULL
            AND t.table_name LIKE 'wp_%'
            AND t.table_type != 'VIEW';
";

$result = $mysqli->query($query);

if($result === false) {
    exit(1);
}

// loop through the result set
while ($row = $result->fetch_assoc()) {
    // get the table schema and name
    $tableSchema = $row["TABLE_SCHEMA"];
    $tableName = $row["TABLE_NAME"];

    // Display a message for table to edit manually
    echo "Please edit the table $tableSchema.$tableName manually to add a primary key.".PHP_EOL;
}

				
			

The script works by establishing a connection with the MySQL database, performing a deep dive to locate WordPress tables missing primary keys. If an ‘id’ column is found in these tables, the script performs a quick transformation, declaring this ‘id’ column as a new primary key and setting it to auto-increment.

Considerations Before Running the Script

It’s vital to remember that any script, including this PHP script, should initially be tested in a non-production environment. Always remember to back up your data before running any scripts to prevent any loss of information. Once you’re confident that the script works as expected, you can run it on a production database.

Tying it All Together

Coming full circle, we understand that migrating databases or dealing with older WordPress installations can often present unique, unexpected challenges. Missing primary keys in your database can seem like a daunting problem at first, but with the right tools and some handy PHP scripting, you can ensure that your data integrity and website performance remain unaffected.

If you found this post to be helpful, why not let your social network know? Click on the link below to share it on X or your preferred social platform and spread the word. Want to stay ahead of the curve with posts like these? Don’t forget to subscribe to our blog. If you have questions or need consulting, don’t hesitate to Contact Me.

Share it on:

Twitter
LinkedIn
Facebook
WhatsApp

About the Author

Gary Gitton
Hello, I'm Gary Gitton - an accomplished Software Engineer, Tech Lead, specializing in PHP, API Engineering, DevOps, and Cloud Management. Throughout my career, I've had the privilege to enhance multiple software solutions with my expertise in multiple languages and platforms. I bring my unique blend of technical and business acumen to every project, ensuring efficient, scalable, and innovative outcomes. I'm also passionate about fostering a culture of continuous learning, mentoring developers, and leading projects with agile methodologies. Whether concocting a bespoke API or orchestrating cloud environments, I'm committed to delivering quality and excellence. Let's connect and transform your vision into a digital reality.

You might also like