Что такое uninstall.php? Очистка данных после удаления плагина

Пока у вас на сайте активен какой-либо плагин, то он может добавлять какие-либо свои данные, например опции, транзиты, события 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

После того, как чекбокс был добавлен, можно добавить соответствующее условий где-нибудь в начале файла uninstall.php:

if( ! get_option( 'true_do_uninstall', false ) ) {
	die;
}

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал