データベースを使って、テーブルにあるデータの表示方法を紹介します。

EC-CUBEにはMVCモデルのような仕組みがあります。

まずは、EC-CUBE独自のMVCモデルのそれぞれの役割を紹介します。

appフォルダにあるCustomizeフォルダは、開発者のカスタマイズできる4つのフォルダがあります。

app/Customize に対象フォルダがあります。

Controller:

ユーザーのリクエストを受け取り、処理結果を画面表示やAPIレスポンスとして返す「制御部」

Entity:

データベースのテーブルと対応し、データそのものをオブジェクトとして扱う「データ構造」

Repository:

エンティティに対するデータ操作(検索・更新など)をまとめた「データアクセス層」

Resource:

主にテンプレートや静的ファイルなど、画面表示やスタイル、スクリプトを定義する「外部リソース」

例えば、新着情報一覧を表示し、そのうちの一つをクリックすると、その新着情報の詳細を見ることができるというシンプルなもので説明します。

まず、envファイルで、開発環境をデバッグモードにします。

APP_ENV=prodというところがあるので、APP_ENV=devに変更します。

APP_ENV=dev
APP_DEBUG=1

まずブロック管理で、新着情報一覧画面を作ります。

news.twig 新着情報画面

{% set NewsList = repository('Eccube\\Entity\\News').getList() %}

   
          
            {% for News in NewsList %}
                        <div>
                            {{ News.publish_date|date_day }}
                        </div>
                            <div>
                                {{ News.title }}
                            </div>
                            {% if News.description or News.url %}
                                <div class="ec-newsRole__newsClose">
                                    <a class="ec-newsRole__newsCloseBtn">
                                        <i class="fas fa-angle-down"></i>
                                    </a>
                                </div>
                            {% endif %}
                        
                        <div>
                        {{ News.description|raw|nl2br }}
                        {% if News.url %}
                            {#<br>#}
                            {#<a href="{{ News.url }}" {% if News.link_method == '1' %}target="_blank"{% endif %}>{{ '詳しくはこちら'|trans }}</a>#}
                            <a href="{{ News.url }}">詳細</a>
                        {% endif %}
                        </div>
                
            {% endfor %}
        

Controllerフォルダ:NewsController.php

<?php
// customize/Controller/NewsController.php

namespace Customize\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Customize\Entity\News;

class NewsController extends AbstractController
{
    /**
     * @Route("/news/{id}", name="news_detail", requirements={"id"="\d+"})
    */

    public function detail(int $id, EntityManagerInterface $entityManager): Response
    {
        $news = $entityManager->getRepository(News::class)->find($id);
        if (!$news) {
            throw $this->createNotFoundException('指定された新着情報は存在しません。');
        }
        return $this->render('@user_data/news_detail.twig', ['news' => $news]);

    }
}

app/Customize/Entiry

Entityフォルダ:News.php

<?php
// customize/Entity/News.php

namespace Customize\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="Customize\Repository\NewsRepository")
 * @ORM\Table(name="dtb_news")
 */
class News
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @ORM\Column(name="description", type="text", nullable=true)
     */
    private $content;

    /**
     * @ORM\Column(name="publish_date", type="datetime", nullable=true)
     */
    private $publishDate;

    // --- Getter/Setter ---
    
    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }
    
    public function setTitle(string $title): self
    {
        $this->title = $title;
        return $this;
    }
    
    public function getContent(): ?string
    {
        return $this->content;
    }
    
    public function setContent(?string $content): self
    {
        $this->content = $content;
        return $this;
    }
    
    public function getPublishDate(): ?\DateTimeInterface
    {
        return $this->publishDate;
    }
    
    public function setPublishDate(?\DateTimeInterface $publishDate): self
    {
        $this->publishDate = $publishDate;
        return $this;
    }
}

Repositoryフォルダ:NewsRepository.php

app/Customize/Repository/

4.30ではrepositoryフォルダがないので新規でRepositoryフォルダを作成します。

<?php
// customize/Repository/NewsRepository.php

namespace Customize\Repository;

use Doctrine\ORM\EntityRepository;

class NewsRepository extends EntityRepository
{
    /**
     * 公開済みニュース記事を取得するサンプルメソッド
     *
     * @return array
     */
    public function findPublishedNews(): array
    {
        $qb = $this->createQueryBuilder('n');
        $qb->where('n.publishDate <= :now')
           ->setParameter('now', new \DateTime())
           ->orderBy('n.publishDate', 'DESC');

        return $qb->getQuery()->getResult();
    }
}

最後に新着情報の詳細画面を作ります。

user_dataフォルダに、news_detail.phpを作成します。

app/template/user_data/

news_detail.php 新着情報詳細画面

{% extends 'default_frame.twig' %}

{% block title %}{{ news.title }}{% endblock %}

{% block main %}
<article>
    <header>
        <h1>{{ news.title }}</h1>
        <time datetime="{{ news.publishDate|date('c') }}">
            {{ news.publishDate|date('Y-m-d H:i') }}
        </time>
    </header>
    <section class="news-content">
        {{ news.content|raw }}
    </section>
</article>
{% endblock %}

もしSymfonyのルート機構を利用してPATH関数で動的にURLを生成したい場合は、管理画面のファイル管理で作成したページに対してもルートを手動で登録する必要があります。

たとえば、以下のようにルーティング設定ファイルroutes.yamlにルート定義を追加します。

custom_news_detail:
    path: /custom_news_detail/{id}
    defaults: { _controller: 'Customize\\Controller\\NewsController::detail', id: null }
    requirements:
        id: "\d+"

また、ファイル管理上、app/template/user_data にファイルを置きたい場合は、Twigの設定にそのディレクトリを追加する必要があります。

config/packages/twig.yaml に次のように追記します

twig:
    paths:
        '%kernel.project_dir%/app/template/user_data': user_data

これで新着情報一覧から、新着情報をクリックし、新着情報の詳細画面が表示され完成です。