WP如何创建自定义筛选页面

首先创建页面模板,添加样式

<?php
/**
 * Template Name: Post Filter Page
 * 
 * Create this file in your theme directory as filter-template.php
 */

get_header(); ?>

<div class="container">
    <div class="filter-page-wrapper">
        <h1 class="page-title"><?php the_title(); ?></h1>

        <!-- Filter Form -->
        <form id="post-filter-form" class="filter-form">
            <div class="filter-row">
                <!-- Price Range Filter -->
                <div class="filter-group">
                    <label for="chengce">层次:</label>
                    <select name="chengci" id="chengci">
                        <option value="">所有层次</option>
                        <option value="中专">中专</option>
                        <option value="中职">中职</option>
                        <option value="技校">技校</option>
                        
                    </select>
                </div>

                <div class="filter-group">
                    <label for="fanwei">范围:</label>
                    <select name="fanwei" id="fanwei">
                        <option value="">所有范围</option>
                        <option value="全国">全国初中、高中、中职应届生</option>
                        <option value="广东">广东初中、高中、中职应届生</option>
                        
                    </select>
                </div>

                <div class="filter-group">
                    <label for="lishu">级别:</label>
                    <select name="jibie" id="jibie">
                        <option value="">所有级别</option>
                        <option value="国家示范">国家示范</option>
                        <option value="省重点">省重点</option>
                        
                    </select>
                </div>

                <div class="filter-group">
                    <label for="lishu">隶属:</label>
                    <select name="lishu" id="lishu">
                        <option value="">全部</option>
                        <option value="广州市教育局">广州市教育局</option>
                        <option value="广东省教育厅">广东省教育厅</option>
                        
                    </select>
                </div>

                <div class="filter-group">
                    <label for="xiaozhi">校址:</label>
                    <select name="xiaozhi" id="xiaozhi">
                        <option value="">全部</option>
                        <option value="增城区">增城区</option>
                        <option value="天河区">天河区</option>
                        <option value="琶洲区">琶洲区</option>
                        
                    </select>
                </div>

                <div class="filter-group">
                    <label for="xingzhi">性质:</label>
                    <select name="xingzhi" id="xingzhi">
                        <option value="">全部</option>
                        <option value="公办">公办</option>
                        <option value="民办">民办</option>
                        
                    </select>
                </div>

                
            </div>
            <div class="filter-row">
                <!-- Category Filter -->
                <div class="filter-group">
                    <label for="category">Category:</label>
                    <select name="category" id="category">
                        <option value="">All Categories</option>
                        <?php
                        $categories = get_categories();
                        foreach($categories as $category) {
                            echo '<option value="' . esc_attr($category->term_id) . '">' . 
                                 esc_html($category->name) . '</option>';
                        }
                        ?>
                    </select>
                </div>

               
            </div>

            <!-- Sort Filter -->
            <div class="filter-row">
                <div class="filter-group">
                    <label for="sort">Sort By:</label>
                    <select name="sort" id="sort">
                        <option value="date-desc">Newest First</option>
                        <option value="date-asc">Oldest First</option>
                        <!-- <option value="price-asc">Price: Low to High</option>
                        <option value="price-desc">Price: High to Low</option> -->
                    </select>
                </div>
            </div>

            <?php 

            wp_nonce_field('post_filter_nonce', 'filter_nonce'); ?>
            
            <div class="filter-buttons">
                <button type="submit" class="filter-submit">Apply Filters</button>
                <button type="reset" id="reset-filters" class="filter-reset">Reset Filters</button>
            </div>
        </form>

        <!-- Results Container -->
        <div id="filter-results">
            <!-- Results will be loaded here via AJAX -->
            <div class="loading-spinner" style="display: none;">
                <div class="spinner"></div>
            </div>
        </div>

        <!-- Pagination Container -->
        <div id="filter-pagination" class="pagination-wrapper"></div>
    </div>
</div>

<?php get_footer(); ?>

执行后端程序

<?php  

// Enqueue necessary scripts and styles
function custom_filter_enqueue_scripts() {
    // Enqueue styles
    wp_enqueue_style('filter-styles', get_template_directory_uri() . '/assets/css/filter-styles.css');
    wp_enqueue_style( 'theme-style', get_template_directory_uri() . '/css/index.css' );
    wp_enqueue_style( 'admin-style', get_template_directory_uri() . '/css/yzipi-admin.css' );
    wp_enqueue_style( 'pc-style', get_template_directory_uri() . '/css/yzipi-pc.css' );
    wp_enqueue_style( 'mobile-style', get_template_directory_uri() . '/css/yzipi-phone.css' );
    wp_enqueue_style( 'index-mobile-style', get_template_directory_uri() . '/index/index-phone.css' );
    wp_enqueue_style( 'index-pc-style', get_template_directory_uri() . '/index/index-pc.css' );
    
    // Enqueue scripts
    wp_enqueue_script('jquery');
    wp_enqueue_script(
        'filter-script', 
        get_template_directory_uri() . '/assets/js/filter-script.js', 
        array('jquery'), 
        '1.0', 
        true
    );

    // Pass AJAX URL to script
    wp_localize_script('filter-script', 'filterAjax', array(
        'ajaxurl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('filter_posts_nonce')
    ));
}
add_action('wp_enqueue_scripts', 'custom_filter_enqueue_scripts');

// AJAX handler for filtering posts
function handle_post_filter() {
    // Verify nonce
    check_ajax_referer('post_filter_nonce', 'filter_nonce');

    // Initialize query arguments
    $args = array(
        'post_type' => 'post',
        'posts_per_page' => 10,
        'paged' => isset($_POST['page']) ? absint($_POST['page']) : 1,
        'meta_query' => array('relation' => 'AND'),
        'tax_query' => array()
    );

    // Handle price range
    // if (!empty($_POST['price_range'])) {
    //     $price_range = explode('-', $_POST['price_range']);
    //     if (count($price_range) == 2) {
    //         $args['meta_query'][] = array(
    //             'key' => 'price',
    //             'value' => array($price_range[0], $price_range[1]),
    //             'type' => 'NUMERIC',
    //             'compare' => 'BETWEEN'
    //         );
    //     } elseif (strpos($_POST['price_range'], '+') !== false) {
    //         $min_price = intval($price_range[0]);
    //         $args['meta_query'][] = array(
    //             'key' => 'price',
    //             'value' => $min_price,
    //             'type' => 'NUMERIC',
    //             'compare' => '>='
    //         );
    //     }
    // }

    // Handle location   input 输入 
    // if (!empty($_POST['cengci'])) {
    //     $args['meta_query'][] = array(
    //         'key' => 'cengci',
    //         'value' => sanitize_text_field($_POST['cengci']),
    //         'compare' => 'LIKE'
    //     );
    // }

    // cengci
    if (!empty($_POST['chengci'])) {
        $args['meta_query'][] = array(
            'key' => 'chengci',
            'value' => sanitize_text_field($_POST['chengci']),
            'compare' => '='
        );
    }

     if (!empty($_POST['fanwei'])) {
        $args['meta_query'][] = array(
            'key' => 'fanwei',
            'value' => sanitize_text_field($_POST['fanwei']),
            'compare' => '='
        );
    }

    // jibie
    if (!empty($_POST['jibie'])) {
        $args['meta_query'][] = array(
            'key' => 'jibie',
            'value' => sanitize_text_field($_POST['jibie']),
            'compare' => '='
        );
    }

    // lishu
    if (!empty($_POST['lishu'])) {
        $args['meta_query'][] = array(
            'key' => 'lishu',
            'value' => sanitize_text_field($_POST['lishu']),
            'compare' => '='
        );
    }

    // xingzhi
    if (!empty($_POST['xingzhi'])) {
        $args['meta_query'][] = array(
            'key' => 'xingzhi',
            'value' => sanitize_text_field($_POST['xingzhi']),
            'compare' => '='
        );
    }

    //xiaozhi
    if (!empty($_POST['xiaozhi'])) {
        $args['meta_query'][] = array(
            'key' => 'xiaozhi',
            'value' => sanitize_text_field($_POST['xiaozhi']),
            'compare' => '='
        );
    }

    // Handle category
    if (!empty($_POST['category'])) {
        $args['tax_query'][] = array(
            'taxonomy' => 'category',
            'field' => 'term_id',
            'terms' => absint($_POST['category'])
        );
    }

    // Handle date range
    // if (!empty($_POST['date_from']) || !empty($_POST['date_to'])) {
    //     $date_query = array();
        
    //     if (!empty($_POST['date_from'])) {
    //         $date_query['after'] = sanitize_text_field($_POST['date_from']);
    //     }
        
    //     if (!empty($_POST['date_to'])) {
    //         $date_query['before'] = sanitize_text_field($_POST['date_to']);
    //     }
        
    //     $args['date_query'] = array($date_query);
    // }

    // Handle sorting
    // if (!empty($_POST['sort'])) {
    //     switch ($_POST['sort']) {
    //         case 'date-asc':
    //             $args['orderby'] = 'date';
    //             $args['order'] = 'ASC';
    //             break;
    //         case 'date-desc':
    //             $args['orderby'] = 'date';
    //             $args['order'] = 'DESC';
    //             break;
    //         case 'price-asc':
    //             $args['meta_key'] = 'price';
    //             $args['orderby'] = 'meta_value_num';
    //             $args['order'] = 'ASC';
    //             break;
    //         case 'price-desc':
    //             $args['meta_key'] = 'price';
    //             $args['orderby'] = 'meta_value_num';
    //             $args['order'] = 'DESC';
    //             break;
    //     }
    // }

    $query = new WP_Query($args);
    
    ob_start();
    
    if ($query->have_posts()) {
        echo '<div class="dabw"><div class="st"><div class="posts-grid fees">';
        while ($query->have_posts()) {
            $query->the_post();
            get_template_part('template-parts/content', 'school');
        }
        echo '</div></div></div>';

        // Generate pagination
        $total_pages = $query->max_num_pages;
        if ($total_pages > 1) {
            echo '<div class="pagination">';
            for ($i = 1; $i <= $total_pages; $i++) {
                $current_class = ($i == $_POST['page']) ? ' current' : '';
                echo sprintf(
                    '<a href="#" class="page-number%s" data-page="%d">%d</a>',
                    esc_attr($current_class),
                    $i,
                    $i
                );
            }
            echo '</div>';
        }
    } else {
        echo '<div class="no-results">';
        echo '<p>No posts found matching your criteria.</p>';
        echo '</div>';
    }

    $response = array(
        'html' => ob_get_clean(),
        'found_posts' => $query->found_posts,
        'max_pages' => $query->max_num_pages
    );

    wp_reset_postdata();
    wp_send_json($response);
}
add_action('wp_ajax_filter_posts', 'handle_post_filter');
add_action('wp_ajax_nopriv_filter_posts', 'handle_post_filter');

// Function to display individual filtered post
function get_filtered_post_template() {
    ?>
    <article id="post-<?php the_ID(); ?>" <?php post_class('filtered-post'); ?>>
        <?php if (has_post_thumbnail()) : ?>
            <div class="post-thumbnail">
                <?php the_post_thumbnail('medium'); ?>
            </div>
        <?php endif; ?>

        <div class="post-content">
            <header class="entry-header">
                <h2 class="entry-title">
                    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                </h2>
            </header>

            <div class="entry-meta">
                <?php
                $price = get_post_meta(get_the_ID(), 'price', true);
                $location = get_post_meta(get_the_ID(), 'location', true);
                $status = get_post_meta(get_the_ID(), 'status', true);

                if ($price) {
                    echo '<span class="price">$' . number_format(esc_html($price), 2) . '</span>';
                }
                if ($location) {
                    echo '<span class="location"><i class="fas fa-map-marker-alt"></i> ' . 
                         esc_html($location) . '</span>';
                }
                if ($status) {
                    echo '<span class="status">' . esc_html(ucfirst($status)) . '</span>';
                }
                ?>
            </div>

            <div class="entry-excerpt">
                <?php the_excerpt(); ?>
            </div>

            <div class="entry-footer">
                <a href="<?php the_permalink(); ?>" class="read-more">Read More</a>
            </div>
        </div>
    </article>
    <?php
}








JS

// Save this as filter-script.js in your theme's assets/js directory
jQuery(document).ready(function($) {
    const filterForm = $('#post-filter-form');
    const resultsContainer = $('#filter-results');
    const loadingSpinner = $('.loading-spinner');
    let currentRequest = null;

    // Handle form submission
    filterForm.on('submit', function(e) {
        e.preventDefault();
        loadPosts(1);
    });

    // Handle pagination clicks
    $(document).on('click', '.page-number', function(e) {
        e.preventDefault();
        loadPosts($(this).data('page'));
    });

    // Handle reset button
    $('#reset-filters').on('click', function(e) {
        e.preventDefault();
        filterForm[0].reset();
        loadPosts(1);
    });

    // Function to load posts via AJAX
    function loadPosts(page) {
        // Show loading spinner
        loadingSpinner.show();
        resultsContainer.addClass('loading');

        // Abort previous request if it exists
        if (currentRequest != null) {
            currentRequest.abort();
        }

        // Get form data and append page number
        const formData = new FormData(filterForm[0]);
        formData.append('action', 'filter_posts');
        formData.append('page', page);

        // Make AJAX request
        currentRequest = $.ajax({
            url: filterAjax.ajaxurl,
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function(response) {
                // Update results container
                resultsContainer.html(response.html);
                
                // Update URL with filters (optional) 这个实用
                //updateURL(formData);
                
                // Scroll to results smoothly 这个实用
                $('html, body').animate({
                    scrollTop: resultsContainer.offset().top - 100
                }, 500);
                
                // Update results count if needed
                if (response.found_posts > 0) {
                    $('#results-count').text(response.found_posts + ' results found');
                }
            },
            error: function(xhr, status, error) {
                resultsContainer.html('<p class="error-message">Error loading posts. Please try again.</p>');
                console.error('Ajax error:', error);
            },
            complete: function() {
                loadingSpinner.hide();
                resultsContainer.removeClass('loading');
                currentRequest = null;
            }
        });
    }

    // Function to update URL with filters (optional)
    function updateURL(formData) {
        const params = new URLSearchParams();
        for (const pair of formData.entries()) {
            if (pair[1]) { // Only add non-empty values
                params.append(pair[0], pair[1]);
            }
        }
        const newURL = `${window.location.pathname}?${params.toString()}`;
        window.history.pushState({}, '', newURL);
    }

    window.addEventListener('popstate', function() {
        const urlParams = new URLSearchParams(window.location.search);
        
        // Reset form to match URL parameters
        filterForm[0].reset();
        for (const [key, value] of urlParams) {
            const input = filterForm.find(`[name="${key}"]`);
            if (input.length) {
                input.val(value);
            }
        }
        
        // Load posts with current URL parameters
        loadPosts(urlParams.get('page') || 1);
    });

    // Debounce function for search inputs
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    // // Handle live search for location input
    // const locationInput = $('#location');
    // locationInput.on('input', debounce(function() {
    //     if (locationInput.val().length >= 2 || locationInput.val().length === 0) {
    //         loadPosts(1);
    //     }
    // }, 500));

    // // Handle date range validation
    // const dateFrom = $('#date_from');
    // const dateTo = $('#date_to');

    // dateFrom.on('change', function() {
    //     dateTo.attr('min', $(this).val());
    // });

    // dateTo.on('change', function() {
    //     dateFrom.attr('max', $(this).val());
    // });

    // Initial load with URL parameters if they exist
    const initialPage = new URLSearchParams(window.location.search).get('page') || 1;
    loadPosts(initialPage);
});
×
WP如何创建自定义筛选页面

WP如何创建自定义筛选页面

首先创建页面模板,添加样式 <?p...