Using WP-CLI to Backup and Restore WordPress Widgets

If you have ever lost your WordPress widgets after changing or updating your theme, this guide will help you solve that problem for the future! I will show you how to back up the WordPress widgets  (header, footer, sidebar, inactive and active) with WP-CLI so you can easily restore your widgets at any time. This is incredibly useful for importing and exporting different widget sets if you are working on various designs or themes to make switching easy.

I have the privilege of using WP-CLI to solve complex issues for my clients on Codeable – where I just completed my 500th project! – so if you are looking for somebody who loves to automate with WP-CLI please get in touch.

Import and Export WordPress Widgets with WP-CLI

Backing up WordPress widgets properly involves two steps:

  1. Backup the status of active and inactive website and their positions
  2. Backup the widgets themselves from the wp_options table

Backup Active and Inactive WordPress Widgets

The WordPress widget status of active and inactive widgets is in the sidebar_widgets option in the wp_options table in the database.

We can grab this option and put it into the file /tmp/widgets.txt

wp option get sidebars_widgets --format=json > /tmp/widgets.txt

Now let's check the contents with the cat command

cat /tmp/widgets.txt

This is the serialized array of the widget structure and the widget IDs

{"wp_inactive_widgets":[],"sidebar-1":["search-2","text-2","recently-5","wpctc_widget-2","archives-2","wpp-3","text-3","custom_html-2","custom_html-3"],"sidebar-2":[],"header":[],"footer-1":["text-4"],"footer-2":["text-5"],"footer-3":[],"footer-4":[],"footer-5":[],"footer-bar":[],"top-bar":[],"array_version":3}

Here is the serialized array as pretty printed using JSON Pretty Print

{
   "wp_inactive_widgets":[

   ],
   "sidebar-1":[
      "search-2",
      "text-2",
      "recently-5",
      "wpctc_widget-2",
      "archives-2",
      "wpp-3",
      "text-3",
      "custom_html-2",
      "custom_html-3"
   ],
   "sidebar-2":[

   ],
   "header":[

   ],
   "footer-1":[
      "text-4"
   ],
   "footer-2":[
      "text-5"
   ],
   "footer-3":[

   ],
   "footer-4":[

   ],
   "footer-5":[

   ],
   "footer-bar":[

   ],
   "top-bar":[

   ],
   "array_version":3
}

You can restore the WordPress widgets by importing them with this WP-CLI option command which tells WP-CLI to read the backup as a json file (with --format=json) and make that the new sidebars_widgets option using the wp option update command.

wp option update sidebars_widgets --format=json < /tmp/widgets.txt

That covers the widget status, now let's do the widgets themselves.

Backing up WordPress Widgets with WP-CLI

Now it is on to the actual import and export of your widgets. We can us WP-CLI to run database queries, this one will show all of the widgets in the wp_options table.

wp db query "SELECT option_name FROM $(wp db prefix --allow-root)options WHERE option_name LIKE 'widget\_%'" --allow-root

I would hate to lose all of these widgets!

+---------------------------------+
| option_name                     |
+---------------------------------+
| widget_archives                 |
| widget_calendar                 |
| widget_categories               |
| widget_custom_html              |
| widget_gadwp-frontwidget-report |
| widget_list_widget              |
| widget_media_audio              |
| widget_media_gallery            |
| widget_media_image              |
| widget_media_video              |
| widget_meta                     |
| widget_nav_menu                 |
| widget_pages                    |
| widget_recent-comments          |
| widget_recent-posts             |
| widget_recently                 |
| widget_rss                      |
| widget_search                   |
| widget_tag_cloud                |
| widget_text                     |
| widget_wpctc_widget             |
| widget_wpp                      |
+---------------------------------+

Loop through these with bash and WP-CLI

# create array of all widgets in the wp_options table
WIDGETSARRAY=($(wp db query "SELECT option_name FROM $(wp db prefix --allow-root)options WHERE option_name LIKE 'widget\_%'" --skip-column-names --allow-root))

# loop through widgets
for WIDGET in ${WIDGETSARRAY[@]}
do
    wp option get ${WIDGET} --format=json --allow-root > /tmp/widgets/${WIDGET}.txt
done

Restoring the same widgets you backed up

# loop through widget backups
for WIDGETBACKUP in /tmp/widgets/*.txt
do
    # extract filename
    WIDGETFILE=$(basename ${WIDGETBACKUP})
    # get filename only without extension
    WIDGET="${WIDGETFILE%%.*}"
    # output which widget is being updated
    #echo "$WIDGET"
    # show widget backup contents
    #cat ${WIDGETBACKUP}
    WIDGETTEST=$(wp option get ${WIDGET} --allow-root)
    if [[ ! -z "$WIDGETTEST" ]]; then
         wp option update ${WIDGET} --format=json --allow-root < ${WIDGETBACKUP}
    else
         wp option add ${WIDGET} --format=json --allow-root < ${WIDGETBACKUP}
    fi
done

I hope this helps you from losing your widgets with theme switches in the future :).

Sources

WP-CLI option command
Update Serialized Options Programmatically
Get just the filename from a path in a bash script
Suppress header output from SQL