<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Customize\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\Annotation\Route;
use Eccube\Repository\ProductRepository;
use Plugin\RecentlyViewedProducts\Service\RecentlyViewedProductService;
use Eccube\Controller\TopController as BaseController;
class CustomizeTopController extends BaseController
{
/**
* @var RecentlyViewedProductService
*/
protected $recentlyViewedProductService;
/**
* RecentlyViewedProductController constructor.
*/
public function __construct(RecentlyViewedProductService $recentlyViewedProductService)
{
$this->recentlyViewedProductService = $recentlyViewedProductService;
}
/**
* @Route("/books", name="books", methods={"GET"})
* @Template("@user_data/books.twig")
*/
public function index()
{
$productRepository = $this->getDoctrine()->getRepository(\Eccube\Entity\Product::class);
// ProductにTagもJOINして取得する
$qb = $productRepository->createQueryBuilder('p')
->leftJoin('p.ProductTag', 'pt')
->leftJoin('pt.Tag', 't')
->leftJoin('p.ProductCategories', 'pc')
->leftJoin('pc.Category', 'c')
->addSelect('pt')
->addSelect('t')
->addSelect('pc')
->addSelect('c')
->where('p.Status = 1')
->orderBy('p.id', 'DESC');
$Products = $qb->getQuery()->getResult();
$RecentlyViewedProducts = array_map(function($RecentlyViewedProduct) {
return $RecentlyViewedProduct->getProduct();
}, $this->recentlyViewedProductService->getRecentlyViewedProducts());
$recommendProducts = [];
if($this->getUser()){
$Customer = $this->getUser();
$recentlyViewedProductRepository = $this->getDoctrine()->getRepository(\Plugin\RecentlyViewedProducts\Entity\RecentlyViewedProduct::class);
$histories = $recentlyViewedProductRepository->findBy(
['Customer' => $Customer->getId()],
['viewed_date' => 'DESC'],
30
);
// 履歴のproduct_id一覧を作成
$viewedProductIds = array_map(function($history) {
return $history->getProduct()->getId();
}, $histories);
$historyKeywords = [];
foreach ($histories as $history) {
$product = $history->getProduct();
if (!$product) continue;
// 検索ワード
if ($product->getSearchWord()) {
$words = array_map('trim', explode(',', $product->getSearchWord()));
$historyKeywords = array_merge($historyKeywords, $words);
}
// 著者
if ($product->getAuthor()) {
$historyKeywords[] = $product->getAuthor();
}
}
// ユーザーの所属県
if ($Customer->getPref()) {
$historyKeywords[] = $Customer->getPref()->getName();
}
// 特徴キーワードをユニークにする
$historyKeywords = array_unique($historyKeywords);
// 全商品を取得
$allProducts = $productRepository->findAll();
// 各商品のスコアを計算
$productScores = [];
foreach ($allProducts as $product) {
$keywords = [];
// 検索ワード
if ($product->getSearchWord()) {
$words = array_map('trim', explode(',', $product->getSearchWord()));
$keywords = array_merge($keywords, $words);
}
// 著者
if ($product->getAuthor()) {
$keywords[] = $product->getAuthor();
}
// ここでは商品自体に「県」はないのでスキップ
$keywords = array_unique($keywords);
// 閲覧履歴の特徴キーワードと比較して一致数をカウント
$commonCount = count(array_intersect($historyKeywords, $keywords));
// スコアが高いものだけ残す(ここでは0でも一応保持)
$productScores[] = [
'product' => $product,
'score' => $commonCount,
];
}
// スコア順にソート(スコア高い順)
usort($productScores, function($a, $b) {
return $b['score'] <=> $a['score'];
});
// Twigに渡す用のおすすめ商品リスト作成
$recommendProducts = array_map(function($item) {
return $item['product'];
}, array_slice($productScores, 0, 30)); // 例:おすすめ30件
}
// Twigへ渡す
return [
'Products' => $Products,
'recommendProducts' => $recommendProducts,
'RecentlyViewedProducts' => $RecentlyViewedProducts,
];
}
}