• Home
  • Guides
    • All
    • Linux
    • Programming
    • Tools
    • WordPress
    Building a Simple WordPress Post List Tool with PHP

    Building a Simple WordPress Post List Tool with PHP

    Monitoring Web Page Changes with Python

    Monitoring Web Page Changes with Python

    My SSH Setup: How I Manage Multiple Servers

    My SSH Setup: How I Manage Multiple Servers

    Building a Network Tracker Auditor for Privacy with Python

    Building a Network Tracker Auditor for Privacy with Python

    Streaming Audio Files Securely with PHP

    Streaming Audio Files Securely with PHP

    Scraping Web Data with Python Helium

    Scraping Web Data with Python Helium

    Building a Secure 2FA Authenticator with Python

    Building a Secure 2FA Authenticator with Python

    Building a Cache Warmer with Python

    Building a Cache Warmer with Python

    How to Create a Python GUI to Launch Webhooks

    How to Create a Python GUI to Launch Webhooks

  • Blog
    • All
    • Artificial Intelligence
    • Privacy
    • Reviews
    • Security
    • Tutorials
    Why Stable Websites Outperform Flashy Redesigns

    Why Stable Websites Outperform Flashy Redesigns

    AdGuard Ad Blocker Review

    AdGuard Ad Blocker Review

    Surfshark VPN Review

    Surfshark VPN Review

    Nmap Unleash the Power of Cybersecurity Scanning

    Nmap: Unleash the Power of Cybersecurity Scanning

    Floorp Browser Review

    Floorp Browser Review

    Understanding Man-in-the-Middle Attacks

    Understanding Man-in-the-Middle Attacks

    Privacy-Focused Analytics

    Privacy-Focused Analytics: Balancing Insights and Integrity

    Safeguarding Your Facebook Account

    Safeguarding Your Facebook Account: Understanding the Differences Between Hacking and Cloning

    38 essential points to harden WordPress

    38 Essential Points to Harden WordPress

  • Apps
    • Bible App
    • Bible Verse Screensaver
    • Blue AI Chatbot
    • Early Spring Predictor
    • FIGlet Generator
    • Password Generator
    • StegX
    • The Matrix
    • WeatherX
    • Website Risk Level Tool
  • About
    • About JMooreWV
    • Live Cyber Attacks
  • Contact
    • General Contact
    • Website Administration & Cybersecurity
No Result
View All Result
  • Home
  • Guides
    • All
    • Linux
    • Programming
    • Tools
    • WordPress
    Building a Simple WordPress Post List Tool with PHP

    Building a Simple WordPress Post List Tool with PHP

    Monitoring Web Page Changes with Python

    Monitoring Web Page Changes with Python

    My SSH Setup: How I Manage Multiple Servers

    My SSH Setup: How I Manage Multiple Servers

    Building a Network Tracker Auditor for Privacy with Python

    Building a Network Tracker Auditor for Privacy with Python

    Streaming Audio Files Securely with PHP

    Streaming Audio Files Securely with PHP

    Scraping Web Data with Python Helium

    Scraping Web Data with Python Helium

    Building a Secure 2FA Authenticator with Python

    Building a Secure 2FA Authenticator with Python

    Building a Cache Warmer with Python

    Building a Cache Warmer with Python

    How to Create a Python GUI to Launch Webhooks

    How to Create a Python GUI to Launch Webhooks

  • Blog
    • All
    • Artificial Intelligence
    • Privacy
    • Reviews
    • Security
    • Tutorials
    Why Stable Websites Outperform Flashy Redesigns

    Why Stable Websites Outperform Flashy Redesigns

    AdGuard Ad Blocker Review

    AdGuard Ad Blocker Review

    Surfshark VPN Review

    Surfshark VPN Review

    Nmap Unleash the Power of Cybersecurity Scanning

    Nmap: Unleash the Power of Cybersecurity Scanning

    Floorp Browser Review

    Floorp Browser Review

    Understanding Man-in-the-Middle Attacks

    Understanding Man-in-the-Middle Attacks

    Privacy-Focused Analytics

    Privacy-Focused Analytics: Balancing Insights and Integrity

    Safeguarding Your Facebook Account

    Safeguarding Your Facebook Account: Understanding the Differences Between Hacking and Cloning

    38 essential points to harden WordPress

    38 Essential Points to Harden WordPress

  • Apps
    • Bible App
    • Bible Verse Screensaver
    • Blue AI Chatbot
    • Early Spring Predictor
    • FIGlet Generator
    • Password Generator
    • StegX
    • The Matrix
    • WeatherX
    • Website Risk Level Tool
  • About
    • About JMooreWV
    • Live Cyber Attacks
  • Contact
    • General Contact
    • Website Administration & Cybersecurity
No Result
View All Result
Home Guides Programming PHP

Building a Simple WordPress Post List Tool with PHP

Jonathan Moore by Jonathan Moore
13 seconds ago
Reading Time: 8 mins read
A A
Building a Simple WordPress Post List Tool with PHP
FacebookTwitter

I needed a quick way to view all my WordPress posts without logging into the admin dashboard. Sometimes you just want a fast, no-nonsense list that you can sort and browse through. So I built a standalone PHP script that sits in my WordPress root directory and does exactly that.

This tool displays posts in a clean HTML table with sorting options, category filtering, and pagination. You can filter by category using a dropdown, sort by date or title, and page through results. Perfect for when you need quick access to your content without the overhead of the full WordPress admin.

The Complete Script

Create a file called list-posts.php or something similar in your WordPress root directory (the same folder that contains wp-config.php):

<?php
/**
 * Simple WordPress Post Lister
 * Place this file in your WordPress root directory
 */

// Configuration
$posts_per_page = 25;

// Load WordPress
require_once( 'wp-load.php' );

// Get current page, sort parameters, and category
$current_page = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'date';
$order = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'DESC';
$selected_category = isset( $_GET['category'] ) ? sanitize_text_field( $_GET['category'] ) : '';

// Build query arguments
$args = array(
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => $posts_per_page,
    'paged' => $current_page,
    'orderby' => $orderby,
    'order' => $order
);

// Add category filter if specified
if ( ! empty( $selected_category ) ) {
    $args['category_name'] = $selected_category;
}

// Run the query
$query = new WP_Query( $args );
$total_posts = $query->found_posts;
$total_pages = $query->max_num_pages;

// Get all categories
$categories = get_categories( array(
    'orderby' => 'name',
    'order' => 'ASC',
    'hide_empty' => true
) );

// Helper function to build sort URLs
function get_sort_url( $new_orderby, $current_orderby, $current_order, $category ) {
    $new_order = 'DESC';

    if ( $new_orderby === $current_orderby ) {
        $new_order = ( $current_order === 'DESC' ) ? 'ASC' : 'DESC';
    }

    $url = '?orderby=' . $new_orderby . '&order=' . $new_order;

    if ( ! empty( $category ) ) {
        $url .= '&category=' . $category;
    }

    return $url;
}

// Helper function to build pagination URLs
function get_page_url( $page, $orderby, $order, $category ) {
    $url = '?orderby=' . $orderby . '&order=' . $order . '&paged=' . $page;

    if ( ! empty( $category ) ) {
        $url .= '&category=' . $category;
    }

    return $url;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WordPress Post List</title>
    <style>
        body {
            font-family: "Segoe UI", Roboto, sans-serif;
            max-width: 1200px;
            margin: 40px auto;
            padding: 0 20px;
            background: #f5f5f5;
        }

        .container {
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba( 0, 0, 0, 0.1 );
        }

        h1 {
            margin-top: 0;
            color: #333;
        }

        .filter-bar {
            margin-bottom: 20px;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 4px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .filter-bar label {
            font-weight: 600;
            color: #333;
        }

        .filter-bar select {
            padding: 8px 12px;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            background: white;
            font-size: 14px;
            min-width: 200px;
        }

        .info {
            margin-bottom: 20px;
            color: #666;
            font-size: 14px;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }

        th {
            background: #f8f9fa;
            padding: 12px;
            text-align: left;
            border-bottom: 2px solid #dee2e6;
            font-weight: 600;
        }

        th a {
            color: #333;
            text-decoration: none;
        }

        th a:hover {
            color: #0066cc;
        }

        td {
            padding: 12px;
            border-bottom: 1px solid #dee2e6;
        }

        tr:hover {
            background: #f8f9fa;
        }

        .post-link {
            color: #0066cc;
            text-decoration: none;
        }

        .post-link:hover {
            text-decoration: underline;
        }

        .pagination {
            display: flex;
            gap: 10px;
            justify-content: center;
            margin-top: 30px;
        }

        .pagination a,
        .pagination span {
            padding: 8px 12px;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            text-decoration: none;
            color: #333;
        }

        .pagination a:hover {
            background: #f8f9fa;
        }

        .pagination .current {
            background: #0066cc;
            color: white;
            border-color: #0066cc;
        }

        .sort-indicator {
            font-size: 12px;
            margin-left: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>WordPress Post List</h1>

        <div class="filter-bar">
            <label for="category-select">Category:</label>
            <select id="category-select" onchange="window.location.href=this.value;">
                <option value="?orderby=<?php echo $orderby; ?>&order=<?php echo $order; ?>">All Categories</option>
                <?php foreach ( $categories as $category ) : ?>
                    <option value="?orderby=<?php echo $orderby; ?>&order=<?php echo $order; ?>&category=<?php echo $category->slug; ?>"
                            <?php selected( $selected_category, $category->slug ); ?>>
                        <?php echo esc_html( $category->name ); ?> (<?php echo $category->count; ?>)
                    </option>
                <?php endforeach; ?>
            </select>
        </div>

        <div class="info">
            Showing <?php echo $total_posts; ?> posts
            <?php if ( ! empty( $selected_category ) ) : ?>
                <?php
                $cat_obj = get_category_by_slug( $selected_category );
                if ( $cat_obj ) :
                ?>
                    in category: <strong><?php echo esc_html( $cat_obj->name ); ?></strong>
                <?php endif; ?>
            <?php endif; ?>
        </div>

        <table>
            <thead>
                <tr>
                    <th style="width: 70%;">
                        <a href="<?php echo get_sort_url( 'title', $orderby, $order, $selected_category ); ?>">
                            Title
                            <?php if ( $orderby === 'title' ) : ?>
                                <span class="sort-indicator"><?php echo ( $order === 'DESC' ) ? '↓' : '↑'; ?></span>
                            <?php endif; ?>
                        </a>
                    </th>
                    <th style="width: 30%;">
                        <a href="<?php echo get_sort_url( 'date', $orderby, $order, $selected_category ); ?>">
                            Date
                            <?php if ( $orderby === 'date' ) : ?>
                                <span class="sort-indicator"><?php echo ( $order === 'DESC' ) ? '↓' : '↑'; ?></span>
                            <?php endif; ?>
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <?php if ( $query->have_posts() ) : ?>
                    <?php while ( $query->have_posts() ) : $query->the_post(); ?>
                        <tr>
                            <td>
                                <a href="<?php echo get_permalink(); ?>" class="post-link" target="_blank">
                                    <?php echo get_the_title(); ?>
                                </a>
                            </td>
                            <td>
                                <?php echo get_the_date( 'F j, Y' ); ?>
                            </td>
                        </tr>
                    <?php endwhile; ?>
                <?php else : ?>
                    <tr>
                        <td colspan="2">No posts found.</td>
                    </tr>
                <?php endif; ?>
            </tbody>
        </table>

        <?php if ( $total_pages > 1 ) : ?>
            <div class="pagination">
                <?php if ( $current_page > 1 ) : ?>
                    <a href="<?php echo get_page_url( $current_page - 1, $orderby, $order, $selected_category ); ?>">← Previous</a>
                <?php endif; ?>

                <?php for ( $i = 1; $i <= $total_pages; $i++ ) : ?>
                    <?php if ( $i === $current_page ) : ?>
                        <span class="current"><?php echo $i; ?></span>
                    <?php else : ?>
                        <a href="<?php echo get_page_url( $i, $orderby, $order, $selected_category ); ?>"><?php echo $i; ?></a>
                    <?php endif; ?>
                <?php endfor; ?>

                <?php if ( $current_page < $total_pages ) : ?>
                    <a href="<?php echo get_page_url( $current_page + 1, $orderby, $order, $selected_category ); ?>">Next →</a>
                <?php endif; ?>
            </div>
        <?php endif; ?>

        <?php wp_reset_postdata(); ?>
    </div>
</body>
</html>

How It Works

The script starts by loading WordPress with require_once( 'wp-load.php' ). This gives us access to all WordPress functions without needing to be inside the admin dashboard or a theme file.

Configuration

At the top, I set one configuration variable:

$posts_per_page = 25;

The $posts_per_page variable controls pagination. Set it to whatever number works for you.

Query Parameters

The script accepts URL parameters for sorting, pagination, and category filtering:

$current_page = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'date';
$order = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'DESC';
$selected_category = isset( $_GET['category'] ) ? sanitize_text_field( $_GET['category'] ) : '';

I use sanitize_text_field() to clean the input and max( 1, intval() ) to make sure the page number is always at least 1.

Getting Categories

To populate the dropdown, I fetch all categories that have at least one post:

$categories = get_categories( array(
    'orderby' => 'name',
    'order' => 'ASC',
    'hide_empty' => true
) );

The hide_empty parameter makes sure empty categories don’t show up in the list. Categories are sorted alphabetically by name.

Building the Query

WordPress’s WP_Query class handles all the heavy lifting:

$args = array(
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => $posts_per_page,
    'paged' => $current_page,
    'orderby' => $orderby,
    'order' => $order
);

If a category is selected from the dropdown, it gets added to the query arguments automatically.

Helper Functions

I created two helper functions to keep the template code clean. The get_sort_url() function builds URLs for the sortable column headers. When you click a column that’s already sorted, it reverses the sort direction. It also preserves the selected category:

function get_sort_url( $new_orderby, $current_orderby, $current_order, $category ) {
    $new_order = 'DESC';
    
    if ( $new_orderby === $current_orderby ) {
        $new_order = ( $current_order === 'DESC' ) ? 'ASC' : 'DESC';
    }
    
    $url = '?orderby=' . $new_orderby . '&order=' . $new_order;
    
    if ( ! empty( $category ) ) {
        $url .= '&category=' . $category;
    }
    
    return $url;
}

The get_page_url() function builds pagination links while preserving both the current sort settings and selected category.

The Category Dropdown

The filter bar sits at the top of the page with a clean dropdown selector:

<select id="category-select" onchange="window.location.href=this.value;">
    <option value="?orderby=<?php echo $orderby; ?>&order=<?php echo $order; ?>">All Categories</option>
    <?php foreach ( $categories as $category ) : ?>
        <option value="?orderby=<?php echo $orderby; ?>&order=<?php echo $order; ?>&category=<?php echo $category->slug; ?>" 
                <?php selected( $selected_category, $category->slug ); ?>>
            <?php echo esc_html( $category->name ); ?> (<?php echo $category->count; ?>)
        </option>
    <?php endforeach; ?>
</select>

Each category option shows the category name and post count. The selected() function makes sure the current category stays selected when you sort or paginate. When you change the category, the page reloads with the new filter applied while keeping your current sort order.

The Display

The HTML table shows post titles as clickable links that open in a new tab. Column headers are clickable for sorting, with small arrows indicating the current sort direction.

Pagination appears at the bottom if there’s more than one page of results. It shows Previous/Next buttons plus numbered page links. All pagination links preserve your category filter and sort order.

Using the Script

Upload list-posts.php to your WordPress root directory and access it at https://yoursite.com/list-posts.php.

The page loads with all posts sorted by date, newest first. Use the category dropdown to filter posts. Click the column headers to change the sort order. The date column toggles between newest and oldest. The title column toggles between A-Z and Z-A.

When you filter by category, the info line shows which category you’re viewing. The dropdown stays on your selected category as you sort and page through results.

Security Notes

This script doesn’t include authentication, so anyone who finds the URL can view your post list. For a production site, I would add a simple password check at the top:

$password = 'your-secure-password';

if ( ! isset( $_GET['pw'] ) || $_GET['pw'] !== $password ) {
    die( 'Access denied' );
}

Then access it with https://yoursite.com/list-posts.php?pw=your-secure-password.

Or better yet, protect it with .htaccess authentication or only use it on development sites.

Customization Ideas

You can easily extend this script. Here are some ideas:

  • Add more columns like author, word count, or comment count
  • Include post excerpts in an expandable row
  • Add a search box to filter by title
  • Show draft posts alongside published ones
  • Export the list to CSV
  • Add checkboxes for bulk actions
  • Filter by multiple categories at once
  • Add date range filtering

The basic structure is flexible enough to add whatever you need.

That’s it! A simple, fast way to view, filter, and sort your WordPress posts without touching the admin dashboard.

Tags: Admin ToolsPHPPost ManagementWordPress
ShareTweetSharePinShareShareScan
ADVERTISEMENT
Jonathan Moore

Jonathan Moore

Senior Software Engineer and Cybersecurity Specialist with over 3 decades of experience in developing web, desktop, and server applications for Linux and Windows-based operating systems. Worked on numerous projects, including automation, artificial intelligence, data analysis, application programming interfaces, intrusion detection systems, streaming audio servers, WordPress plugins, and much more.

Related Articles

Streaming Audio Files Securely with PHP

Streaming Audio Files Securely with PHP

PHP is widely used for managing file access, handling data securely, and serving multimedia content online. One of the common...

Groundhog Day: Predicting Early Spring with PHP

Groundhog Day: Predicting Early Spring with PHP

In the quaint town of Punxsutawney, Pennsylvania, a unique tradition unfolds each year on February 2nd, known as Groundhog Day....

Automating JavaScript Minification with PHP

Automating JavaScript Minification with PHP

Automating JavaScript minification with PHP can significantly streamline a developer's workflow. It ensures that the deployed code is always in...

Recommended Services

Latest Articles

Building a Simple WordPress Post List Tool with PHP

Building a Simple WordPress Post List Tool with PHP

I needed a quick way to view all my WordPress posts without logging into the admin dashboard. Sometimes you just...

Read moreDetails

Why Stable Websites Outperform Flashy Redesigns

Why Stable Websites Outperform Flashy Redesigns

Most websites do not fail in dramatic fashion. There is no explosion, no warning siren, no obvious moment where everything...

Read moreDetails

Monitoring Web Page Changes with Python

Monitoring Web Page Changes with Python

There are times when I need to know that a web page has changed without actively watching it. That might...

Read moreDetails

My SSH Setup: How I Manage Multiple Servers

My SSH Setup: How I Manage Multiple Servers

If you work with more than one server, the need to manage multiple servers with SSH becomes obvious pretty quickly....

Read moreDetails
  • Privacy Policy
  • Terms of Service

© 2025 JMooreWV. All rights reserved.

No Result
View All Result
  • Home
  • Guides
    • Linux
    • Programming
      • JavaScript
      • PHP
      • Python
    • Tools
    • WordPress
  • Blog
    • Artificial Intelligence
    • Tutorials
    • Privacy
    • Security
  • Apps
    • Bible App
    • Bible Verse Screensaver
    • Blue AI Chatbot
    • Early Spring Predictor
    • FIGlet Generator
    • Password Generator
    • StegX
    • The Matrix
    • WeatherX
    • Website Risk Level Tool
  • About
    • About JMooreWV
    • Live Cyber Attacks
  • Contact
    • General Contact
    • Website Administration & Cybersecurity