こんにちは!
今回はMagentoおよびAdobe Commerce(以下まとめてMagento)において商品画像がリサイズされて画面に表示される過程について解説してみたいと思います。
※本記事はAdobe Commerce 2.4.7で検証した内容について記載しています
Magentoでは、商品一覧や商品詳細、カート画面など、同じ商品画像であっても表示場所によって異なるサイズの画像が利用されています。
例えば、
- 商品一覧では 240×300など、中くらいのサイズ
- カート画面では 165×165など、小さいサイズ
- ウィジェットなどではその用途に応じたサイズ
といったように、用途に応じて最適なサイズの画像が表示されます。
各画面で表示されているimgタグのsrc属性を見てみると何やら複雑なパスになっていてこのパス名が一体どこからやってきたものなのかファイルはどのように管理されているのかが非常に気になります。
今回はMagentoの商品画像がどのように管理され、実際の画像URLがどのように生成されているのかをソースコードベースで整理してみます。
商品画像はリサイズ画像が利用される
Magentoではアップロードされた元画像をそのまま表示するのではなく、表示用途ごとにリサイズされた画像を利用します。
そのため、実際には次の2種類の画像ファイルが存在します。
- 元画像
- リサイズ済み画像(キャッシュ画像)
画像の保存場所
元画像
商品画像を登録すると元画像は以下の場所に保存されます。
<magento_root>/pub/media/catalog/product/<dir1>/<dir2>/<file_name>
<dir1> と <dir2> には、ファイル名の先頭1文字目・2文字目が使用されます。
例えば、
abc00123.jpg
というファイルの場合は、
pub/media/catalog/product/a/b/abc00123.jpg
に保存されます。
商品画像は大量に保存されるのでディレクトリを分散して効率的に管理するための仕組みです。
リサイズ画像
リサイズ画像はキャッシュとして保存されるので、~/product/cache 配下に保存されます。
実際に画面で利用される画像は多くの場合こちらのリサイズ済み画像です。
保存先は次のようになります。
<magento_root>/pub/media/catalog/product/cache/<hash>/<dir1>/<dir2>/<file_name>
元画像との最大の違いは <hash> が付与されている点です。例えば、
pub/media/catalog/product/cache/3ddc3660adb9e922098ea9039ded78da/a/b/abc00123.jpg
のようなパスになります。
ハッシュ値は何を表しているのか
このハッシュ値はただのランダムな文字列ではありません。
画像加工時のパラメータをMD5ハッシュ化した値です。
Magentoの Magento\Catalog\Model\View\Asset\Image クラス(ソースコード:vendor/magento/module-catalog/Model/View/Asset/Image.php)を読み解くと、以下のような情報を元にハッシュを生成しています。
h:<image_height>_w:<image_width>_<background>_r:<angle>_q:<quality>_<keep_aspect_ratio>_<keep_frame>_<keep_transparency>_<constrain_only>
ハッシュの元となるテキストを構成する内容は以下の通りです。
| パラメータ | 内容 | テキスト値の例 |
|---|---|---|
| image_height | 画像高さ(px) | empty, 165, 300など |
| image_width | 画像幅(px) | empty, 165, 240など |
| background | 余白部分の背景色 | nobackground / rgb255,255,255など |
| angle | 画像回転角度 | empty, 90, 180など |
| quality | 画像品質 | empty, 80, 90, 100など |
| keep_aspect_ratio | 縦横比を維持するか | proportional / nonproportional |
| keep_frame | 指定サイズに収めるため余白を付与 | frame / noframe |
| keep_transparency | 透過情報を維持するか | transparency / notransparency |
| constrain_only | 元画像サイズより大きくしない | doconstrainonly / notconstrainonly |
例えば、パラメータによって
h:300_w:240_rgb255,255,255_r:empty_q:80_proportional_frame_transparency_doconstrainonly
のような文字列が生成され、そのMD5ハッシュ値がキャッシュディレクトリ名として利用されます。
つまり、
- サイズが同じ
- 品質設定も同じ
- その他の加工条件も同じ
であれば、生成されるハッシュ値も同じになります。
そのためこのパスは同じ条件の場合にキャッシュが働くようにするための「画像加工条件を表現した恒久的なURL」と考えることができます。
【余談】 何故ハッシュ化されているのか
パラメータ文字列のままでも良さそうなものですが、何故ハッシュ化されているのでしょうか。
これはおそらく、ハッシュ化することでパス長を短く保ちながら同じ加工条件のものを常に同じキャッシュパスとして生成することで不要な画像生成を避けて効率的なキャッシュ運用をするためだと考えられます。
テンプレートではどうやってリサイズ画像を指定するか
先ほどリサイズ画像はパラメータをハッシュ化したURLパスで保存されると説明しました。
ではどうやってテンプレート内でそのURLを指定するのでしょうか。実はテンプレートでは、画像ファイルのパスを直接記述していません。
例えば標準テーマでは次のようなコードが利用されています。
(テンプレート例: vendor/magento/module-catalog-widget/view/frontend/templates/product/widget/content/grid.phtml )
~前略~
<div class="product-item-info">
<a href="<?= $escaper->escapeUrl($block->getProductUrl($_item)) ?>" class="product-item-photo">
<?= $block->getImage($_item, $image)->toHtml() ?>
</a>
ここで渡しているのは、
- 商品オブジェクト $_item、このブロック内で取得したもの
- 画像設定ID $image→"new_products_content_widget_grid"など
のみです。
実際の画像ファイル名(元画像ファイル)は商品データから取得され、リサイズ等のパラメータは別途定義済みの画像設定のIDを指定します。
画像設定について
画像サイズなどの設定はテーマの view.xml に定義されています。
(lumaテーマなら、vendor/magento/theme-frontend-luma/etc/view.xml)
<image id="new_products_content_widget_grid" type="small_image">
<width>240</width>
<height>300</height>
</image>
例えば上記設定の場合、
- width = 240
- height = 300
が画像生成時のパラメータとして利用されます。
商品一覧、詳細、カートなど必要な場面に応じて異なる画像サイズをそれぞれ定義しておくことでテンプレート側を変更せずとも反映されるようになっています。
view.xmlで指定できるパラメータは以下の通りです。
| view.xmlのキー | 内容 | 未指定時 | 対応パラメータ |
|---|---|---|---|
| height | 画像高さ(px) | null | image_height |
| width | 画像幅(px) | null | image_width |
| background | 余白部分の背景色 | [255,255,255] | background |
| angle | 画像回転角度 | null | angle |
| ※view.xml外 (システム設定) |
画像品質 | 80 | quality |
| aspect_ratio | 縦横比を維持するか(true/false) | true | keep_aspect_ratio |
| frame | 指定サイズに収めるため余白を付与(true/false) | 標準ではtrue (テーマ依存) |
keep_frame |
| transparency | 透過情報を維持するか(true/false) | true | keep_transparency |
| constrain | 元画像サイズより大きくしない(true/false) | true | constrain_only |
※view.xmlでは一部true/falseなどで指定します
実際の画像URLはどこで生成されるのか
テンプレート内で、$block->getImage(~)のように記述していますが、そのメソッドから生成される最終的なimgタグは Magento\Catalog\Block\Product\Image クラスによって生成されています。
このクラスが持つテンプレートではimgタグが次のように定義されています。
<img class="<?= $escaper->escapeHtmlAttr($block->getClass()) ?>"
<?php foreach ($block->getCustomAttributes() as $name => $value): ?>
<?= $escaper->escapeHtmlAttr($name) ?>="<?= $escaper->escapeHtml($value) ?>"
<?php endforeach; ?>
src="<?= $escaper->escapeUrl($block->getImageUrl()) ?>"
loading="lazy"
width="<?= $escaper->escapeHtmlAttr($block->getWidth()) ?>"
height="<?= $escaper->escapeHtmlAttr($block->getHeight()) ?>"
alt="<?= $escaper->escapeHtmlAttr($block->getLabel()) ?>"/>
$block->getImageUrl() がそのURLを出力する部分。このメソッドが、
/pub/media/catalog/product/cache/...
という実際のURLを生成しています。
リサイズ画像はいつ生成されるのか
リサイズ画像のURLについては分かりましたが、ではその画像ファイル自体はいつ生成されるのでしょうか。
Magentoではリサイズ画像は下記のタイミングで自動生成されます。主に2つ。
商品登録時
商品画像が登録されると、テーマのview.xmlに定義されている画像設定に応じてその商品のリサイズ画像が予め生成されます。非同期で生成されます(キューに登録されコンシューマ/cronで処理されます)。
※商品登録時の自動生成は2.3以降で導入され、処理の非同期化は2.4.7から導入されています。
リサイズ画像が存在しない状態でアクセスされた時
何らかの理由でキャッシュ画像が存在しない場合でも、Magentoは自動的に再生成を行います。
実際には pub/media 配下へのアクセスはMagento側で制御されており、
- リサイズ画像の存在確認
- ファイルが無ければ画像生成
- 生成後に画像を返却
という流れで処理されます。
そのため、画像キャッシュを削除しても画像が表示できなくなるという事は無く、アクセスがあると再度自動的に生成されます。
その他のタイミング
上に挙げたタイミング以外でも一部の処理ではその時必要な特定のリサイズ画像を生成する場面もあります(管理画面の商品一覧画面のサムネイルなど)。またコマンドラインからのリサイズ画像再生成の実行でも生成が行われます(後述)。
リサイズ画像のキャッシュファイルクリア
管理画面のキャッシュ管理に「Flush Catalog Images Cache」ボタンがあります。
この操作を実行すると、
pub/media/catalog/product/cache
配下のリサイズ画像が全て削除されます。削除後は画像URLへのアクセスがあった時にMagentoが都度自動的にリサイズ画像を生成します。
画像サイズの変更やview.xmlの変更を行った際に古いキャッシュを全て削除したい場合などで利用することがあります。
注意
キャッシュ画像を削除するとアクセス時に画像のリサイズ画像の生成処理が行われるため、商品一覧ページのような商品画像の多いページで初回表示が非常に重くなる場合がありますので注意してください。
リサイズ画像の再生成コマンド
下記のコマンドでリサイズ画像を一括で再生成することも出来ます。
bin/magento catalog:images:resize
注意
全ての商品画像のリサイズ画像を生成するので処理にとても時間がかかるため、実行の際はご注意ください。
まとめ
Magentoの商品画像表示には、単純なファイル参照ではなく画像リサイズとキャッシュ生成の仕組みが組み込まれています。一見複雑に思えるこの仕組みはテーマでの拡張性などを考慮したものとなっています。
ポイント整理
- 元画像は
pub/media/catalog/productに保存される - 表示時にはリサイズ済み画像が利用される(
pub/media/catalog/product/cacheに保存) - リサイズ画像のURLには加工条件を表すハッシュ値が含まれる
- 画像サイズの定義は view.xml で管理される
- キャッシュ画像はMagentoが自動生成してくれる
仕組みを理解しておくと、テーマ開発で画像サイズを調整する際や、画像表示のトラブル解決などに役立ちます。
※本記事はAdobe Commerce 2.4.7の標準的な動作を確認して記事にしたものです。バージョンや設定によって動作が異なる場合があります。

