Last Updated on December 20, 2024 by Mike Kipruto
In this technical documentation, I will guide you on how you can create your own simple Advanced Search and Replace WordPress plugin. This plugin allows users to search for specific values across the entire database and replace them as needed, this how the plugin’s interface would look like
Let’s get started, happy coding 🙌
Plugin Header
To begin, we need to define the plugin header. This is important for WordPress to recognize your plugin. Below is the header information that should be added at the top of your plugin file.
<?php
/*
Plugin Name: Advanced Search and Replace
Description: A simple plugin to search and replace values across the entire database with additional functionality to search for occurrences of specific words.
Version: 1.0
Author: Mike Kipruto
*/
We place this header at the top of our plugin file to provide essential information about our plugin.
Prevent Direct Access
Next, we want to ensure that the plugin can’t be accessed directly. We do this by checking if the ABSPATH
constant is defined.
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
This check helps us prevent unauthorized access.
Creating the Plugin Class
We will encapsulate our functionality within a class to maintain code organization and avoid conflicts with other plugins.
class AdvancedSearchReplace {
private $wpdb;
public function __construct() {
global $wpdb;
$this->wpdb = $wpdb;
add_action( 'admin_menu', [ $this, 'add_admin_menu' ] );
}
}
In this code snippet, we use the add_action()
hook to attach our menu function to the WordPress admin menu.
Adding an Admin Menu
To allow the admin user to access our plugin interface, we will add a menu page under the WordPress admin dashboard.
public function add_admin_menu() {
add_menu_page(
'Advanced Search & Replace',
'Search & Replace',
'manage_options',
'advanced-search-replace',
[ $this, 'render_admin_page' ],
'dashicons-search',
100
);
}
The add_menu_page()
function creates a new menu item. The permission required for this action is set with the manage_options
capability.
Rendering the Admin Page
Now, we need to create the form for user input. This form will facilitate searching and replacing text:
public function render_admin_page() {
// Check user permissions
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// Process form submission
if ( isset( $_POST['asr_action'] ) && check_admin_referer( 'asr_action_nonce', 'asr_nonce' ) ) {
if ( $_POST['asr_action'] === 'search' ) {
$this->search_occurrences();
} elseif ( $_POST['asr_action'] === 'replace' ) {
$this->search_and_replace();
}
}
?>
<div class="wrap">
<h1>Advanced Search and Replace</h1>
<form method="post">
<?php wp_nonce_field( 'asr_action_nonce', 'asr_nonce' ); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="asr_search">Search For</label></th>
<td><input type="text" id="asr_search" name="asr_search" class="regular-text" placeholder="Enter text to search for" required></td>
</tr>
<tr>
<th scope="row"><label for="asr_replace">Replace With</label></th>
<td><input type="text" id="asr_replace" name="asr_replace" class="regular-text" placeholder="Enter replacement text (leave blank for search only)"></td>
</tr>
</table>
<p>
<button type="submit" name="asr_action" value="search" class="button-secondary">Search Only</button>
<button type="submit" name="asr_action" value="replace" class="button-primary">Search and Replace</button>
</p>
</form>
</div>
<?php
}
Here, we utilize the current_user_can()
function to verify if the user has the appropriate permissions. Additionally, we include a nonce field using wp_nonce_field()
to protect against CSRF attacks.
Searching for Occurrences
Next, we implement the functionality to search for occurrences of the specified term in the database:
private function search_occurrences() {
$search = sanitize_text_field($_POST['asr_search']);
if (empty($search)) {
echo '<div class="error notice"><p>Search term cannot be empty.</p></div>';
return;
}
$tables = $this->wpdb->get_col("SHOW TABLES");
$total_occurrences = 0;
foreach ($tables as $table) {
$columns = $this->wpdb->get_results("SHOW COLUMNS FROM $table", ARRAY_A);
foreach ($columns as $column) {
$column_name = $column['Field'];
$data_type = $column['Type'];
if ($this->is_text_column($data_type)) {
$occurrences = $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(*) FROM $table WHERE $column_name LIKE %s", '%' . $this->wpdb->esc_like($search) . '%'));
$total_occurrences += $occurrences;
if ($occurrences > 0) {
echo "<div class='notice notice-info'><p>Found $occurrences occurrences in $table.$column_name.</p></div>";
}
}
}
}
if ($total_occurrences === 0) {
echo '<div class="notice notice-warning"><p>No occurrences found in the database.</p></div>';
} else {
echo "<div class='updated notice'><p>Total occurrences found: $total_occurrences</p></div>";
}
}
In this method, we’re performing SQL queries to retrieve and count occurrences of the search term. We also utilize functions such as sanitize_text_field()
for data sanitization, get_col()
and get_results()
to interact with the database.
Searching and Replacing
Now let’s create the method for searching and replacing:
private function search_and_replace() {
$search = sanitize_text_field($_POST['asr_search']);
$replace = sanitize_text_field($_POST['asr_replace']);
if (empty($search)) {
echo '<div class="error notice"><p>Search term cannot be empty.</p></div>';
return;
}
$tables = $this->wpdb->get_col("SHOW TABLES");
$total_replacements = 0;
foreach ($tables as $table) {
$columns = $this->wpdb->get_results("SHOW COLUMNS FROM $table", ARRAY_A);
foreach ($columns as $column) {
$column_name = $column['Field'];
$data_type = $column['Type'];
if ($this->is_text_column($data_type)) {
$updated_rows = $this->wpdb->query($this->wpdb->prepare("UPDATE $table SET $column_name = REPLACE($column_name, %s, %s) WHERE $column_name LIKE %s", $search, $replace, '%' . $this->wpdb->esc_like($search) . '%'));
$total_replacements += $updated_rows;
if ($updated_rows > 0) {
echo "<div class='notice notice-info'><p>Updated $updated_rows rows in $table.$column_name.</p></div>";
}
}
}
}
if ($total_replacements === 0) {
echo '<div class="notice notice-warning"><p>No replacements made in the database.</p></div>';
} else {
echo "<div class='updated notice'><p>Total rows updated: $total_replacements</p></div>";
}
}
This function operates similarly to the search function but utilizes the UPDATE
SQL command to replace occurrences within the database.
Checking for Text Columns
Lastly, we need a helper function to ensure we are operating only on text columns:
private function is_text_column($data_type) {
return preg_match('/^(char|varchar|text|mediumtext|longtext)/i', $data_type);
}
This function uses preg_match()
to evaluate whether the data type matches common text column types in MySQL. This step is crucial because we want to prevent any unintended operations on non-text columns.
Final Step: Initialize the Plugin
At the end of your PHP file, you need to instantiate the class to make the plugin operational.
new AdvancedSearchReplace();
Finally, we must instantiate our class at the end of the PHP file to activate our plugin:
Conclusion
By following this guide, you now have a basic WordPress plugin that can search for and replace values across the database. Always ensure to test your plugin thoroughly to avoid any potential data loss when performing database modifications.
If you need help with the setup or have any questions, please leave a comment below, and I’ll be happy to assist you!
References
For further reading, you can check out the accompanying documentation for hooks and functions used in this guide:
WordPress Documentation Links
- add_action(): https://developer.wordpress.org/reference/functions/add_action/
- add_menu_page():
https://developer.wordpress.org/reference/functions/add_menu_page/ - current_user_can():
https://developer.wordpress.org/reference/functions/current_user_can/ - wp_nonce_field():
https://developer.wordpress.org/reference/functions/wp_nonce_field/ - sanitize_text_field():
https://developer.wordpress.org/reference/functions/sanitize_text_field/ - get_col():
https://developer.wordpress.org/reference/classes/wpdb/get_col/ - get_results():
https://developer.wordpress.org/reference/classes/wpdb/get_results/ - get_var():
https://developer.wordpress.org/reference/classes/wpdb/get_var/ - prepare():
https://developer.wordpress.org/reference/classes/wpdb/prepare/ - query():
https://developer.wordpress.org/reference/classes/wpdb/query/ - esc_like():
https://developer.wordpress.org/reference/functions/esc_like/
PHP Documentation Links
- preg_match():
https://www.php.net/manual/en/function.preg-match.php - empty():
https://www.php.net/manual/en/function.empty.php - isset():
https://www.php.net/manual/en/function.isset.php - header():
https://www.php.net/manual/en/function.header.php - global:
https://www.php.net/manual/en/language.variables.variable.php#language.variables.scope
This concludes the documentation! Feel free to explore the links provided for each function and hook to gain a deeper understanding of their usage. Happy coding!
Leave a Reply