Custom page for filtering posts, WordPress is going 404 for any year other than the current year in the URL (&year=)

huangapple go评论59阅读模式
英文:

Custom page for filtering posts, WordPress is going 404 for any year other than the current year in the URL (&year=)

问题

以下是您提供的代码的翻译:

我有一个名为`news/`的页面。它没有设置为博客页面,我也不想将其设置为博客页面。我只想要几个下拉菜单,配有一个筛选按钮,该按钮将显示符合下拉菜单条件的帖子,并进行分页,否则显示列表中的所有帖子。以下是代码:

// 获取页眉
get_header(); 

// 获取筛选条件
$category = $_GET['category'] ?? '';
$tag = $_GET['tag'] ?? '';
$year = isset($_GET['year']) ? intval($_GET['year']) : 0;

// 获取当前页数
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

// 查询参数
$args = array(
    'post_type'      => 'post',
    'orderby'        => 'date',
    'order'          => 'DESC',
    'posts_per_page' => 10,
    'paged'          => $paged,
    'category_name'  => $category,
    'tag'            => $tag,
);

// 如果指定了年份,添加日期查询参数
if ($year) {
    $args['date_query'] = array(
        'year' => $year,
    );
}

// 创建新的WordPress查询对象
$query = new WP_Query($args);
?>

<?php
// 获取类别、标签和年份的信息
$categories = get_categories(array(
    'orderby' => 'name',
    'order'   => 'ASC'
));

$tags = get_tags(array(
    'orderby' => 'name',
    'order'   => 'ASC'
));

$years = $wpdb->get_col("
    SELECT DISTINCT YEAR(post_date)
    FROM $wpdb->posts
    WHERE post_status = 'publish'
    ORDER BY post_date DESC
");

var_dump($years);
var_dump($year);

?>

<!-- 创建筛选表单 -->
<form action="<?php echo esc_url(get_permalink()); ?>" method="get">
    <label for="category">选择类别:</label>
    <select name="category" id="category">
        <option value="">所有文章</option>
        <?php foreach ($categories as $category) : ?>
            <option value="<?php echo esc_attr($category->slug); ?>" <?php selected(isset($_GET['category']) && $_GET['category'] === $category->slug); ?>>
                <?php echo esc_html($category->name); ?>
            </option>
        <?php endforeach; ?>
    </select>
    <label for="tag">选择标签:</label>
    <select name="tag" id="tag">
        <option value="">标签</option>
        <?php foreach ($tags as $tag) : ?>
            <option value="<?php echo esc_attr($tag->slug); ?>" <?php selected(isset($_GET['tag']) && $_GET['tag'] === $tag->slug); ?>>
                <?php echo esc_html($tag->name); ?>
            </option>
        <?php endforeach; ?>
    </select>
    <label for="year">选择年份:</label>
    <select name="year" id="year">
        <option value="">所有年份</option>
        <?php foreach ($years as $archive_year) : ?>
            <?php var_dump($years); ?>
            <option value="<?php echo esc_attr($archive_year); ?>" <?php selected(isset($_GET['year']) && $_GET['year'] === $archive_year); ?>>
                <?php echo esc_html($archive_year); ?>
            </option>
        <?php endforeach; ?>
    </select>

    <input type="submit" value="筛选">
</form>

<?php if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post(); ?>
    <!-- 显示帖子内容 -->
    <h2><?php the_title(); ?></h2>
    <div class="post-content">
        <?php the_content(); ?>
    </div>
<?php endwhile; ?>
    <!-- 添加分页链接 -->
    <?php
    global $wp_query;
    $total_pages = $wp_query->max_num_pages;
    if ($total_pages > 1) {
        $current_page = max(1, get_query_var('paged'));
        echo '<div class="pagination">';
        echo paginate_links(array(
            'base'      => get_pagenum_link(1) . '%_%',
            'format'    => 'page/%#%',
            'current'   => $current_page,
            'total'     => $total_pages,
            'prev_text' => '&laquo;',
            'next_text' => '&raquo;',
        ));
        echo '</div>';
    }
    ?>
<?php else : ?>
    <p>没有找到帖子</p>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

<?php
// 获取页脚
get_footer();

这段代码主要用于创建一个自定义的WordPress页面,允许用户根据类别、标签和年份筛选帖子,并分页显示结果。如果您有任何其他问题,请随时提出。

英文:

I have a page I am calling news/. It is not set as the blog page and nor do I want it to be the blog page. I just want several dropdowns with a filter button that will display posts with a pagination that match the dropdown criteria, otherwise display all posts in the list. Here is the code:

get_header(); 
$category = $_GET[&#39;category&#39;] ?? &#39;&#39;;
$tag = $_GET[&#39;tag&#39;] ?? &#39;&#39;;
$year = isset($_GET[&#39;year&#39;]) ? intval($_GET[&#39;year&#39;]) : 0;
$paged = (get_query_var(&#39;paged&#39;)) ? get_query_var(&#39;paged&#39;) : 1;
$args = array(
&#39;post_type&#39;      =&gt; &#39;post&#39;,
&#39;orderby&#39;        =&gt; &#39;date&#39;,
&#39;order&#39;          =&gt; &#39;DESC&#39;,
&#39;posts_per_page&#39; =&gt; 10,
&#39;paged&#39;          =&gt; $paged,
&#39;category_name&#39;  =&gt; $category,
&#39;tag&#39;            =&gt; $tag,
);
if ($year) {
$args[&#39;date_query&#39;] = array(
&#39;year&#39; =&gt; $year,
);
}
$query = new WP_Query($args);
?&gt;
&lt;?php
$categories = get_categories(array(
&#39;orderby&#39; =&gt; &#39;name&#39;,
&#39;order&#39;   =&gt; &#39;ASC&#39;
));
$tags = get_tags(array(
&#39;orderby&#39; =&gt; &#39;name&#39;,
&#39;order&#39;   =&gt; &#39;ASC&#39;
));
$years = $wpdb-&gt;get_col(&quot;
SELECT DISTINCT YEAR(post_date)
FROM $wpdb-&gt;posts
WHERE post_status = &#39;publish&#39;
ORDER BY post_date DESC
&quot;);
var_dump($years);
var_dump($year);
?&gt;
&lt;form action=&quot;&lt;?php echo esc_url(get_permalink()); ?&gt;&quot; method=&quot;get&quot;&gt;
&lt;label for=&quot;category&quot;&gt;Select a category:&lt;/label&gt;
&lt;select name=&quot;category&quot; id=&quot;category&quot;&gt;
&lt;option value=&quot;&quot;&gt;All Articles&lt;/option&gt;
&lt;?php foreach ($categories as $category) : ?&gt;
&lt;option value=&quot;&lt;?php echo esc_attr($category-&gt;slug); ?&gt;&quot; &lt;?php selected(isset($_GET[&#39;category&#39;]) &amp;&amp; $_GET[&#39;category&#39;] === $category-&gt;slug); ?&gt;&gt;
&lt;?php echo esc_html($category-&gt;name); ?&gt;
&lt;/option&gt;
&lt;?php endforeach; ?&gt;
&lt;/select&gt;
&lt;label for=&quot;tag&quot;&gt;Select a tag:&lt;/label&gt;
&lt;select name=&quot;tag&quot; id=&quot;tag&quot;&gt;
&lt;option value=&quot;&quot;&gt;Tags&lt;/option&gt;
&lt;?php foreach ($tags as $tag) : ?&gt;
&lt;option value=&quot;&lt;?php echo esc_attr($tag-&gt;slug); ?&gt;&quot; &lt;?php selected(isset($_GET[&#39;tag&#39;]) &amp;&amp; $_GET[&#39;tag&#39;] === $tag-&gt;slug); ?&gt;&gt;
&lt;?php echo esc_html($tag-&gt;name); ?&gt;
&lt;/option&gt;
&lt;?php endforeach; ?&gt;
&lt;/select&gt;
&lt;label for=&quot;year&quot;&gt;Select a year:&lt;/label&gt;
&lt;select name=&quot;year&quot; id=&quot;year&quot;&gt;
&lt;option value=&quot;&quot;&gt;All Years&lt;/option&gt;
&lt;?php foreach ($years as $archive_year) : ?&gt;
&lt;?php var_dump($years); ?&gt;
&lt;option value=&quot;&lt;?php echo esc_attr($archive_year); ?&gt;&quot; &lt;?php selected(isset($_GET[&#39;year&#39;]) &amp;&amp; $_GET[&#39;year&#39;] === $archive_year); ?&gt;&gt;
&lt;?php echo esc_html($archive_year); ?&gt;
&lt;/option&gt;
&lt;?php endforeach; ?&gt;
&lt;/select&gt;
&lt;input type=&quot;submit&quot; value=&quot;Filter&quot;&gt;
&lt;/form&gt;
&lt;?php if ($query-&gt;have_posts()) : while ($query-&gt;have_posts()) : $query-&gt;the_post(); ?&gt;
&lt;!-- Display your post content here --&gt;
&lt;h2&gt;&lt;?php the_title(); ?&gt;&lt;/h2&gt;
&lt;div class=&quot;post-content&quot;&gt;
&lt;?php the_content(); ?&gt;
&lt;/div&gt;
&lt;?php endwhile; ?&gt;
&lt;!-- Add pagination links --&gt;
&lt;?php
global $wp_query;
$total_pages = $wp_query-&gt;max_num_pages;
if ($total_pages &gt; 1) {
$current_page = max(1, get_query_var(&#39;paged&#39;));
echo &#39;&lt;div class=&quot;pagination&quot;&gt;&#39;;
echo paginate_links(array(
&#39;base&#39;      =&gt; get_pagenum_link(1) . &#39;%_%&#39;,
&#39;format&#39;    =&gt; &#39;page/%#%&#39;,
&#39;current&#39;   =&gt; $current_page,
&#39;total&#39;     =&gt; $total_pages,
&#39;prev_text&#39; =&gt; &#39;&amp;laquo;&#39;,
&#39;next_text&#39; =&gt; &#39;&amp;raquo;&#39;,
));
echo &#39;&lt;/div&gt;&#39;;
}
?&gt;
&lt;?php else : ?&gt;
&lt;p&gt;No posts found&lt;/p&gt;
&lt;?php endif; ?&gt;
&lt;?php wp_reset_postdata(); ?&gt;
&lt;?php
get_footer();

The issue is that for any url, it is working fine as long as the URL is:
https://site/news/?category=&amp;year=2023
Or
https://site/news/?category=&amp;year=
or any URL without the year parameter
The moment you put in:
https://site/news/?category=&amp;year=2022 or any other year, 2022, 2021, 2020 it goes to a 404 page.

If I put a year in via hard code in the above code, but don't have 2022, 2021, 2020 in the url, it will filter fine.

I am assuming this is an issue with the Settings > Permalinks in my WordPress, but I am not understanding how to set it up. Currently it looks like this:

Custom Structure: /%category%/%postname%/

I noticed if I just selected the first option, other years would redirect to the traditional wordpress search and not my custom news/ filter page. I do not want this. I don't care about the traditional WordPress search posts page/functions. I just want all years to filter in place on my custom news page along with the other criteria.

答案1

得分: 1

某些查询字符串参数,包括year,被WordPress视为“保留”,使用它们可能会引发未定义的行为,包括可能出现404页面。不幸的是,我能找到唯一记录这一情况的位置是在register_taxonomy页面上,这并不明显,因为这个问题是系统范围的,与分类名称无关。

特别重要的是要避免以下保留术语,如果您通过$_GET或$_POST数组传递术语,这样做可能会导致WordPress以404错误响应,而没有其他提示或解释。

解决这个问题的快速简便方法是选择一个不同的年份参数,例如y。更长而复杂的解决方案可能是钩入template_include,但我认为那可能太晚了,查询已经被设置好了,所以您可能需要使用一个专门的重写规则

如果将来有其他人遇到这个问题,如果您需要年份、月份和日期,并决定使用ymd以保持一致性,不幸的是,m也是保留的,但month则不是。

英文:

Certain query string parameters, including year, are considered "reserved" by WordPress, and using them might kick in undefined behavior, including possibly a 404 page. Unfortunately, the only location that I can find that documents this is on the register_taxonomy page, which is very much not obvious because the problem is system-wide, and not just related to taxonomy names.

> Avoiding the following reserved terms is particularly important if you are passing the term through the $_GET or $_POST array. Doing so can cause WordPress to respond with a 404 error without any other hint or explanation.

The fast and easy solution to this is to just pick a different parameter for the year, such as y. The longer and more complicated solution is to possibly hook into template_include, however I think that's too late and the query will already be setup, so instead you might have to have a dedicated rewrite rule instead.

If anyone else stumbles on this some day and you have a need for year, month and day, so you decide to use y, m and d for consistency, unfortunately m is also reserved, however month isn't.

huangapple
  • 本文由 发表于 2023年5月18日 03:27:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76275592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定