在模板中获取产品的完整图片网址


23

我正在尝试创建一个静态块来显示动态产品。这是应该获取每个子类别并为每个类别中的每个产品打印图像的代码。

<?php
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $category = $objectManager->get('Magento\Framework\Registry')->registry('current_category');
    ?><ol><?php
    foreach ($category->getChildrenCategories() as $child_category) {
        ?><li>
            <ul><?php
                foreach ($child_category->getProductCollection() as $product) {
                    ?><li><img src="<?php echo $product->getImage();?>"/><li><?php
                }
            ?></ul>
        </li><?php
    }
    ?></ol>

除了img srcs仅以“ /a/b/ab001.jpg”为例而不是完整路径外,它几乎可以正常工作,例如“ / pub / media / catalog / product / cache / 1 / small_image / 240x300 / abc123def456 / a / b / 001.jpg”,因此找不到图像。获取产品图片的正确方法是什么?


1
不要尝试直接在模板上使用对象管理器。我们应该创建新的块或重复使用现有的功能。
Khoa TruongDinh

Answers:


28

如果您的代码块扩展了Magento\Catalog\Block\Product\AbstractProduct,您可以使用:

$imageType = 'category_page_list'; // choose which image
$image = $block->getImage($product, $imageType);

然后使用

$image->getImageUrl();

或者如果您想将其输出为<img>元素:

echo $image->toHtml();

如果您的模块没有/不能扩展抽象产品模块,则可以getImage()自己创建一个方法:

public function getImage($product, $imageId)
{
    return $this->imageBuilder->setProduct($product)
        ->setImageId($imageId)
        ->create();
}

$this->imageBuilder 必须注入为 Magento\Catalog\Block\Product\ImageBuilder


$imageType$imageId变量应在主题定义的图像类型中的一种,例如category_page_list

app/design/frontend/Magento/luma/etc/view.xml例如,有关Luma主题的所有图像类型,请参见。

在Magento 2中,使用了这些图像类型,而不是直接在模板中定义宽度和高度。


我想你的代码,但我得到这个错误Uncaught Magento\Framework\View\Asset\File\NotFoundException: Unable to resolve the source file for 'adminhtml/_view/en_US/Magento_Catalog/images/product/placeholder/.jpg'
ND17

@ ND17两个问题:1)您是否在管理区域中使用该块?此代码仅适用于前端2)您是否配置了占位符图像?如果没有,并且产品没有图像,您将总是会出错
Fabian Schmengler

1
@davideghz例如在主题中定义的图像类型之一category_page_list。参见:github.com/magento/magento2/blob/…在Magento 2中,您可以使用它们而不是直接在模板中定义宽度和高度
Fabian Schmengler

3
为什么会带回占位符而不是分配的图像?
劳拉

2
我遇到的问题与@Laura相同。它总是返回占位符图像而不是分配的图像(分配的图像在产品列表或常规产品详细信息页面中完全可见)。
fritzmg

9

如果您需要调整产品图像的大小并使用默认的Magento图像缓存系统,并且您不在前端区域中,则可以使用此替代方法。

用例:如果需要在自定义API上为外部应用程序调整图像URL的大小,这可能会很有用。

功能码:

/**
 * @var \Magento\Catalog\Model\ProductFactory
 */
protected $productFactory;

/**
 * @var \Magento\Catalog\Helper\ImageFactory
 */
protected $helperFactory;

/**
 * @var \Magento\Store\Model\App\Emulation
 */
protected $appEmulation;

/**
 * Constructor.
 *
 * @param \Magento\Catalog\Model\ProductFactory $productFactory
 * @param \Magento\Store\Model\App\Emulation $appEmulation
 * @param \Magento\Catalog\Helper\ImageFactory $helperFactory
 * @param \Magento\Store\Model\StoreManagerInterface $storeManager
 */
public function __construct(
    \Magento\Catalog\Model\ProductFactory $productFactory,
    \Magento\Store\Model\App\Emulation $appEmulation,
    \Magento\Catalog\Helper\ImageFactory $helperFactory,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
) {
    $this->productFactory                   = $productFactory;
    $this->imageBuilder                     = $imageBuilder;
    $this->helperFactory                    = $helperFactory;
    $this->appEmulation                     = $appEmulation;
    $this->storeManager                     = $storeManager;
}

/**
 * Retrieve product image
 *
 * @param \Magento\Catalog\Model\Product $product
 * @param string $imageId
 * @param array $attributes
 * @return \Magento\Catalog\Block\Product\Image
 */
public function getImage($product, $imageId, $attributes = [])
{
    $image = $this->helperFactory->create()->init($product, $imageId)
        ->constrainOnly(true)
        ->keepAspectRatio(true)
        ->keepTransparency(true)
        ->keepFrame(false)
        ->resize(200, 300);

    return $image;
}

public function customFunction()
{
    // some stuff here

    $storeId = $this->storeManager->getStore()->getId();

    $this->appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true);

    $product = $this->productFactory->create()->loadByAttribute('sku', 'productSKU');
    $imageUrl = $this->getImage($product, 'product_base_image')->getUrl();

    echo $imageUrl;

    $this->appEmulation->stopEnvironmentEmulation();

    // some stuff here
}

输出示例:

http://{domain}/media/catalog/product/cache/1/image/200x300/e9c3970ab036de70892d86c6d221abfe/s/r/{imageName}.jpg

评论 :

如果您已经在同一storeId上,则函数startEnvironmentEmulation的第三个参数用于强制使用前端区域。(对API区域有用)

此解决方法可以避免出现此类错误:

http://XXXX.com/pub/static/webapi_rest/_view/en_US/Magento_Catalog/images/product/placeholder/.jpg

Uncaught Magento\Framework\View\Asset\File\NotFoundException: Unable to resolve the source file for 'adminhtml/_view/en_US/Magento_Catalog/images/product/placeh‌​older/.jpg'

1
感谢您提供有关环境仿真的技巧,这正是我所需要的。
thaddeusmt

2
环境仿真挽救了我的生活。非常感谢!
麦地那

+1的API实用性
Tony,

8

试试吧

$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
$imageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();

1
这个很好,因为它将根据当前请求自动提供安全/不安全的URL
Milan Simek'Nov

3

试试这个代码..

$ProductImageUrl = $block->getUrl('pub/media/catalog').'product'.$_product->getImage();

欢迎来到Magento SE。仅包含一行代码的答案通常不是很有帮助。在这种情况下,应该如何使用这条线还是比较清楚的,但是getUrl()即使可能偶然使用,使用也不是正确的方法。它采用$route“模块/控制器/动作”形式的参数。“ pub / media / catalog”看起来像一条路线,但不是。
Fabian Schmengler '16

不使用对象管理器,很好的答案。即使只有一行。
LM_Fielding '16

@LM_Fielding并非所有不使用对象管理器的答案都会自动得到良好回答。
Fabian Schmengler '16

尝试使用此代码并发表您的评论
Shihas Suliaman

1

也许Magento\Catalog\Helper\Product::getImageUrl()可以帮上忙。我不明白为什么Magento开发人员没有在Magento\Catalog\Helper\Image类中实现它,因为getUrl图像助手中的方法没有返回人们期望的结果...


1

请尝试以下代码:

$prdId = 35;
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$hotPrd = $objectManager->get('Magento\Catalog\Model\Product')->load($prdId);
$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
echo $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $hotPrd->getThumbnail();

1

您可以使用ObjectManager或Block。

对象管理器:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
$imageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();

区块:

protected $_storeManagerInterface;

public function __construct(
  ...
  \Magento\Store\Model\StoreManagerInterface $storeManagerInterface,
  ...
)
{
  ...
  $this->_storeManagerInterface = $storeManagerInterface;
  ...
}

...

public function getStoreInterface($imgUrl){
   $store = $this->_storeManagerInterface->getStore();
   $storeMedia = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $imgUrl;
   return $storeMedia;
}
...

调用函数:

<img src="<?php echo $block->getStoreInterface($imgUrl) ?>"/>


0

在您的模块中:

public function getProducts()
{
    //... create collection code goes here...

    $result = [ ];

    foreach ( $collection as $product ) {
        $result[] = [
            'id'        => $product->getId(),
            '_sku'      => $product->getSku(),
            'permalink' => $product->getProductUrl($product),
            'title'     => $product->getName(),
            'raw_price' => $product->getPrice(),
            'image_url' => $this->getUrl().'pub/media/catalog/product'.$product->getImage()
        ];
    }

    return $result;
}

然后,在您的代码块中,您将获得以下结果:

print_r($block->getProducts());

好吧,这并不完美,但对我有用。

看一下结果: 在此处输入图片说明


0

在您的类中注入依赖项StoreManagerInterface,例如:

use \Magento\Framework\View\Element\Template\Context;
use \Magento\Store\Model\StoreManagerInterface;

public function __construct(Context $context, StoreManagerInterfac $storeManager)
    {
        parent::__construct($context);
        $this->_storeManager = $storeManager;

    }

在您的方法之后,例如获取拇指钉

public function getProductThumbnail(){

        return $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();
    }

0

您可以尝试以下代码。

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$category = $objectManager->get('Magento\Framework\Registry')->registry('current_category');
$childcategories = $category->getChildrenCategories();

foreach($childcategories as $child)
    {
echo '<li class="sub-cat">';
        $cat = $objectManager->create('Magento\Catalog\Model\Category')->load($child->getId()); 
        ?>
        <a href="<?php echo $cat->getUrl(); ?>">
        <div class="sub-title">
            <h3><?php echo $cat->getName();?></h3>
        </div> 
    <?php
        if ($_imgUrl = $cat->getImageUrl())
        {
            $_imgHtml = '<div class="category-image"><img src="' . $_imgUrl . '" alt="' . $block->escapeHtml($cat->getName()) . '" title="' . $block->escapeHtml($cat->getName()) . '" class="image" /></div>';
            $_imgHtml = $_helper->categoryAttribute($cat, $_imgHtml, 'image');
            /* @escapeNotVerified */ echo $_imgHtml;
        }  

    ?>      
    <?php echo '</a></li>'; }
    echo '</ul>';
}

0

这是另一种工作方法:

/** @var \Magento\Framework\UrlInterface $urlManager */
$url = $urlManager->getDirectUrl('pub/media/catalog/product' . $product->getImage());

或根据当前请求尊重安全/不安全的URL:

/** @var \Magento\Framework\UrlInterface $urlManager */
/** @var \Magento\Framework\App\RequestInterface $request */
$url = $urlManager->getDirectUrl(
    'pub/media/catalog/product' . $product->getImage(),
    ['_secure' => $request->isSecure()]
);

我将对象实例化留给您自己的想象。


0

我们可以在phtml文件中获取基本图片网址

$_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$imageHelper  = $_objectManager->get('\Magento\Catalog\Helper\Image');
<?php $image_url = $imageHelper->init($product, 'product_base_image')->setImageFile($product->getFile())->resize($imagewidth, $imageheight)->getUrl(); ?>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.