- Issues Arising from Domain Changes
When migrating a WordPress site to another server or changing the domain, unexpected issues may arise throughout the site. In particular, if the embedded links and image URLs in the site continue to reference the old domain, certain parts of the site may not display correctly.
For example, the following issues commonly occur:
- Images not displaying: Images inserted in posts or pages may stop appearing because they still use the old domain name. If the image links are not correctly updated, visitors will encounter “Image not found” errors.
- Links not functioning: Internal and external links within the site may still reference the old domain, preventing users from navigating to the intended pages when clicked. This harms the user experience and negatively impacts SEO (Search Engine Optimization).
- Unable to access the admin dashboard: If the WordPress admin dashboard is still operating based on the old domain, it may become inaccessible after migration. This issue can prevent you from making site settings or editing content, disrupting site management.
- Themes and plugins not functioning properly: Some themes and plugins may have hardcoded URLs. If these settings are not updated, the themes and plugins may not function as expected.
These issues cannot be solved merely by moving the WordPress files because WordPress stores URLs in the database, and these must be properly updated. However, manually updating the database is time-consuming and prone to errors.
To address these issues efficiently, a more streamlined approach is required. One such tool is WP-CLI, which allows you to easily replace old URLs in the database with the new domain in bulk. However, the focus of this article is on a custom script, so please continue reading.
- What is WP-CLI?
To address the issues caused by domain changes during site migration, WP-CLI is a tool that can be very helpful. Beginners might wonder, “What is a CLI?” or “What is WP-CLI?” So let’s take a step-by-step approach to explain it clearly.
What is a CLI?
First, let’s briefly discuss the term CLI (Command Line Interface). A CLI is a system where you input commands into a text-based interface to interact with the computer. Typically, we operate by clicking on a browser or pressing buttons in an app, but with a CLI, you operate by “typing commands.”
For example, tasks such as opening folders or deleting files are performed using the keyboard instead of a mouse.
What is WP-CLI?
Now, let’s explain WP-CLI. WP-CLI is a tool that allows you to manage WordPress through the command line. Normally, WordPress is managed using a browser, but with WP-CLI, you can easily perform various operations on WordPress by simply entering commands.
For example:
- You can install plugins or update themes instantly without opening a browser.
- You can bulk-replace data in the database or delete specific posts.
In short, WP-CLI helps you streamline WordPress management tasks. It’s particularly useful when you need to replace URLs in the database after a domain change, as in this case.
Benefits of Using WP-CLI
Beginners may ask, “Is this really necessary?” But WP-CLI offers several advantages:
- Speed: Instead of manually changing each item in the browser, WP-CLI allows you to complete multiple tasks at once with a single command.
- Accuracy: WP-CLI supports serialized data, which can be easily corrupted with manual updates. This means it reduces the risk of data corruption.
- Automation: Even if you manage multiple sites, you can apply the same commands across all of them, greatly improving efficiency.
How to Use WP-CLI
Now, let’s look at how to use WP-CLI with a simple example.
- Install WP-CLI
First, you need to install WP-CLI. Depending on your server environment, WP-CLI may not be pre-installed, so in that case, check with your server administrator or verify if your server supports WP-CLI.
For installation instructions, refer to the official WP-CLI website.
How to Install WP-CLI
We will explain how to install WP-CLI, a tool that makes managing WordPress more efficient, in a way that is easy for beginners to understand. Here, we will introduce the basic installation method using a Phar file.
- Check System Requirements
Before installing WP-CLI, check the system requirements. If the following conditions are met, you can install and use WP-CLI smoothly.
- A UNIX-based environment (e.g., OS X, Linux, FreeBSD, Cygwin): WP-CLI can also be used on Windows, but some features may be limited.
- PHP 5.6 or higher: Since WP-CLI runs on PHP, PHP must be installed. If your PHP version is outdated, update to the latest version.
- WordPress version 3.7 or higher: If you’re using an older version of WordPress, some WP-CLI features may not work properly.
- Download WP-CLI
To install WP-CLI, you need to download the Phar file (an executable PHP archive). Using this file, you can easily install and use WP-CLI.
Run the following command in your terminal (command line) to download the WP-CLI Phar file:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
This command uses curl
to download the WP-CLI Phar file from the internet. The file will be saved in your current directory under the name wp-cli.phar
.
- Verify the Phar File is Working
Next, verify that the downloaded Phar file works correctly. Run the following command:
php wp-cli.phar --info
By running this command, you can check whether WP-CLI is functioning. If PHP and WP-CLI versions are displayed correctly, it means the installation was successful.
The command ‘php’ is not found. You can install it using the following method:
sudo apt install php8.3-cli # version 8.3.6-0ubuntu0.24.04.1, or
sudo apt install php-cli # version 2:8.2+93ubuntu1
sudo apt install php8.2-cli # version 8.2.12-1ubuntu2
WP-CLI requires PHP to run, but since PHP is not yet installed in my environment, this message is displayed. Let me explain the available options for Ubuntu 24.04.
Options:
- php8.3-cli: This option installs the command line interface (CLI) for PHP 8.3. PHP 8.3 is the latest version, and it is expected to receive future updates and support. However, some WordPress plugins and themes may not yet be compatible with PHP 8.3.
- php-cli (version 8.2): This option installs the CLI for PHP 8.2, which is provided as the default on Ubuntu 24.04. PHP 8.2 is stable and supported by WordPress and many plugins, making it an ideal recommendation.
- php8.2-cli: This option installs only the CLI for PHP 8.2. It is similar to
php-cli
, but explicitly specifies the version to be installed.
Recommendation:
The safest choice is to install php-cli (version 8.2). PHP 8.2 is stable and highly compatible with many WordPress plugins and themes, so it’s less likely to cause any issues. Simply run the following command to install it:
sudo apt install php-cli
Once installed, you can run the php wp-cli.phar --info
command again to confirm, and the output should appear as expected.
OS: Linux 6.8.0-41-generic #41-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 2 20:41:06 UTC 2024 x86_64
Shell: /bin/bash
PHP binary: /usr/bin/php8.3
PHP version: 8.3.6
php.ini used: /etc/php/8.3/cli/php.ini
MySQL binary: /usr/bin/mysql
MySQL version: mysql Ver 8.0.39-0ubuntu0.24.04.2 for Linux on x86_64 ((Ubuntu))
SQL modes:
WP-CLI root dir: phar://wp-cli.phar/vendor/wp-cli/wp-cli
WP-CLI vendor dir: phar://wp-cli.phar/vendor
WP_CLI phar path: /home/mamu/mysql
WP-CLI packages dir:
WP-CLI cache dir: /home/mamu/.wp-cli/cache
WP-CLI global config:
WP-CLI project config:
WP-CLI version: 2.11.0
Even though I installed version 8.2, as shown in the result above, PHP 8.3 is being used. I looked into this issue.
Why does PHP version 8.3 show up even though I selected the second option (sudo apt install php-cli)?
Conclusion
When you install the php-cli
package, it installs the system’s default PHP version’s CLI (in this case, PHP 8.3). As a result, when you run the php
command, PHP 8.3 is used.
Detailed Explanation
About the php-cli
Package
The php-cli
package is a meta-package in Ubuntu that provides the CLI for the system’s default PHP version.
The default PHP version depends on your system’s repository configuration and what has been installed.
The installation options presented:
sudo apt install php8.3-cli
# version 8.3.6-0ubuntu0.24.04.1sudo apt install php-cli
# version 2:8.2+93ubuntu1sudo apt install php8.2-cli
# version 8.2.12-1ubuntu2
- The first option explicitly installs the CLI for PHP 8.3.
- The second option installs the CLI via the
php-cli
meta-package, which provides the system’s default PHP version. - The third option installs the CLI for PHP 8.2 explicitly.
Confusion over Version Numbers
The version number for the php-cli
package (e.g., 2:8.2+93ubuntu1) refers to the package itself, not the PHP version it installs.
If PHP 8.3 is the system’s default version, then installing php-cli
will install the CLI for PHP 8.3.
How the php
Command Works
The php
command points to the default version of PHP on the system.
Therefore, when you run php wp-cli.phar --info
, PHP 8.3 is used because it is the system’s default version.
Why This Happens
Since the system’s default PHP version is PHP 8.3, installing the php-cli
package installs the CLI for PHP 8.3, and the php
command points to PHP 8.3.
Difference Between Package Version and PHP Version
The package version number is used for version control within the package management system and may not directly correspond to the version of the software itself.
Actions and Considerations
If everything is working correctly with the current setup, you can continue using it as is.
If PHP 8.3 is functioning properly and WP-CLI works without issues, there is no need to change anything.
If You Want to Use a Specific PHP Version
If you want to use PHP 8.2, follow these steps:
- Install the CLI for PHP 8.2bashコードをコピーする
sudo apt install php8.2-cli
- Switch the default PHP version using the
update-alternatives
commandbashコードをコピーするsudo update-alternatives --config php
From the list that appears, select the path for PHP 8.2.
Additional Information
update-alternatives
Command
If multiple PHP versions are installed, you can use this command to switch the default PHP version.- Check PHP Version
You can verify the current PHP version by running the following command:bashコードをコピーするphp -v
The php-cli
package installs the CLI for the system’s default PHP version, which in this case is PHP 8.3.
The reason the chosen option did not install the expected version is that php-cli
is a meta-package, and it does not explicitly specify the PHP version.
If necessary, you can install a specific version’s CLI package and switch the default PHP version using the update-alternatives
command.
- Making WP-CLI Usable as a Command
Once you have verified that the Phar file works correctly, you can make WP-CLI easier to use by setting it up to be executed with the wp
command.
First, make the Phar file executable by running the following command:
chmod +x wp-cli.phar
Next, move the Phar file to a directory in your system’s PATH so that it can be run from anywhere:
sudo mv wp-cli.phar /usr/local/bin/wp
Now you can easily run WP-CLI using the wp
command.
- Verifying WP-CLI Installation
To check if WP-CLI is installed correctly, run the following command:
wp --info
This command will display environment information used by WP-CLI, such as the PHP and MySQL versions. With this, the WP-CLI installation is complete.
WP-CLI Updates
WP-CLI is regularly updated, so it’s necessary to keep it up to date to use the latest features. To update WP-CLI, use the following command:
wp cli update
If WP-CLI was installed with administrative privileges, you will need to use sudo
when updating:
sudo wp cli update
If you want to try the latest developer version, you can also update to the nightly build with the following command:
wp cli update --nightly
This way, you can work with the latest version of WP-CLI.
1. Setting Up Tab Completion
When using WP-CLI, you can improve your workflow by enabling “tab completion,” which allows you to automatically complete commands as you type. If you use Bash or zsh, follow these steps to set up tab completion:
For Bash:
Download the tab completion script:
curl -O https://raw.githubusercontent.com/wp-cli/wp-cli/master/utils/wp-completion.bash
Add the script to your ~/.bash_profile
to load it:
source /FULL/PATH/TO/wp-completion.bash
To apply the changes, run the following command:
source ~/.bash_profile
For zsh:
To enable Bash tab completion in zsh, you need to add additional settings. Append the following lines to your ~/.zshrc
file:
autoload bashcompinit
bashcompinit
source /FULL/PATH/TO/wp-completion.bash
Now, tab completion is enabled. When typing WP-CLI commands, you can press the Tab key to complete the command automatically.
2. Replacing Domain Names with WP-CLI
WP-CLI allows you to replace old domain names with new ones across your database when migrating. Use the following command:
wp search-replace 'http://old-domain.com' 'http://new-domain.com' --all-tables
This command will replace the old domain with the new one across all tables in the database.
Example Command:
wp search-replace '192.168.0.50' '192.168.0.91' --all-tables
wp search-replace
: This part instructs WP-CLI to search and replace.
'http://old-domain.com'
: Specify the old domain here.
'http://new-domain.com'
: Input the new domain here.
--all-tables
: This ensures the replacement runs across all WordPress tables.
3. Taking a Backup
Before using WP-CLI, always take a backup of your database to avoid issues in case of mistakes.
Example Backup Command:
wp db export backup.sql
This command exports the current database to a file called backup.sql
.
WP-CLI is a highly useful tool, even for beginners, and can be a great help when performing tasks like domain changes during migration. It may feel a bit daunting at first, but once you try it, you’ll be surprised at how convenient it is. With WP-CLI, you’ll be able to manage databases, plugins, and more in no time, making it an essential tool for anyone looking to manage WordPress efficiently.
What is WP-CLI’s wp db export
?
wp db export
is a database export feature provided by WP-CLI. With this command, you can easily back up your WordPress database without needing to use mysqldump
. While it functions similarly to mysqldump
, it handles the database in a way that’s optimized for WordPress when executed through WP-CLI.
Command Explanation
wp db export backup.sql
wp db export
: This is WP-CLI’s database export command. It exports the entire database used by the current WordPress installation.backup.sql
: This specifies the filename where the exported database will be saved. In this case, it will be saved asbackup.sql
.
Unlike mysqldump
, this command is tailored for the WordPress environment, making it more convenient for those familiar with managing WordPress sites.
Comparison: mysqldump
vs. wp db export
- mysqldump: A general-purpose database export tool for MySQL. It can export databases beyond WordPress, making it a widely-used backup tool for various databases. I personally use this tool.
mysqldump -u username -p database_name > backup.sql
- wp db export: A command that simplifies exporting a WordPress database via WP-CLI. Unlike
mysqldump
, you don’t need to configure detailed options, and it integrates seamlessly with WordPress’s management environment, making it easier to back up.
Usability
- For Beginners:
wp db export
is easier to use thanmysqldump
, especially in environments where WP-CLI is already installed, making it more user-friendly for beginners. - Integrated Tool: Using WP-CLI allows for consistent operations with other management tasks, making it convenient for users familiar with WordPress.
If WP-CLI is available in your environment, using this command for WordPress site backups makes it easy to back up your database.
How to Replace URLs with WP-CLI
When migrating a WordPress site or changing the domain name, you need to replace the URLs in the database. Doing this manually can be very tedious, but WP-CLI makes it easy, safe, and efficient to replace URLs.
Here, we’ll explain in detail how to replace URLs from the old domain to the new domain using WP-CLI.
Preparation Before Starting the Replacement
First, be sure to back up your database. If any issues arise during the replacement process, having a backup will allow you to easily restore the database.
As explained in the previous section, here’s a reminder on how to back up your database:
wp db export backup.sql
This command saves the current WordPress database to a file named backup.sql
. This way, you can have peace of mind in case anything goes wrong. When you execute the wp db export backup.sql
command, the backup file will be created in the directory where the command was run.
For example, if your current working directory is /home/user/
, the backup.sql
file will be saved as /home/user/backup.sql
.
If you want to save the backup file to a specific location, you can specify the path. For instance, if you want to save the backup to the /home/user/backups/
folder, you would specify it like this:
wp db export /home/user/backups/backup.sql
This will create the backup file in the specified location.
However, the following error occurred.
Error: This does not seem to be a WordPress installation.
The used path is: /home/mamu/mysql/
Pass –path=`path/to/wordpress` or run `wp core download`.
This error message occurs because the command is being executed in a directory that is not the one where WordPress is installed. WP-CLI commands must be run in the directory where WordPress is installed.
Cause of the Error
The wp db export
command expects to be run in the location where the WordPress files are present. If the current directory is not the WordPress directory, an error will occur.
Solution
1. Run the command in the WordPress installation directory
First, navigate to the directory where WordPress is installed before running the command. For example, if WordPress is installed in /var/www/html/wordpress
, you can navigate to that directory with the following command:
cd /var/www/html/wordpress
Afterward, run the following command to take a backup:
wp db export backup.sql
2. Use the --path
option
If you prefer not to leave your current directory, you can use the --path
option to specify the path to the WordPress installation.
For example, if WordPress is installed in /var/www/html/wordpress
, you can run the following command:
wp db export backup.sql --path=/var/www/html/wordpress
This will execute the command while specifying the path where WordPress is installed, and the backup will be created.
Solution 1: Navigate to the WordPress installation directory and execute the command.
Solution 2: Use the --path
option to specify the WordPress installation directory.
Using WP-CLI inside Docker containers
If you’re running WordPress in a Docker environment, executing WP-CLI from the host may feel a bit more complex, but it can be handled appropriately. Even if you have mounted directories on the host, using WP-CLI within the Docker container is convenient.
Solution: Use WP-CLI inside the Docker container
When running WordPress in Docker, it is common to execute WP-CLI directly inside the container. This allows you to access the WordPress files and database directly.
Steps:
- Install WP-CLI inside the container
If WP-CLI is not installed in the Docker container, log into the container with the following command:docker exec -it <container_name> bash
Then, download and install WP-CLI inside the container:curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
- Take a backup using WP-CLI
Run thewp db export
command inside the container to back up the database:wp db export /var/www/html/backup.sql
In this case,/var/www/html/
is the directory where the WordPress files are located. The backup file will be saved in/var/www/html/
within the container.
Sharing files between the host and container
If you have a mounted directory on the host, you can save the backup file to the host by using the mount point. For example, if the container’s /var/www/html/
is mounted to /home/user/wordpress/
on the host, the backup file will be saved as /home/user/wordpress/backup.sql
on the host.
Example:
docker exec -it <container_name> wp db export /var/www/html/backup.sql
This will create a backup file in the folder mounted on the host.
Understanding the process
The docker exec
command is used to execute commands inside the Docker container, so you can run it from any directory on the host. However, if WP-CLI is not installed in the container or if it is not correctly registered in the $PATH
environment variable, an error will occur. It can be helpful to create a Dockerfile that installs WP-CLI.
# Base the image on the official WordPress image
FROM wordpress:latest
# Install curl and download WP-CLI
RUN apt-get update && apt-get install -y curl \
&& curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
&& chmod +x wp-cli.phar \
&& mv wp-cli.phar /usr/local/bin/wp
# Install mariadb-client to use mysqldump
RUN apt-get install -y mariadb-client
However, you will also need to modify the docker-compose.yml
file. Below is an example of a configuration that does not use a Dockerfile and relies on the official image (image: wordpress:latest
), so no build is necessary. In this case, running docker compose build
will not build anything since the configuration does not include custom build settings.
wordpress:
container_name: wp
depends_on:
- db
image: wordpress:latest
ports:
- "8080:80"
Enabling the build process
If you want to create a custom image, you need to add the build
section to the docker-compose.yml
file, instead of using image: wordpress:latest
.
Example: Adding a build section to docker-compose.yml
wordpress:
container_name: wp
depends_on:
- db
build: .
image: custom-wordpress-wpcli # Use the custom-built image from the Dockerfile
ports:
- "8080:80"
build: .
: This section tells Docker to build the image using the Dockerfile in the current directory.image: custom-wordpress-wpcli
: This specifies the name of the custom-built image. By naming the image, you can use it in the future.
Now, you’re ready to back up your database.
docker exec -it <container_name> wp db export /var/www/html/backup.sql
What to do if an error occurs?
Error: YIKES! It looks like you’re running this as root. You probably meant to run this as the user that your WordPress installation exists under.
If you REALLY mean to run this as root, we won’t stop you, but just bear in mind that any code on this site will then have full control of your server, making it quite DANGEROUS.
If you’d like to continue as root, please run this again, adding this flag: –allow-root
If you’d like to run it as the user that this site is under, you can run the following to become the respective user:
sudo -u USER -i — wp
This error occurs because WP-CLI is issuing a warning about executing commands as the root user. For security reasons, WP-CLI typically recommends running commands as the user who installed WordPress, rather than as root.
Solution
1. Use the --allow-root
flag (simple solution)
By using this flag, you can execute WP-CLI as the root user. However, be aware that running commands as root carries security risks. If you’re in an environment where security isn’t a concern, this method should work without issues.
docker exec -it wp wp db export /var/www/html/backup.sql --allow-root
2. Execute the command as the appropriate user
Another solution is to switch to the user under which WordPress is installed and run WP-CLI as that user. In many WordPress installations, the www-data
user is used. You can switch to the www-data
user and run the command as follows:
docker exec -it wp sudo -u www-data wp db export /var/www/html/backup.sql
This will allow you to execute WP-CLI as the appropriate user, avoiding any security warnings.
- Option 1: Using the
--allow-root
flag lets you run WP-CLI as root but be cautious about the security risks. - Option 2: Switching to the appropriate user (e.g.,
www-data
) helps avoid security risks by running the command under the correct user.
What if the following error occurs?
OCI runtime exec failed: exec failed: unable to start container process: exec: “sudo”: executable file not found in $PATH: unknown
This error message indicates that the sudo
command is not installed inside the container. Often, lightweight container images don’t include sudo
, so you need to execute commands as the www-data
user without using sudo
.
Solution: Use the su
command
To switch to the www-data
user inside the container, use the su
command:
docker exec -it --user www-data wp wp db export /var/www/html/backup.sql
This command uses Docker’s --user
option to directly execute the command as the www-data
user inside the container. This allows you to run WP-CLI with the correct user permissions without needing sudo
.
- If
sudo
is not available in the container, use the--user
option to specify the user directly.
Running WP-CLI as the www-data
user allows you to avoid security warnings while executing the command.
Backup File Location
The above command saves the backup.sql
file to /var/www/html/
inside the Docker container. If this directory is mounted to /home/user/wordpress/
on the host, the backup file will also appear as /home/user/wordpress/backup.sql
on the host.
Why you don’t need to be in the host directory
When using docker exec
, you are executing commands inside the container. This means that no matter which directory you are in on the host, the operation is performed within the container. There is no need to be in a specific directory on the host.
The docker exec
command can be run from any directory on the host, and there is no need to navigate to a specific directory on the host.
While the backup file is saved inside the container, if the directory is mounted to the host, the file will also be accessible on the host.
Using WP-CLI inside Docker containers is highly convenient. By installing WP-CLI within the container and running commands inside the container, you can easily perform tasks such as database operations and backups for WordPress.
2. Basic Flow of Replacing URLs
Next, let’s execute the basic command to replace old URLs with new ones. To do this, we use WP-CLI’s search-replace
command. This command searches for the specified string (in this case, the old domain URL) and replaces it with a new string (the new domain URL).
Here is the basic command:
wp search-replace 'http://old-domain.com' 'http://new-domain.com' --all-tables
3. Detailed Explanation of the Command
Let’s break down each part of the command:
wp search-replace
: This is the WP-CLI command that searches for a specified string and replaces it with another string in the WordPress database.'http://old-domain.com'
: This specifies the old URL that you want to search for. Here, you input the old domain name before migration.'http://new-domain.com'
: This is where you input the new domain name. This will be the URL that replaces the old one.--all-tables
: This option tells WP-CLI to search through all tables in the WordPress database. Since WordPress stores URLs in multiple tables, this ensures that all instances of the old URL are replaced.
4. Options for Safer Replacements
If you want to verify which parts will be replaced before making changes, you can use the --dry-run
option. This option simulates the replacement process, showing what will be replaced without actually changing the data.
wp search-replace 'http://old-domain.com' 'http://new-domain.com' --all-tables --dry-run
This allows you to check which tables and columns will be modified, ensuring that you can proceed with the actual replacement confidently. If you are using Docker, you can run the following command:
wp search-replace '192.168.0.50' '192.168.0.91' --all-tables
You want to run this without entering the container. It is possible to execute this command directly from the host using WP-CLI inside the Docker container. However, you must run it as the appropriate user and ensure that mysqldump
or mysql
works properly within the environment.
How to Execute the Command
To execute the wp search-replace
command without entering the container, use Docker’s exec
command. As in the previous examples, run it as the www-data
user:
docker exec -it --user www-data wp wp search-replace '192.168.0.50' '192.168.0.91' --all-tables
This allows you to execute the replacement directly from the host inside the container.
Important Notes
Running commands as the www-data
user avoids the security warnings associated with running as the root user.
If mariadb-client
or mysqldump
is installed inside the container, the command should execute without issues.
If you encounter errors indicating that mysqldump
or mysql
is missing, follow the earlier steps to install mariadb-client
.
By using docker exec
, you can run the wp search-replace
command without entering the container.
Once you’ve confirmed that the necessary user permissions and mysqldump
are available inside the container, the command should run without errors.
5. Performing the Actual Replacement
Once the simulation runs successfully, you can proceed with the actual replacement by removing the --dry-run
option:
wp search-replace 'http://old-domain.com' 'http://new-domain.com' --all-tables
This command will replace the old domain with the new one across the entire database. It targets all tables, ensuring that URLs in posts, images, and settings files are replaced in one go.
6. After the Replacement
After the replacement is complete, check your WordPress site to ensure that all URLs have been correctly updated to the new domain. Pay special attention to links in posts, image displays, and access to the admin panel to make sure there are no issues.
The wp search-replace 'http://old-domain.com' 'http://new-domain.com' --all-tables
command replaces all instances of the old domain URL with the new domain URL across all tables in the WordPress database. Specifically, the following items will be replaced.
Replacement Targets
wp_posts
table,post_content
column: This includes URLs for links and images within the content of posts and pages. In other words, if the old domain is present in the article content, it will also be replaced with the new domain.wp_options
table,siteurl
andhome
columns: The basic URL of WordPress and the URL of the front page will also be replaced.wp_posts
table,guid
column: This includes the permalink (fixed link) URLs for posts and pages, which will also be replaced.- Other tables: The entire database, including tables created by plugins and themes, will be subject to replacement.
Including the Post Content (post_content
)
By using the --all-tables
option, all tables and columns in the database become replacement targets, including the post_content
column. This ensures that URLs within the content of articles and pages, such as links and images, will also be replaced.
Caution
This command handles serialized data correctly, so even fields containing serialized data are safely replaced. However, because all tables are included, there is a risk that unintended replacements may occur. For example, external links or URLs stored in configuration files by certain plugins may also be changed.
The wp search-replace
command performs replacements across the entire database, including the post content (post_content
).
Since all tables are included, it is important to use this command carefully. It is highly recommended to back up the database before executing the command, to prevent any accidental data loss.
WP-CLI Allows Safe and Efficient URL Replacements
WP-CLI makes it easy to replace URLs across the entire database, saving a significant amount of time compared to manually changing each URL one by one. Additionally, since it handles serialized data properly, the risk of data corruption is minimized.
Although the process may seem a bit complex, following each command step by step will make it manageable, even for beginners. Always take a backup first and use the --dry-run
option to proceed safely.
Importing a Database with WP-CLI
WP-CLI also provides a database import feature. Specifically, you can use the wp db import
command to import a database backup file (usually an SQL file) into the WordPress database.
How to Use the wp db import
Command
Here is the basic usage:
wp db import <filename>.sql
Replace <filename>.sql
with the name of the SQL file you want to import.
Before running this command, make sure you are in the WordPress installation directory.
Example
For example, if you want to import a backup file named backup.sql
:
wp db import backup.sql
Running this command will import the contents of backup.sql
into the current database.
Important Notes
- Database Backup: It is strongly recommended to back up the current database before performing an import. This will protect against data loss in case of any issues.
- Verify Database Connection Info: Make sure the correct database connection information is set in the
wp-config.php
file. - Sufficient Permissions: Ensure that the user running WP-CLI has sufficient permissions to access the database.
Other Database-Related Commands
WP-CLI provides several other useful commands for database management:
wp db reset
: Resets the database and deletes all tables.wp db reset
wp db query
: Runs custom SQL queries.wp db query "SELECT * FROM wp_posts WHERE post_status='publish';"
By using these commands, you can efficiently manage your WordPress database.
What to Do When WP-CLI is Unavailable
While WP-CLI is a highly useful tool, there are situations where it may not be available or cannot be installed on certain servers. In such cases, you still need a method to replace URLs in the WordPress database. Here, we will introduce a method to replace URLs using a custom script when WP-CLI is not available on the server.
Why a Custom Script is Necessary
URLs are stored in various locations in the WordPress database. Finding and replacing all these URLs manually would be a tedious task. If WP-CLI is available, it can handle the replacement in one go. However, if WP-CLI is unavailable, you can create your own script to efficiently operate on the database.
Special care needs to be taken when dealing with serialized data, as manual replacement can be risky. Using a script ensures that the replacement process is safe and accurate.
Using a Python Script to Replace URLs
Here, we will introduce a Python script to replace URLs in a MySQL database. Python is a versatile programming language that makes it easy to connect to and manipulate databases. This script is especially useful in environments where WP-CLI cannot be used.
Preparation: Installing Python and Necessary Modules
First, check if Python is installed on your server. If it is not installed, you can either ask your server administrator to install it or download it from the official Python website.
Next, install the Python module called MySQL Connector. This allows Python to connect to a MySQL database. Use the following command to install MySQL Connector:
pip install mysql-connector-python
Additionally, install any other required modules.
Creating a Custom Script
Next, create a script that safely operates on specific tables and columns, replacing the old URL with the new one in bulk.
import mysql.connector
import logging
import os
import argparse
from dotenv import load_dotenv
from concurrent.futures import ThreadPoolExecutor, as_completed
from tqdm import tqdm
import phpserialize
# Load environment variables from the .env file
load_dotenv()
# Log file settings
logging.basicConfig(
level=logging.DEBUG, # Set log level to DEBUG
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('wpurl_replace.log', encoding='utf-8'),
logging.StreamHandler()
]
)
# Parse command-line arguments
parser = argparse.ArgumentParser(description='WordPress URL replacement script')
parser.add_argument('--dry-run', action='store_true', help='Perform a dry run without making actual replacements')
parser.add_argument('--old-url', required=True, help='The URL to be replaced')
parser.add_argument('--new-url', required=True, help='The new URL to replace the old one')
args = parser.parse_args()
logging.debug(f"Command-line arguments: {args}")
# Database connection settings
db_config = {
'user': os.getenv('DB_USER'),
'password': os.getenv('DB_PASSWORD'),
'host': os.getenv('DB_HOST'),
'database': os.getenv('DB_NAME'),
}
logging.debug(f"Database settings: {db_config}")
# Function definitions (all included, no omissions)
# Function to retrieve the primary key for each table
def get_primary_key(table_name):
primary_keys = {
'wp_options': 'option_id',
'wp_postmeta': 'meta_id',
'wp_users': 'ID',
'wp_posts': 'ID',
'wp_commentmeta': 'meta_id',
'wp_comments': 'comment_ID',
'wp_links': 'link_id',
'wp_term_taxonomy': 'term_taxonomy_id',
'wp_termmeta': 'meta_id',
'wp_terms': 'term_id',
'wp_usermeta': 'umeta_id',
}
return primary_keys.get(table_name, 'id') # Default is 'id'
# Function to establish a database connection
def connect_to_database():
try:
conn = mysql.connector.connect(**db_config, autocommit=True)
logging.debug("Connected to the database")
return conn
except mysql.connector.Error as err:
logging.error(f"Database connection error: {err}")
raise
# Function to retrieve all tables
def get_all_tables(cursor):
cursor.execute("SHOW TABLES")
return [table[0] for table in cursor.fetchall()]
# Function to retrieve all columns for a specific table
def get_columns(cursor, table_name):
cursor.execute(f"SHOW COLUMNS FROM `{table_name}`")
return cursor.fetchall()
# Function to check if a column contains serialized data
def is_column_serialized(table_name, column_name):
serialized_columns = {
'wp_options': ['option_value'],
'wp_postmeta': ['meta_value'],
# Add other tables and columns containing serialized data
}
return table_name in serialized_columns and column_name in serialized_columns[table_name]
# Function to replace URLs in serialized data and re-serialize it
def unserialize_replace_serialize(data, old_url, new_url):
try:
unserialized = phpserialize.loads(data.encode())
if isinstance(unserialized, dict):
for key, value in unserialized.items():
if isinstance(value, bytes):
value_str = value.decode()
unserialized[key] = value_str.replace(old_url, new_url).encode()
return phpserialize.dumps(unserialized).decode()
except Exception:
return data.replace(old_url, new_url)
# Function to replace URLs in specific columns of a table
def replace_url_in_table(table_name, column_name, old_url, new_url, dry_run):
conn = connect_to_database() # Connect to the database per thread
cursor = conn.cursor()
try:
primary_key = get_primary_key(table_name) # Retrieve primary key
if is_column_serialized(table_name, column_name):
if dry_run:
logging.info(f"Would replace serialized data in {table_name}.{column_name}")
return 0
else:
sql = f"SELECT {primary_key}, `{column_name}` FROM `{table_name}` WHERE `{column_name}` LIKE %s"
cursor.execute(sql, (f'%{old_url}%',))
rows = cursor.fetchall()
logging.debug(f"Found {len(rows)} rows in {table_name}.{column_name}")
update_count = 0
for row in rows:
id, data = row
new_data = unserialize_replace_serialize(data, old_url, new_url)
if new_data != data:
update_sql = f"UPDATE `{table_name}` SET `{column_name}` = %s WHERE {primary_key} = %s"
cursor.execute(update_sql, (new_data, id))
logging.debug(f"Updated row with ID {id} in {table_name}.{column_name}")
update_count += 1
return update_count
else:
if dry_run:
sql = f"SELECT COUNT(*) FROM `{table_name}` WHERE `{column_name}` LIKE %s"
cursor.execute(sql, (f'%{old_url}%',))
count = cursor.fetchone()[0]
logging.info(f"Would replace {count} occurrences in {table_name}.{column_name}")
return count
else:
sql_update = f"""
UPDATE `{table_name}`
SET `{column_name}` = REPLACE(`{column_name}`, %s, %s)
WHERE `{column_name}` LIKE %s
"""
cursor.execute(sql_update, (old_url, new_url, f'%{old_url}%'))
affected_rows = cursor.rowcount
logging.debug(f"Updated {affected_rows} rows in {table_name}.{column_name}")
return affected_rows
except mysql.connector.Error as err:
logging.error(f"Error in {table_name}.{column_name}: {err}")
return 0
finally:
cursor.close()
conn.close()
def main():
try:
logging.debug("Starting the main function")
conn = connect_to_database()
cursor = conn.cursor()
tables = get_all_tables(cursor)
logging.debug(f"Retrieved tables: {tables}")
total_updates = 0
with ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for table_name in tables:
columns = get_columns(cursor, table_name)
logging.debug(f"Columns in table {table_name}: {columns}")
for (column_name, column_type, _, _, _, _) in columns:
if 'char' in column_type or 'text' in column_type or 'varchar' in column_type:
logging.debug(f"Processing {table_name}.{column_name}")
future = executor.submit(
replace_url_in_table,
table_name,
column_name,
args.old_url,
args.new_url,
args.dry_run
)
futures.append(future)
with tqdm(total=len(futures), desc="Processing") as pbar:
for future in as_completed(futures):
try:
result = future.result()
total_updates += result
pbar.update(1)
except Exception as e:
logging.error(f"Error during URL replacement: {e}", exc_info=True)
print(f"Total updates: {total_updates}")
if args.dry_run:
print("Dry run completed. No changes were made.")
else:
print("URL replacement completed.")
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
finally:
if 'conn' in locals() and conn.is_connected():
cursor.close()
conn.close()
logging.debug("Closed the database connection")
if __name__ == "__main__":
main()
Introduction
This script is a Python script for bulk replacing URLs in a WordPress database. When migrating a site to a new domain or server, it is necessary to replace old URLs with new ones, but doing this manually is a difficult task. By using this script, you can efficiently replace specified URLs from all text-type columns in the database.
Key Features
- Database Connection: Connects to a MySQL database using information from a
.env
file. - Scanning All Tables and Columns: Automatically detects all tables and text-type columns in the database.
- URL Replacement: Replaces the specified old URL with the new URL.
- Handling Serialized Data: Correctly processes columns containing serialized data, such as the
wp_options
andwp_postmeta
tables. - Dry Run Feature: By using the
--dry-run
option, you can check which data will be replaced without making actual changes. - Detailed Logging: Progress and results are recorded in the
wpurl_replace.log
file.
Environment and Preparation
Required Python Packages
- Python 3.7 or higher
mysql-connector-python
python-dotenv
tqdm
phpserialize
Installing Packages
Use the following command to install the necessary packages:
pip install mysql-connector-python python-dotenv tqdm phpserialize
Creating the .env
File
Create a .env
file in the same directory as the script with the following contents to store database connection information:
DB_USER=your_database_username
DB_PASSWORD=your_database_password
DB_HOST=your_database_host_or_IP_address
DB_NAME=your_database_name
How to Use the Script
Command-Line Arguments
--old-url
: The old URL to be replaced (required)--new-url
: The new URL to replace the old one (required)--dry-run
: Enable dry run mode (optional)
Example Usage
To actually replace the data:
python wpurl_replace.py --old-url http://oldsite.com --new-url http://newsite.com
To run in dry run mode (no changes will be made):
python wpurl_replace.py --old-url http://oldsite.com --new-url http://newsite.com --dry-run
Detailed Explanation of the Script
1. Connecting to the Database
The script reads the database connection information from the .env
file and connects to the MySQL database.
The connection uses the autocommit
option, ensuring that changes are automatically reflected in the database.
2. Detecting Tables and Columns
The script retrieves all tables in the database.
It then retrieves the column information for each table and identifies text-type columns (such as char
, varchar
, and text
).
3. Replacing URLs
Handling Serialized Data:
For columns that contain serialized data, such as the option_value
column in the wp_options
table or the meta_value
column in the wp_postmeta
table, special handling is required.
The data is unserialized, the old URL is recursively replaced with the new URL, and then the data is re-serialized before being saved back into the database.
Handling Regular Text Data:
For text-type columns, the SQL REPLACE
function is used to perform a bulk replacement.
Dry Run Mode:
When the --dry-run
option is specified, no actual data changes are made. Instead, the script logs the number of records that would be replaced.
4. Logging
The script logs the progress and any errors to the wpurl_replace.log
file.
Progress and results are also displayed in the console.
Important Notes
- Backups: Be sure to back up the database before running the script to prevent any data loss in case of an issue.
- Testing in a Staging Environment: First run the script in a staging environment to verify that it works as expected before running it in production.
- Appropriate Permissions: Ensure that the user connecting to the database has sufficient read and write permissions.
- Checking Logs: After running the script, check the
wpurl_replace.log
file for any errors.
Troubleshooting
If the log file is not generated:
- Ensure that the script has write permissions in the directory where it is being executed.
- Check that the logging settings are configured correctly in the script.
If an error occurs:
- Review the error messages in the
wpurl_replace.log
file to identify the issue. - If necessary, adjust the logging level in the script to obtain more detailed information.
If no replacements are made:
- Confirm that the old URL exists in the database.
- Ensure that the
--dry-run
option is not enabled.
This script automates the process of replacing URLs during WordPress site migrations or domain changes, significantly reducing the time and effort required. By using it correctly, you can safely and efficiently update URLs in the database.
FAQ
Q1. When should this script be used?
This script is used when migrating a WordPress site to a new domain or server to replace old URLs with new ones in the database all at once.
Q2. What is serialized data?
Serialized data refers to data that has been serialized using PHP’s serialize()
function. Arrays or objects are converted into a string and stored in the database. This script correctly deserializes and replaces the URLs in such data.
Q3. Is there anything I should be aware of before running the script?
Yes, be sure to back up your database. It is also recommended to verify the script’s behavior in a test environment before running it in production.
Support
If you have any questions or encounter issues, follow these steps for troubleshooting:
- Check the log file: Review the
wpurl_replace.log
file for any error messages or warnings. - Verify your environment: Make sure that the correct version of Python and all necessary packages are installed.
- Check your configuration: Confirm that the database connection information in the
.env
file and the command-line arguments are correct.
What if I’m not comfortable using the command line?
For those who are not familiar with the command line, web-based database management tools like PhpMyAdmin or Adminer are very useful. These tools allow you to manage databases intuitively through a web browser without needing to memorize commands, making them ideal for beginners or those who prefer GUI operations.
How to Import a Database Using PhpMyAdmin
- Access PhpMyAdmin: Open your browser and go to
http://yourdomain.com/phpmyadmin
to access PhpMyAdmin on your server. - Select the database: From the list on the left, choose the database where you want to import the data.
- Click the “Import” tab: In the top menu, select the “Import” tab.
- Choose the file: Under the “File to import” section, select the local SQL file you want to import.
- Set options: Adjust the character set and format options as needed.
- Run the import: Click the “Go” button at the bottom of the page to start the import.
Benefits of PhpMyAdmin
- User-friendly: The intuitive interface means you don’t need to memorize commands.
- Immediate feedback: Results are displayed immediately, allowing you to easily track the progress of your operations.
- Multi-functional: In addition to importing, PhpMyAdmin also allows you to edit tables, run queries, and more.
Things to Watch Out For
- Large file imports: Depending on the server settings, there may be limits on the file size you can upload. In such cases, consider adjusting the server settings or using command-line tools.
- Security: Since PhpMyAdmin is a powerful tool, it’s important to take proper security measures to prevent unauthorized access. Strengthen admin passwords and restrict access as necessary.
Alternative Tools
- Adminer: A lightweight, single-file database management tool. It’s easier to set up than PhpMyAdmin and offers the essential features in a compact form.
- MySQL Workbench: An official MySQL management tool available as a desktop application, offering advanced database management through a GUI.
For those who are uncomfortable with the command line or prefer a GUI, tools like PhpMyAdmin and Adminer are ideal. These tools make it easy to perform tasks such as importing/exporting databases and managing tables.
Key Points:
- Choose the tool that suits you: Select the most appropriate tool based on your task and skill level.
- Importance of backups: Always back up your database, regardless of the tool you are using.
- Security measures: Ensure proper security practices when using web-based tools.