You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Magento 2集成Fishpig后,如何按分类展示单篇最新博客文章?

Solution: Display Latest Post per Category (Excluding Uncategorized) in FishPig WordPress for Magento 2

Got it, let's tackle this problem step by step. The core issue here is that your current setup pulls multiple posts from a single category, but we need to loop through each valid category and fetch just its most recent published post. Here's how to implement this properly, following Magento 2's MVC best practices (avoiding direct core file edits as much as possible):

First, we'll build a custom block to handle the data logic (keeping template files clean, which is Magento's preferred pattern).

Step 1: Create the Block Class

In your custom module (replace Vendor\Module with your actual module namespace), create this file:
app/code/Vendor/Module/Block/Blog/CategoryLatestPosts.php

<?php
namespace Vendor\Module\Block\Blog;

use FishPig\WordPress\Block\AbstractBlock;
use FishPig\WordPress\Model\ResourceModel\Post\CollectionFactory as PostCollectionFactory;
use FishPig\WordPress\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;

class CategoryLatestPosts extends AbstractBlock
{
    protected $postCollectionFactory;
    protected $categoryCollectionFactory;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        PostCollectionFactory $postCollectionFactory,
        CategoryCollectionFactory $categoryCollectionFactory,
        array $data = []
    ) {
        $this->postCollectionFactory = $postCollectionFactory;
        $this->categoryCollectionFactory = $categoryCollectionFactory;
        parent::__construct($context, $data);
    }

    public function getCategoriesWithLatestPost()
    {
        // Fetch all categories, exclude Uncategorized and empty categories
        $categoryCollection = $this->categoryCollectionFactory->create();
        $categoryCollection->addFieldToFilter('slug', ['neq' => 'uncategorized'])
                          ->addFieldToFilter('count', ['gt' => 0]); // Only show categories with posts

        $categoriesWithPosts = [];

        foreach ($categoryCollection as $category) {
            // Get the latest published post for this category
            $postCollection = $this->postCollectionFactory->create();
            $postCollection->addIsPublishedFilter()
                          ->addCategoryFilter($category)
                          ->setOrder('post_date', 'DESC')
                          ->setPageSize(1);

            if ($post = $postCollection->getFirstItem()) {
                $categoriesWithPosts[] = [
                    'category' => $category,
                    'latest_post' => $post
                ];
            }
        }

        return $categoriesWithPosts;
    }
}

Step 2: Create the Template File

Next, create the template to render the data:
app/code/Vendor/Module/view/frontend/templates/blog/category-latest-posts.phtml

<?php $categoriesWithPosts = $block->getCategoriesWithLatestPost(); ?>
<?php if (!empty($categoriesWithPosts)): ?>
    <div class="category-latest-posts grid-container">
        <?php foreach ($categoriesWithPosts as $item): ?>
            <?php $category = $item['category']; ?>
            <?php $post = $item['latest_post']; ?>
            <div class="category-post-item grid-item">
                <h3 class="category-title">
                    <a href="<?= $block->escapeUrl($category->getUrl()) ?>">
                        <?= $block->escapeHtml($category->getName()) ?>
                    </a>
                </h3>
                <div class="latest-post-card">
                    <?php if ($featuredImage = $post->getFeaturedImage()): ?>
                        <img 
                            src="<?= $block->escapeUrl($featuredImage->getAvailableImageUrl()) ?>" 
                            alt="<?= $block->escapeHtmlAttr($post->getPostTitle()) ?>"
                            class="post-featured-image"
                        >
                    <?php endif; ?>
                    <h4 class="post-title">
                        <a href="<?= $block->escapeUrl($post->getUrl()) ?>">
                            <?= $block->escapeHtml($post->getPostTitle()) ?>
                        </a>
                    </h4>
                    <p class="post-excerpt">
                        <?= $block->escapeHtml($post->getPostExcerpt()) ?>
                    </p>
                    <span class="post-date">
                        <?= $block->escapeHtml($post->getPostDate()) ?>
                    </span>
                </div>
            </div>
        <?php endforeach; ?>
    </div>
<?php endif; ?>

Step 3: Add the Block to Your Blog Layout

To display this on your blog homepage, update the FishPig blog layout file (or your custom layout override):
app/design/frontend/YourTheme/YourThemeChild/Magento_Theme/layout/fishpig_wordpress_blog_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\Blog\CategoryLatestPosts" 
                   name="category.latest.posts"
                   template="Vendor_Module::blog/category-latest-posts.phtml"
                   before="-"/>
        </referenceContainer>
    </body>
</page>

If you just want to test the logic without building a custom module, you can add this code directly to your existing FishPig/WordPress/view/frontend/templates/post/list.phtml (note: core file edits are not ideal for long-term maintenance):

<?php
// Fetch valid categories (exclude Uncategorized and empty ones)
$categoryCollection = $this->getLayout()->createObject(\FishPig\WordPress\Model\ResourceModel\Category\Collection::class);
$categoryCollection->addFieldToFilter('slug', ['neq' => 'uncategorized'])
                   ->addFieldToFilter('count', ['gt' => 0]);
?>

<div class="category-latest-posts">
    <?php foreach ($categoryCollection as $category): ?>
        <?php
        // Get latest post for this category
        $postCollection = $this->getLayout()->createObject(\FishPig\WordPress\Model\ResourceModel\Post\Collection::class);
        $postCollection->addIsPublishedFilter()
                       ->addCategoryFilter($category)
                       ->setOrder('post_date', 'DESC')
                       ->setPageSize(1);
        
        $post = $postCollection->getFirstItem();
        ?>

        <?php if ($post->getId()): ?>
            <div class="category-post">
                <h3><?= $block->escapeHtml($category->getName()) ?></h3>
                <a href="<?= $block->escapeUrl($post->getUrl()) ?>">
                    <?= $block->escapeHtml($post->getPostTitle()) ?>
                </a>
                <?php if ($post->getPostExcerpt()): ?>
                    <p><?= $block->escapeHtml($post->getPostExcerpt()) ?></p>
                <?php endif; ?>
                <span class="post-date"><?= $block->escapeHtml($post->getPostDate()) ?></span>
            </div>
        <?php endif; ?>
    <?php endforeach; ?>
</div>

Key Notes

  • Excluding Uncategorized: We use the category slug uncategorized instead of ID because the ID can vary (default is 1, but it's not guaranteed).
  • Empty Categories: The addFieldToFilter('count', ['gt' => 0]) line ensures we only show categories that have at least one published post.
  • Security: Always use escapeHtml(), escapeUrl(), and escapeHtmlAttr() to prevent XSS vulnerabilities in your templates.
  • Performance: If you have a lot of categories, consider adding caching to the block to improve load times.

内容的提问来源于stack exchange,提问作者Joey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:01:33