Пока у вас на сайте активен какой-либо плагин, то он может добавлять какие-либо свои данные, например опции, транзиты, события Cron или даже произвольные таблицы в базе данных. Что происходит с этими данными после того, как вы удаляете этот плагин? Если вы этом плагине ничего не предусмотрено на такой случай, то они остаются у вас на сайте навечно.
Чтобы глубже вникнуть в тему разработки плагинов, смотрите мой видеокурс.
register_uninstall_hook()
Функция register_uninstall_hook() уже описана в документации WordPress у меня на сайте. В общем и целом она позволяет привязать какую-либо функцию, которая будет выполняться при удалении плагина. Например:
register_uninstall_hook( __FILE__, 'true_delete_plugin_data' ); function true_delete_plugin_data() { // удаляем какую-либо опцию плагина delete_option( 'true_option' ); // удаляем кастомную таблицу из базы данных global $wpdb; $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}true_table" ); }
Также кстати ещё есть register_deactivation_hook(), который запускает функцию при деактивации плагина.
uninstall.php
Для использования этого метода вам понадобится создать файл uninstall.php
в папке с вашим плагином, например my-plugin/uninstall.php
. Этот файл будет запущен автоматически при удалениии плагина пользователем. Окружение WordPress разумеется в нём будет доступно.
Всегда проверяйте в самом начале плагина константу WP_UNINSTALL_PLUGIN
перед любыми действиями по очистки. Это защитит файл от прямого доступа к нему.
Вот так:
if( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { die; }
На всякий случай добавлю, что подобных действий делать не нужно при использовании хука register_uninstall_hook().
Общая структура файла может быть такой
<?php if( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { die; } // удаляем опции плагина // удаляем транзитный кэш // удаляем запланированные события WP_Cron // удаляем кастомные таблицы из базы данных // .. и так далее
Не беспокойтесь, сейчас мы рассмотрим удаление всех типов данных плагина по порядку.
Удаление опций плагина
Наверное опции – это то, что использует большинство плагинов на WordPress. Удаляются они довольно легко – при помощи функции delete_option() или delete_site_option() для WordPress Мультисайт.
// удаляем какую-либо опцию плагина delete_option( 'true_option' );
Если вам нужно удалить несколько опций, то можно это сделать циклом:
$options = array( 'true_option_1', 'true_option_2', 'true_option_3' ); foreach( $options as $option ) { delete_option( $option ); }
Кстати, будьте осторожны при запуске удаления опции каждого сайта внутри сети мультисайт через цикл get_sites() – это может быть довольно ресурсозатратная история.
$sites = get_sites( array( 'fields' => 'ids' ) ); foreach( $sites as $site_id ) { switch_to_blog( $site_id ); delete_option( 'true_option' ); restore_current_blog(); }
Удаление транзитного кэша
О том, что такое транзитный кэш и как его использовать, у меня есть даже целый видеоурок. Несмотря на то, что транзиты – это временный кэш, вы всё равно возможно захотите их очистить, как минимум для того, что не осталось ничего лишнего в базе данных.
Транзиты удаляются похожим способом, как опции (в конце концов это и есть временные опции), но только при помощи функции delete_transient() или delete_site_transient() для мультисайта.
// удаляем транзитный кэш delete_transient( 'true_transient' );
Так же, как и с опциями, эту историю можно прогнать через цикл
$transients = array( 'true_transient_1', 'true_transient_2', 'true_transient_3' ); foreach( $transients as $transient ) { delete_transient( $transients ); }
Удаление запланированных событий WP_Cron
События WP_Cron – это какие-либо действия, срабатывающие через определённое время на сайте, например запланированная публикация поста или же создание резервной копии раз в неделю.
Так вот, вполне возможно что ваш плагин тоже мог надобавлять подобных событий, которые теперь неплохо было бы подчистить.
Это можно легко сделать функциями wp_next_scheduled() и wp_unschedule_event().
// удаляем запланированные события WP_Cron $timestamp = wp_next_scheduled( 'true_cron_event' ); wp_unschedule_event( $timestamp, 'true_cron_event' );
Удаление таблиц из базы данных WordPress
Это, пожалуй, моя любимая часть, наверное потому, что после некоторых плагинов остаются огромные таблицы в БД. Хочу напомнить, что для работы с базой данных в WordPress мы всегда используем объект $wpdb.
// удаляем кастомные таблицы из базы данных global $wpdb; $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}true_table" );
Удаление записей и страниц
Вполне можно допустить, что ваш плагин во время использования на сайте создал какое-либо количество системных страниц, как WooCommerce.
Так вот, их мы тоже можем удалить при помощи функции wp_trash_post() или wp_delete_post(). Если будете использовать вторую функцию, то при передаче второго параметра в неё, пост минует корзину и удалится безвозвратно. Давайте так и сделаем.
wp_delete_post( 55, true ); // удалили безвозвратно пост с ID=55
Однако возможно у вас возник вполне резонный вопрос – откуда мы взяли это 55
? И правда, при активации плагина ID его системных страниц могут быть абсолютно разными и мы никак не можем на это повлиять. Единственный способ – записать эти ID в опцию при создании системных страниц.
// удаляем системные страницы $plugin_pages = get_option( 'true_pages' ); if( $plugin_pages && is_array( $plugin_pages ) ) { foreach( $plugin_pages as $page_id ) { wp_trash_post( $page_id ); } } // и ещё и опцию удаляем к тому же! delete_option( 'true_pages' )
Удаление всех постов опредлённого кастомного типа записи
Намного легче, чем удалять страницы! Потому что, для того, чтобы получить какие-то определённые ID страниц, созданных плагином, нам приходилось получать их из опций, а тут достаточно воспользоваться функцией get_posts(), чтобы сразу получить все посты произвольного типа записи.
// удаляем все произвольные типы постов $cpts = get_posts( array( 'post_type' => 'true_cpt', 'posts_per_page' => -1, 'fields' => 'ids' ) ); if( $cpts ) { foreach( $cpts as $cpt_id ) { wp_delete_post( $cpt_id, true ); } }
Наверное полезно упомянуть, что функция wp_delete_post() также удаляет и все данные, привязанные к постам, например комментарии и метаданные.
Удаление метаданных
Также плагины нередко добавляют какие-то метаданные к определённому типу контента – например к пользователям или к постам на сайте. Их бы неплохо тоже было бы удалить.
Не рекомендую использовать функции update_user_meta(), update_post_meta() и т д в цикле.
// удаляем метаданные $users = get_users(); foreach( $users as $user ) { delete_user_meta( $user->ID, 'true_user_meta'); }
Понимаю, что код выглядит чистым и приятным, кроме того, если нужно исключить каких-то определённых пользователей, то сделать это легко при помощи дополнительных параметров. Однако, зачем? И действительно ли это хорошее решение для 100К пользователей?
Поэтому я бы порекомендовал вам воспользоваться функцией delete_metadata() с параметром $delete_all
в значении true
. Тот же пример, что и сверху, но значительно более оптимальный с точки зрения производительности:
// удаляем метаданные delete_metadata( 'user', 0, 'true_user_meta', null, true );
И ещё кое-что… Что если плагин был удалён по ошибке?
Предположим, что ваш плагин содержит какое-то неимоверное количество сложных настроек. Которые, скажем, настраивал даже не пользователь сайта, а какой-то разработчик, который сайтом занимался. А тут плагин удалили по ошибке и все настройки исчезли безвозвратно!
В таких исключительных случаях я рекомендую ко всем настройкам добавить ещё и какой-нибудь чекбокс например «Удалить все опции плагина при его удалении». Не знаю, имеет ли смысл давать ссылку на пост о том, как создавать страницы настроек, ведь, если вы читаете этот пост, наверное вы и так уже разрабатываете свои плагины.
После того, как чекбокс был добавлен, можно добавить соответствующее условий где-нибудь в начале файла uninstall.php
:
if( ! get_option( 'true_do_uninstall', false ) ) { die; }
Источник: Блог Миши Рудрастых