Table of Content
ショッピングサイトに当たり前のようにある、商品詳細ページに「よく一緒に購入されている商品」を表示させる機能がec-cube4にはないので、簡単なレコメンドを表示する関数を作成した(MySQLを使用)。
手順
- Twig Extension を作成する
- 「よく一緒に購入されている商品」のブロックを作成する
- 商品詳細用レイアウトを作成して、2で作成したブロックを設定する
Twig Extension を作成する
ファイルを新規作成
app/Customize/Twig/Extension/FsBuyTogether.php
過去120日間の購入履歴を参照して、商品を6つ取得する。
<?php
namespace Customize\Twig\Extension;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\Master\ProductStatus;
use Eccube\Repository\ProductRepository;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class FsBuyTogether extends AbstractExtension
{
/** @var EntityManagerInterface */
private $entityManager;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* FsBuyTogether constructor.
*
* @param EntityManagerInterface $entityManager
* @param ProductRepository $productRepository
*/
public function __construct(
EntityManagerInterface $entityManager,
ProductRepository $productRepository
) {
$this->entityManager = $entityManager;
$this->productRepository = $productRepository;
}
/**
* Returns a list of functions to add to the existing list.
*
* @return array An array of functions
*/
public function getFunctions()
{
return [
new TwigFunction('FsBuyTogether', [$this, 'getFsBuyTogether'])
];
}
/**
* Name of this extension
*
* @return string
*/
public function getName()
{
return 'FsBuyTogether';
}
/**
* よく一緒に購入されている商品
*
* @param int $productId
*
* @return array
*/
public function getFsBuyTogether($productId)
{
$days = 120; // 過去120日間の購入履歴を参照する
$searchDate = date('Y-m-d 00:00:00', strtotime( date('Ymd') . '-'. $days . ' day' ) );
$CheckProducts = [];
if (0 == $productId) { return $CheckProducts; }
try {
$sql = 'select
t3.id, count(t3.id) as cnt
from
dtb_product t3
left join dtb_order_item t4
on t3.id = t4.product_id and t3.product_status_id=1
where
t3.id <> :id
and order_id in (
select
t1.id
from
dtb_order t1 left join dtb_order_item t2 on t1.id = t2.order_id
where
t1.create_date >= :create_date and t2.product_id = :id
group by
t1.id
)
group by
t3.id
order by
cnt desc limit 6';
$stmt = $this->entityManager->getConnection()->prepare($sql);
$stmt->execute(['id' => $productId, 'create_date' => $searchDate]);
$result = $stmt->fetchAll();
foreach ($result as $id) {
$Product = $this->productRepository->find($id['id']);
if(!is_null($Product) && $Product->getStatus()->getId() === ProductStatus::DISPLAY_SHOW) {
$CheckProducts[] = $Product;
}
}
return $CheckProducts;
} catch (\Exception $e) {
$CheckProducts = [];
}
return $CheckProducts;
}
}
ブロックを作成する
ファイルを新規作成
app/template/default/Block/buy_together.twig
管理画面の「コンテンツ管理」->「ブロック管理」を開いて新規作成
{#
よく一緒に購入されている商品
#}
{% if app.request.get('_route') == 'product_detail' %}
{% set FsBuyTogetherProducts = FsBuyTogether( Product.id ) %}
{% if FsBuyTogetherProducts|length > 0 %}
<div class="ec-role">
<div class="row">
<h2 class="title mgL">よく一緒に購入されている商品</h2>
{% set i = 1 %}
{% for Product in FsBuyTogetherProducts %}
<div class="col-xs-6 col-md-2">
<div class="thumbnail">
<a href="{{ url('product_detail', {'id' : Product.id}) }}" class="item_photo">
<img src="{{ asset(Product.main_list_image|no_image_product, 'save_image') }}" alt="{{ Product.name }}"></a>
<div class="caption">
<h3>{{ Product.name }}</h3>
<p><span class="ec-price__price">{{ Product.getPrice02IncTaxMin|price }}</span>
<span class="ec-price__tax">{{ 'common.tax_include'|trans }}</span></p>
</div>
</div>
</div>
{% if ((i % 2 == 0) and (0 < i)) %}
<div class="clearfix visible-xs"></div>
{% endif %}
{% set i = i + 1 %}
{% endfor %}
</div>
</div>
{% endif %}
{% endif %}
作成したブロックを表示させるページは商品詳細ページだけにしたいので、商品詳細用のレイアウトを作成する(上記のブロック内で商品詳細ページかどうかの判定を入れているので、「下層ページレイアウト」のままでもいい)。
管理画面の「コンテンツ管理」->「レイアウト管理」を開いて新規作成。
作成した商品詳細用レイアウトに上記で作成した「よく一緒に購入されている商品」ブロックをドラッグ&ドロップして配置。
次に「ページ管理」で、商品詳細ページは商品詳細用レイアウトを使うように設定する。