12

フッター用の「今月の製品」ブロックを作成しています。カテゴリの商品を読み込み、最初の商品を表示する必要があります。

これは私のテンプレートファイルですcustom/featured-product.phtml

<?php $_productCollection = $this->getLoadedProductCollection() ?>

<div class="featured-product">
    <h2><?php echo $this->__('Product of the Month') ?></h2>

    <?php foreach ($_productCollection as $_product): ?>
        <div class="item">
            <a class="product-image" href="<?php echo $_product->getProductUrl() ?>">
                <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(200); ?>" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
            </a>

            <a class="product-name" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a>

            <?php echo $this->getPriceHtml($_product, true) ?>
        </div>

        <?php
        // Note: Exit after first product.
        break;
        ?>
    <?php endforeach ?>
</div>

これは、Magentoの製品リストテンプレートの単純化されたバージョンです。catalog/product/list.phtml


働く

ブロックをCMSページに埋め込む場合、正常に機能します。例:

{{block type="catalog/product_list" category_id="13" template="custom/featured-product.phtml" }}


動作していません

を介してブロックを埋め込むと、local.xml失敗します。正しいマークアップが返されますが、指定されたカテゴリはロードされません。代わりに、ランダムな(選択方法はわかりませんが)製品のセットがロードされます。

私のコードlocal.xml

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" category_id="13" template="custom/featured-product.phtml" />
    </reference>
</default>

page/html/footer.phtml完全を期すために、次のようにブロックを明示的にレンダリングしています。

<?php echo $this->getChildHtml('product_of_the_month') ?>


何か案は?

私の最善の推測は私のlocal.xml間違いです。ロードする必要のある親ブロックはありますか?


【アップデート】

元のコードで製品ページがクラッシュします。回避策は、コードをMagentoコアファイルにそれほど大きく基づいていないcatalog/product/list.phtmlことです。特にこの行を避ける:

<?php $_productCollection = $this->getLoadedProductCollection() ?>


[解決]

CMSページとLayoutXMLで使用するための例を含む作業バージョンはここに含まれています: https ://stackoverflow.com/a/12288000/1497746

4

3 に答える 3

12

AlanStormのアドバイスを使用して実用的な解決策を見つけました。

/template/custom/featured-product.phtml

<?php
$_categoryId = $this->getCategoryId();

$_productCollection = Mage::getModel('catalog/category')->load($_categoryId)
    ->getProductCollection()
    ->addAttributeToSelect('*')
    ->addAttributeToFilter('status', 1)
    ->addAttributeToFilter('visibility', 4)
    ->setOrder('price', 'ASC');
?>

<div class="featured-product">
    <h2><?php echo $this->__( $this->getLabel() ); ?></h2>

    <?php foreach ($_productCollection as $_product): ?>
        <div class="item">
            <a class="product-image" href="<?php echo $_product->getProductUrl() ?>">
                <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(200); ?>" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
            </a>

            <a class="product-name" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a>

            <?php echo $this->getPriceHtml($_product, true) ?>
        </div>

        <?php
        // Note: Exit after first product.
        break;
        ?>
    <?php endforeach ?>
</div>

つまり、コレクションは(私の最初の試みのように)コレクションを受け取るのではなく、手動で生成されます。

<?php $_productCollection = $this->getLoadedProductCollection() ?>
<?php $_collectionSize = $_productCollection->count(); ?>


CMSページでの使用:

{{block type="core/template" category_id="13" label="Product of the Month" template="custom/featured-product.phtml" }}


テンプレートでの使用:

/layout/local.xml

<default>
    <reference name="footer">
        <block type="core/template" name="custom.featuredProduct" as="featured_product" template="custom/featured-product.phtml">
            <action method="setData"><key>category_id</key><value>13</value></action>
            <action method="setData"><key>label</key><value>Product of the Month</value></action>
        </block>
    </reference>
</default>

/template/page/html/footer.phtml

<?php echo $this->getChildHtml('featured_product') ?>


役立つリソース:

商品コレクションの入手方法:

マジックゲッター/セッターの使用:

于 2012-09-05T18:58:06.627 に答える
5

まず、レイアウト更新xml属性ノードを使用してブロックに値を設定することで、何年にもわたってランダムな問題が発生しました(、、、、、、またはtemplate、以外)asnametypeclass

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" template="custom/featured-product.phtml">
            <action method="setCategoryId"><id>13</id></action>
        </block>
    </reference>
</default>

またはこれ

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" template="custom/featured-product.phtml">
            <action method="setData"><key>category_id</key><value>13</value></action>
        </block>
    </reference>
</default>

助けになるかもしれません、そして私の最初のステップになるでしょう。

その後、コレクションをロードしているブロックコードを確認します

#File: app/code/core/Mage/Catalog/Block/Product/List.php
class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract
{
    ...
    public function getLoadedProductCollection()
    {
        return $this->_getProductCollection();
    }        
    ...
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $layer = $this->getLayer();
            /* @var $layer Mage_Catalog_Model_Layer */
            if ($this->getShowRootCategory()) {
                $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
            }

            // if this is a product view page
            if (Mage::registry('product')) {
                // get collection of categories this product is associated with
                $categories = Mage::registry('product')->getCategoryCollection()
                    ->setPage(1, 1)
                    ->load();
                // if the product is associated with any category
                if ($categories->count()) {
                    // show products from this category
                    $this->setCategoryId(current($categories->getIterator()));
                }
            }

            $origCategory = null;
            if ($this->getCategoryId()) {
                $category = Mage::getModel('catalog/category')->load($this->getCategoryId());
                if ($category->getId()) {
                    $origCategory = $layer->getCurrentCategory();
                    $layer->setCurrentCategory($category);
                }
            }
            $this->_productCollection = $layer->getProductCollection();

            $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

            if ($origCategory) {
                $layer->setCurrentCategory($origCategory);
            }
        }

        return $this->_productCollection;
    }                
}

このメソッドは、getLoadedProductCollectionへの呼び出しをラップし、コレクションが実際にロードされる場所です。_getProductCollection_getProductCollection

したがって、いくつかの一時的なデバッグコードは

protected function _getProductCollection()
{
    var_dump(__METHOD__);
    var_dump($this->getCategoryId());
    Mage::Log(__METHOD__);
    Mage::Log($this->getCategoryId());
}

カテゴリIDがレイアウト更新XMLからブロックに確実に反映されるようにするのに役立ちます。

ただし、をもう少し詳しく見てみると、カテゴリIDがリセットさ_getProductCollectionれる条件がいくつかあることがわかります。

if ($this->getShowRootCategory()) {
    $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
}
...
if (Mage::registry('product')) {
    // get collection of categories this product is associated with
    $categories = Mage::registry('product')->getCategoryCollection()
        ->setPage(1, 1)
        ->load();
    // if the product is associated with any category
    if ($categories->count()) {
        // show products from this category
        $this->setCategoryId(current($categories->getIterator()));
    }
}
...

他のMagentoコードでshow_root_categoryプロパティが設定されている場合、またはレジストリに製品オブジェクトがあるページを表示している場合、MagentoはカテゴリIDを上書きします。

さらに複雑なことに、コレクションが読み込まれると、保護されたプロパティに設定されます

$this->_productCollection = $layer->getProductCollection();

パブリックゲッターメソッドはありません。

ここで進む方法は無数にあります。それが私だったら、私は次のいずれかを検討します

  1. Mage_Catalog_Block_Product_Listコレクションのカテゴリをリセットしたり、新しいコレクションをロードしたりするためのメソッドを拡張し、持つカスタムブロッククラスを使用する

  2. のコードに依存せずに、自分でコレクションをロードするproduct/list

于 2012-09-05T16:35:23.523 に答える
1

MagentoCE1.7.0.2で問題を正常に再現しました。

まず、次のコンテンツを使用してlocal.xmlを作成しました。

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" category_id="13" template="custom/featured-product.phtml" />
    </reference>
</default>

私は、いくつかのラッピングXML要素が欠落していることを理解し、いくつかの余分な行を追加しました。

<?xml version="1.0"?>
<layout>
    <default>
        <reference name="footer">
            <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" category_id="13" template="custom/featured-product.phtml" />
        </reference>
    </default>
</layout>

必要なXML要素を追加した後、それは機能しました。

于 2012-09-05T16:45:50.470 に答える