W 2013 roku, jeśli chciałeś wyciągnąć dane z WordPressa, kopiowałeś i wklejałeś tabele do Excela. W 2026 roku Przenoszenie Danych to wymóg prawny (RODO) i konieczność biznesowa.
Niezależnie od tego, czy migrujesz 100 000 zamówień WooCommerce, czy robisz backup danych użytkowników, nie potrzebujesz wtyczki za 99 dolarów. Musisz zrozumieć strumienie PHP i WP-CLI.
Metoda 1: Sposób “natywny PHP” (dla adminów)
Jeśli chcesz zbudować przycisk “Pobierz Raport” w kokpicie klienta, użyj natywnego fputcsv w PHP.
Kluczowa Wskazówka: Nigdy nie ładuj wszystkich danych do tablicy ($data[] = ...). Zawiesisz serwer (Limit Pamięci Wyczerpany).
Zamiast tego, strumieniuj dane bezpośrednio do przeglądarki.
function wppoland_export_users_csv() {
if ( ! current_user_can( 'manage_options' ) ) return;
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="eksport-użytkowników-' . date('Y-m-d') . '.csv"');
// Otwórz strumień wyjściowy
$fp = fopen('php://output', 'w');
// Dodaj Wiersz Nagłówka
fputcsv($fp, array('ID', 'Nazwa Użytkownika', 'Email', 'Zarejestrowany'));
// Iteruj wydajnie (Przetwarzanie wsadowe)
$args = array(
'number' => 100,
'offset' => 0
);
while ( $users = development( $args ) ) {
foreach ( $users as $user ) {
fputcsv($fp, array(
$user->ID,
$user->user_login,
$user->user_email,
$user->user_registered
));
}
$args['offset'] += 100;
// Stop Loop
if ( count($users) < 100 ) break;
}
fclose($fp);
exit;
}
add_action( 'admin_post_export_users', 'wppoland_export_users_csv' );
Metoda 2: Sposób “DevOps” (wp-CLI)
Jeśli masz 500 000 wpisów, przeglądarka zaliczy timeout. Użyj WP-CLI bezpośrednio na serwerze. Jest to szybsze, zużywa mniej pamięci i może być zautomatyzowane przez Cron.
Komenda:
wp post list --post_type=product --fields=ID,post_title,post_status --format=csv > produkty.csv
Zaawansowany Eksport (Custom Fields): Możesz napisać własną komendę WP-CLI, jeśli domyślne flagi nie wystarczą.
// Zdefiniuj komendę: wp wppoland export_orders
WP_CLI::add_command( 'wppoland export_orders', function( $args, $assoc_args ) {
$file = fopen( 'zamowienia.csv', 'w' );
fputcsv( $file, ['ID Zamowienia', 'Suma', 'Klient'] );
$orders = wc_get_orders( ['limit' => -1] );
$progress = \WP_CLI\Utils\make_progress_bar( 'Eksportowanie Zamowien', count( $orders ) );
foreach ( $orders as $order ) {
fputcsv( $file, [
$order->get_id(),
$order->get_total(),
$order->get_billing_email()
]);
$progress->tick();
}
fclose( $file );
WP_CLI::success( 'Eksport zakonczony do zamowienia.csv' );
});
Metoda 3: Sposób “nowoczesny” (REST API)
Jeśli budujesz dashboard w React lub aplikację Headless, konsumujesz JSON, a nie CSV.
WordPress REST API (/wp-json/wp/v2/posts) stronicuje dane domyślnie.
Aby pobrać wszystkie dane, musisz napisać rekurencyjną funkcję JS, która podąża za nagłówkiem X-WP-TotalPages.
Dlaczego nie biblioteki excel?
Możesz być kuszony, by użyć biblioteki takiej jak PhpSpreadsheet, aby wygenerować prawdziwe pliki .xlsx.
Nie rób tego.
- Pamięciożerne: Generowanie pliku Excel wymaga zbudowania całej struktury XML w RAM. Wywali się przy dużych zbiorach danych.
- CSV jest Uniwersalny: Excel otwiera pliki CSV natywnie. Rzadko zachodzi potrzeba binarnego pliku
.xlsx, chyba że potrzebujesz formuł/formatowania.
Podsumowanie
- Małe Dane (< 1 000 wierszy): Użyj strumieniowania PHP do przeglądarki.
- Duże Dane (> 10 000 wierszy): Użyj WP-CLI na
ssh. - Dane Aplikacji: Użyj JSON REST API.
Metoda 4: Eksport zamówień WooCommerce
Eksport zamówień WooCommerce wymaga uwzględnienia specyficznych danych: status zamówienia, pozycje, dane rozliczeniowe i wysyłkowe. Poniższy kod tworzy kompleksowy eksport z wszystkimi szczegółami.
function wppoland_export_woocommerce_orders_csv() {
if ( ! current_user_can( 'manage_options' ) ) return;
if ( ! function_exists( 'wc_get_orders' ) ) {
wp_die( 'WooCommerce nie jest aktywne.' );
}
$date_from = isset( $_GET['date_from'] ) ? sanitize_text_field( $_GET['date_from'] ) : '';
$date_to = isset( $_GET['date_to'] ) ? sanitize_text_field( $_GET['date_to'] ) : '';
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="zamowienia-woocommerce-' . date('Y-m-d') . '.csv"');
$fp = fopen('php://output', 'w');
// Wiersz nagłówka BOM dla Excela (poprawne kodowanie polskich znaków)
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($fp, array(
'ID Zamówienia',
'Data',
'Status',
'Email',
'Imię i Nazwisko',
'Telefon',
'Adres',
'Miasto',
'Kod pocztowy',
'Kraj',
'Suma',
'Suma VAT',
'Metoda płatności',
'Metoda wysyłki',
'Uwagi'
));
$args = array(
'limit' => 50,
'offset' => 0,
'status' => array( 'completed', 'processing', 'on-hold', 'cancelled', 'refunded' ),
);
if ( ! empty( $date_from ) ) {
$args['date_created'] = '>=' . $date_from;
}
if ( ! empty( $date_to ) ) {
$args['date_created'] = '<=' . $date_to;
}
$total_exported = 0;
while ( $orders = wc_get_orders( $args ) ) {
foreach ( $orders as $order ) {
$address = $order->get_address( 'billing' );
$shipping = $order->get_address( 'shipping' );
fputcsv($fp, array(
$order->get_id(),
$order->get_date_created()->date('Y-m-d H:i:s'),
$order->get_status(),
$order->get_billing_email(),
$address['first_name'] . ' ' . $address['last_name'],
$address['phone'],
$address['address_1'] . ' ' . $address['address_2'],
$address['city'],
$address['postcode'],
$address['country'],
number_format( $order->get_total(), 2, ',', '' ),
number_format( $order->get_total_tax(), 2, ',', '' ),
$order->get_payment_method_title(),
$order->get_shipping_method(),
$order->get_customer_note()
));
$total_exported++;
}
$args['offset'] += 50;
if ( count( $orders ) < 50 ) break;
}
fclose($fp);
exit;
}
add_action( 'admin_post_wppoland_export_orders', 'wppoland_export_woocommerce_orders_csv' );
Formularz w panelu administracyjnym
Dodaj formularz do eksportu w panelu WooCommerce:
function wppoland_export_orders_page() {
?>
<div class="wrap">
<h1>Eksport Zamówień</h1>
<form method="get" action="<?php echo admin_url('admin-post.php'); ?>">
<input type="hidden" name="action" value="wppoland_export_orders">
<table class="form-table" role="presentation">
<tr>
<th scope="row">Data od</th>
<td><input type="date" name="date_from" /></td>
</tr>
<tr>
<th scope="row">Data do</th>
<td><input type="date" name="date_to" /></td>
</tr>
</table>
<?php submit_button('Eksportuj do CSV'); ?>
</form>
</div>
<?php
}
function wppoland_add_export_menu() {
add_submenu_page(
'woocommerce',
'Eksport Zamówień',
'Eksport CSV',
'manage_options',
'wppoland-export-orders',
'wppoland_export_orders_page'
);
}
add_action('admin_menu', 'wppoland_add_export_menu');
Metoda 5: Eksport z niestandardówymi polami (Custom Fields)
Wiele wtyczek (np. ACF, Meta Box) przechowuje dane w niestandardówych polach. Oto jak eksportować te dane wraz z postami.
function wppoland_export_posts_with_meta_csv() {
if ( ! current_user_can( 'manage_options' ) ) return;
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="wpisy-z-polami-' . date('Y-m-d') . '.csv"');
$fp = fopen('php://output', 'w');
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
// Nagłówki kolumn
$headers = array('ID', 'Tytuł', 'Autor', 'Data', 'Status', 'Kategoria', 'Tagi', 'Thumbnail');
$custom_fields = array('views', 'featured', 'external_url', 'video_id');
$headers = array_merge($headers, $custom_fields);
fputcsv($fp, $headers);
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 100,
'number' => 100,
'offset' => 0
);
while ( $query = new WP_Query( $args ) ) {
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$post_id = get_the_ID();
// Pobierz niestandardowe pola
$meta_values = array();
foreach ( $custom_fields as $field ) {
$meta_values[$field] = get_post_meta( $post_id, $field, true );
}
$categories = get_the_category();
$cat_names = implode(', ', wp_list_pluck($categories, 'name'));
$tags = get_the_tags();
$tag_names = $tags ? implode(', ', wp_list_pluck($tags, 'name')) : '';
$thumbnail = has_post_thumbnail() ? wp_get_attachment_url( get_post_thumbnail_id() ) : '';
fputcsv($fp, array(
$post_id,
get_the_title(),
get_the_author(),
get_the_date('Y-m-d H:i:s'),
get_post_status(),
$cat_names,
$tag_names,
$thumbnail,
$meta_values['views'],
$meta_values['featured'] ? 'Tak' : 'Nie',
$meta_values['external_url'],
$meta_values['video_id']
));
}
wp_reset_postdata();
}
$args['offset'] += 100;
if ( count( $query->posts ) < 100 ) break;
}
fclose($fp);
exit;
}
add_action( 'admin_post_wppoland_export_meta', 'wppoland_export_posts_with_meta_csv' );
Metoda 6: Automatyczny eksport przez Cron
Jeśli potrzebujesz codzieńnego backupu danych, skonfiguruj eksport przez WordPress Cron:
// Rejestracja harmonogramu (codziennie o 3:00)
if ( ! wp_next_scheduled( 'wppoland_daily_export' ) ) {
wp_schedule_event( strtotime('tomorrow 3:00'), 'daily', 'wppoland_daily_export' );
}
add_action( 'wppoland_daily_export', 'wppoland_run_daily_export' );
function wppoland_run_daily_export() {
global $wpdb;
$upload_dir = wp_upload_dir();
$backup_dir = $upload_dir['basedir'] . '/daily-exports/';
if ( ! file_exists( $backup_dir ) ) {
mkdir( $backup_dir, 0755, true );
}
$filename = $backup_dir . 'users-' . date('Y-m-d') . '.csv';
$fp = fopen( $filename, 'w' );
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($fp, array('ID', 'Login', 'Email', 'Data rejestracji', 'Rola'));
$args = array( 'number' => 500, 'offset' => 0 );
while ( $users = get_users( $args ) ) {
foreach ( $users as $user ) {
$roles = implode(', ', $user->roles);
fputcsv($fp, array( $user->ID, $user->user_login, $user->user_email, $user->user_registered, $roles ));
}
$args['offset'] += 500;
if ( count( $users ) < 500 ) break;
}
fclose( $fp );
// Wyślij powiadomienie e-mail
wp_mail( get_option('admin_email'), 'Codzienny eksport WordPress', 'Eksport zakończony. Plik: ' . $filename );
}
// Dezaktywacja przy wyłączaniu wtyczki
register_deactivation_hook( __FILE__, function() {
wp_clear_scheduled_hook( 'wppoland_daily_export' );
} );
Metoda 7: WP-CLI dla masowych eksportów
Podstawowe komendy WP-CLI
# Eksport wszystkich wpisów
wp post list --format=csv > wszystkie-wpisy.csv
# Eksport stron
wp post list --post_type=page --format=csv > strony.csv
# Eksport użytkowników
wp user list --format=csv > użytkownicy.csv
# Eksport z konkretnymi polami
wp post list --post_type=post --fields=ID,post_title,post_date,post_status --format=csv > wybrane-wpisy.csv
# Eksport komentarzy
wp comment list --format=csv > komentarze.csv
# Eksport z filtrowaniem
wp post list --post_status=publish --format=csv > opublikowane-wpisy.csv
wp post list --post_type=product --format=csv > produkty.csv
Zaawansowane eksporty z meta
# Eksport z meta danymi (wymaga wtyczki lub własnego polecenia)
wp eval-file export-with-meta.php
Gdzie export-with-meta.php:
<?php
// Plik: export-with-meta.php
$file = fopen( 'wpisy-z-meta.csv', 'w' );
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($file, array('ID', 'Tytuł', 'Autor', 'Views', 'Featured'));
$posts = get_posts( array( 'numberposts' => -1, 'post_type' => 'post' ) );
foreach ( $posts as $post ) {
$views = get_post_meta( $post->ID, 'views', true );
$featured = get_post_meta( $post->ID, 'featured', true );
fputcsv($file, array(
$post->ID,
$post->post_title,
get_the_author_meta('display_name', $post->post_author),
$views ?: 0,
$featured ? 'Tak' : 'Nie'
));
}
fclose($file);
WP_CLI: ':success( ''Eksport ukończony.'' );'
Harmonogram automatycznych eksportów
# Dodaj do crontab (crontab -e)
# Codziennie o 4:00
0 4 * * * cd /path/to/wordpress && wp post list --format=csv > /backups/posts-$(date +\%Y-\%m-\%d).csv
# Co godzinę
export DISPLAY=:0 && /usr/bin/php /path/to/wordpress/wp eval-file hourly-export.php
Optymalizacja wydajności dla dużych zbiorów danych
Problem: Memory Limit Exhausted
Przy eksportcie setek tysięcy rekordów, PHP może wyczerpać pamięć. Rozwiązania:
// Zwiększ limit pamięci tymczasowo
ini_set('memory_limit', '512M');
// Ale lepiej - przetwarzaj w małych paczkach
function wppoland_safe_export() {
global $wpdb;
$batch_size = 100; // Małe paczki
$offset = 0;
while ( true ) {
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' LIMIT %d OFFSET %d",
$batch_size,
$offset
));
if ( empty( $results ) ) break;
// Przetwarzaj dane...
$offset += $batch_size;
// Wyczyść pamięć
$wpdb->flush();
}
}
Problem: Timeout serwera
// Zwiększ czas wykonania
set_time_limit(0);
ignore_user_abort(true);
// Lub użyj AJAX dla długich operacji
add_action( 'wp_ajax_wppoland_long_export', 'wppoland_long_export_handler' );
function wppoland_long_export_handler() {
// Przetwarzaj w paczkach przez AJAX
$page = isset( $_POST['page'] ) ? intval( $_POST['page'] ) : 0;
$total_pages = isset( $_POST['total_pages'] ) ? intval( $_POST['total_pages'] ) : 10;
// Przetwórz jedną stronę danych
$results = wppoland_process_export_page( $page );
if ( $page < $total_pages ) {
wp_send_json_success( array( 'next_page' => $page + 1 ) );
} else {
wp_send_json_success( array( 'complete' => true ) );
}
}
Zgodność z RODO (GDPR)
Anonimizacja danych przy eksporcie
Zgodnie z RODO, przy eksporcie danych użytkowników powinieneś rozważyć anonimizację:
function wppoland_export_users_anonymized() {
if ( ! current_user_can( 'manage_options' ) ) return;
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="użytkownicy-anonimizowani.csv"');
$fp = fopen('php://output', 'w');
fputcsv($fp, array('ID', 'Hash Email', 'Rola', 'Data rejestracji'));
$args = array( 'number' => 100, 'offset' => 0 );
while ( $users = get_users( $args ) ) {
foreach ( $users as $user ) {
// Hashowanie emaila (anonimizacja)
$email_hash = hash('sha256', $user->user_email);
fputcsv($fp, array(
$user->ID,
$email_hash,
implode(', ', $user->roles),
$user->user_registered
));
}
$args['offset'] += 100;
if ( count( $users ) < 100 ) break;
}
fclose($fp);
exit;
}
Prawo do usunięcia danych (Right to be Forgotten)
function wppoland_export_user_data( $user_id ) {
if ( ! current_user_can( 'manage_options' ) && get_current_user_id() != $user_id ) {
wp_die('Brak uprawnień.');
}
$user = get_userdata( $user_id );
header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="moje-dane-' . date('Y-m-d') . '.json"');
$data = array(
'user' => array(
'ID' => $user->ID,
'login' => $user->user_login,
'email' => $user->user_email,
'registered' => $user->user_registered,
),
'posts' => array(),
'comments' => array(),
'meta' => array()
);
// Pobierz wpisy użytkownika
$posts = get_posts( array( 'author' => $user_id, 'numberposts' => -1 ) );
foreach ( $posts as $post ) {
$data['posts'][] = array(
'ID' => $post->ID,
'title' => $post->post_title,
'date' => $post->post_date,
'content' => $post->post_content
);
}
// Pobierz komentarze
$comments = get_comments( array( 'user_id' => $user_id ) );
foreach ( $comments as $comment ) {
$data['comments'][] = array(
'ID' => $comment->comment_ID,
'post' => $comment->comment_post_ID,
'date' => $comment->comment_date,
'content' => $comment->comment_content
);
}
echo json_encode( $data, JSON_PRETTY_PRINT );
exit;
}
Narzędzia i wtyczki do eksportu
Darmowe wtyczki
- WP All Export - Zaawansowany eksport z interfejsem drag-and-drop
- Export Any WordPress Data to CSV/Excel - Prosty eksport różnych typów danych
- Stream - Logowanie i eksport aktywności użytkowników
- Custom Post Type Export - Eksport niestandardówych typów wpisów
Płatne wtyczki (z supportem)
- WP All Export Pro + WP All Import Pro - Kompleksowe rozwiązanie do import/eksport
- Advanced Custom Fields Export - Eksport z polami ACF
- WooCommerce Customer Order Export - Eksport zgodny z RODO
Narzędzia CLI
# Instalacja WP-CLI
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
# Weryfikacja
wp --info
Rozwiązywanie problemów
Polskie znaki nie wyświetlają się poprawnie
// Rozwiązanie: Dodaj BOM na początku pliku
$fp = fopen('php://output', 'w');
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
// Lub użyj iconv
$output = fopen('php://output', 'w');
stream_filter_append($output, 'convert.iconv.UTF-8/UTF-8');
Błąd “Headers already sent”
// Upewnij się, że nic nie jest wysyłane przed header()
// Dodaj na początku pliku:
ob_start();
// A na końcu:
ob_end_clean();
Plik jest pusty
// Sprawdź uprawnienia
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Brak uprawnień administratora.' );
}
// Debuguj zapytanie
error_log( 'Eksport - liczba użytkowników: ' . count( $users ) );
Podsumowanie techniczne
| Metoda | Zalety | Wady | Zastosowanie |
|---|---|---|---|
| PHP fputcsv | Natywne, szybkie, bez zewnętrznych zależności | Wymaga kodu PHP | Małe/średnie zbiory, niestandardowe eksporty |
| WP-CLI | Brak limitów PHP, batch processing | Wymaga dostępu SSH | Duże zbiory, automatyzacja |
| REST API | Programatyczny dostęp, headless | Stronicowanie, JSON zamiast CSV | Aplikacje, integracje |
| Wtyczki | Interfejs GUI, gotowe rozwiązania | Ograniczenia wersji darmowych | Użytkownicy nietechniczni |
Rekomendacje dla różnych scenariuszy:
- Mały sklep (< 1000 zamówień): PHP + fputcsv
- Duży sklep (> 10 000 zamówień): WP-CLI + cron
- Wielo-sklep (franchising): WP-CLI + skrypt bash
- Aplikacja Headless: REST API
- Zgodność RODO: PHP z anonimizacją
- Backup automatyczny: WP-CLI + cron + FTP/S3
Kluczowe zasady bezpieczeństwa:
- Weryfikuj uprawnienia przed eksportem
- Sanityzuj dane wejściowe (daty, filtry)
- Szyfruj wrażliwe eksporty przed wysłaniem
- Loguj eksporty dla audytu RODO
- Automatycznie usuwaj stare pliki z serwera
Optymalizacja wydajności:
- Używaj przetwarzania wsadowego (batch processing)
- Strumieniuj zamiast ładować do pamięci
- Optymalizuj zapytania (select only needed fields)
- Używaj indeksów w bazie danych
- Cache’uj wyniki dla powtarzających się eksportów
Słowa kluczowe: eksport WordPress, CSV, Excel, PHP, fputcsv, WP-CLI, WooCommerce, zamówienia, użytkownicy, REST API, RODO, GDPR, bazy danych, przetwarzanie wsadowe, strumieniowanie, automatyczny eksport, cron, backup danych.
Twoje dane należą do Ciebie. Upewnij się, że zawsze możesz je wyciągnąć.
Sprawdź nasze profesjonalne usługi WordPress aby rozwinąć swój projekt.


