Po co pisać własną wtyczkę?
Wtyczka WordPress to samodzielny moduł, który rozszerza funkcjonalność CMS-a niezależnie od aktywnego motywu. Pisanie własnej wtyczki ma sens gdy:
- chcesz dodać funkcję, która ma działać niezależnie od zmiany motywu
- tworzysz coś do wielokrotnego użycia na kilku projektach
- wbudowane wtyczki z repozytorium są zbyt ciężkie lub mają zbyt wiele funkcji
- potrzebujesz pełnej kontroli nad kodem i aktualizacjami
Własna wtyczka to też dobra praktyka architektoniczna: logika biznesowa (custom post types, shortcody, integracje API) trzymana w wtyczce pozostaje dostępna nawet gdy zmienisz motyw na zupełnie inny.
Struktura katalogów i pliki
Wtyczka WordPress to minimum jeden plik PHP z nagłówkiem. W praktyce dobrze zorganizowana wtyczka wygląda tak:
wp-content/plugins/moja-wtyczka/
├── moja-wtyczka.php # plik główny (nagłówek + bootstrap)
├── uninstall.php # czyszczenie przy odinstalowaniu
├── includes/
│ ├── class-moja-wtyczka.php # główna klasa
│ ├── shortcodes.php
│ ├── ajax.php
│ └── helpers.php
├── admin/
│ ├── admin-page.php
│ └── settings.php
├── assets/
│ ├── css/
│ └── js/
└── languages/
└── moja-wtyczka.pot
Nagłówek i bootstrap
Plik główny musi zawierać specjalny komentarz PHP, który WordPress rozpoznaje jako nagłówek wtyczki:
<?php
/**
* Plugin Name: Moja Wtyczka
* Plugin URI: https://twoja-strona.pl/moja-wtyczka
* Description: Krótki opis — widoczny w panelu WordPress.
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 8.0
* Author: Lucjan Jaroszewski
* Author URI: https://twoja-strona.pl
* License: GPL v2 or later
* Text Domain: moja-wtyczka
* Domain Path: /languages
*/
// Zabezpieczenie — blokuje wywołanie pliku bezpośrednio przez URL
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Stałe — dostępne w całej wtyczce
define( 'MOJA_WTYCZKA_VERSION', '1.0.0' );
define( 'MOJA_WTYCZKA_DIR', plugin_dir_path( __FILE__ ) );
define( 'MOJA_WTYCZKA_URL', plugin_dir_url( __FILE__ ) );
// Bootstrap — załaduj główną klasę
require_once MOJA_WTYCZKA_DIR . 'includes/class-moja-wtyczka.php';
/**
* Uruchom wtyczkę.
*/
function moja_wtyczka_run(): void {
$plugin = new Moja_Wtyczka();
$plugin->run();
}
moja_wtyczka_run();
Aktywacja i deaktywacja
WordPress udostępnia hooki do kodu wykonywanego przy aktywacji, deaktywacji i odinstalowaniu wtyczki. To miejsce na tworzenie tabel bazy danych, opcji domyślnych i flush rewrite rules:
<?php
// W pliku głównym wtyczki
/**
* Uruchamiane przy aktywacji w panelu WP.
*/
function moja_wtyczka_aktywacja(): void {
// Utwórz własną tabelę w bazie
global $wpdb;
$table_name = $wpdb->prefix . 'moje_wpisy';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$table_name} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
tresc TEXT NOT NULL,
data_wpisu DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id)
) {$charset_collate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
// Ustaw domyślne opcje
add_option( 'moja_wtyczka_settings', [
'aktywna' => true,
'limit' => 10,
]);
// Wymuś odświeżenie permalinków
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'moja_wtyczka_aktywacja' );
/**
* Uruchamiane przy deaktywacji — NIE usuwaj danych użytkownika.
*/
function moja_wtyczka_deaktywacja(): void {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'moja_wtyczka_deaktywacja' );
Nie usuwaj danych użytkownika przy deaktywacji — użytkownik może deaktywować
wtyczkę tymczasowo. Dane i opcje usuń dopiero w uninstall.php,
gdy użytkownik jawnie odinstaluje wtyczkę przez panel.
Strona ustawień — Settings API
WordPress ma wbudowane Settings API, które obsługuje formularze, walidację i zapisywanie opcji bezpiecznie (z nonce i sanityzacją):
<?php
/**
* Rejestracja strony ustawień i pól.
*/
function moja_wtyczka_admin_menu(): void {
add_options_page(
'Moja Wtyczka — Ustawienia',
'Moja Wtyczka',
'manage_options',
'moja-wtyczka',
'moja_wtyczka_render_page'
);
}
add_action( 'admin_menu', 'moja_wtyczka_admin_menu' );
function moja_wtyczka_settings_init(): void {
register_setting(
'moja_wtyczka_group',
'moja_wtyczka_settings',
[ 'sanitize_callback' => 'moja_wtyczka_sanitize' ]
);
add_settings_section(
'moja_wtyczka_section',
'Ustawienia ogólne',
null,
'moja-wtyczka'
);
add_settings_field(
'limit',
'Limit wpisów',
'moja_wtyczka_field_limit',
'moja-wtyczka',
'moja_wtyczka_section'
);
}
add_action( 'admin_init', 'moja_wtyczka_settings_init' );
function moja_wtyczka_field_limit(): void {
$options = get_option( 'moja_wtyczka_settings', [] );
$limit = (int) ( $options['limit'] ?? 10 );
echo '<input type="number" name="moja_wtyczka_settings[limit]"
value="' . esc_attr( $limit ) . '" min="1" max="100" />';
}
function moja_wtyczka_sanitize( array $input ): array {
return [
'aktywna' => ! empty( $input['aktywna'] ),
'limit' => max( 1, min( 100, (int) ( $input['limit'] ?? 10 ) ) ),
];
}
function moja_wtyczka_render_page(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields( 'moja_wtyczka_group' );
do_settings_sections( 'moja-wtyczka' );
submit_button();
?>
</form>
</div>
<?php
}
Bezpieczeństwo first: Zawsze sprawdzaj uprawnienia
(current_user_can()), używaj nonce przy własnych formularzach
(wp_nonce_field() / check_admin_referer())
i sanityzuj każde wejście użytkownika.
Podsumowanie
Pierwsza własna wtyczka WordPress może wyglądać skomplikowanie, ale wystarczy kilka plików i znajomość kilku wzorców: nagłówek, hooki aktywacyjne, Settings API. Pisząc własne wtyczki zamiast szukania gotowych, zyskujesz pełną kontrolę nad kodem, brakiem zbędnych funkcji i możliwością wielokrotnego użycia w różnych projektach.