【EC-CUBE 4】Serviceの役割・実装方法

本記事では、特定の機能をまとめておけるServiceの使い方と実装方法について紹介します。

Serviceを使うことで、特定の機能をControllerなどから分離することができます。これにより、コードの再利用性と保守性が高まり、管理が容易になります。EC-CUBEでは、支払いやカートに関する機能をまとめたServiceがデフォルトで多数実装されています。

【動作環境】
EC CUBEのバージョン:4.2.1
サーバー:Xserver

目次

特定のテキストを表示するServiceを作成し、Controllerで呼び出す

まずは、特定の文字列 ” Hello 〇〇! ” を出力するだけのシンプルなサービスを実装してみます。
以下のGreeingServiceクラスを定義したファイルを作成し、「app/Customize/Service」に保存します。(Serviceフォルダはデフォルトでは用意されていないので、フォルダも新しく作成します。)

<?php

namespace Customize\Service;

class GreetingService
{
    public function getGreeting(string $name): string
    {
        return "Hello, " . $name . "!";
    }
}

次に、作成したServiceをControllerで呼び出して実行します。
今回は、TestControllerという独自に準備したコントローラを使用します。

<?php

namespace Customize\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Eccube\Controller\AbstractController;
use Customize\Service\GreetingService;

class TestController extends AbstractController
{
  /**
   * @Route("/test", name="test")
   * @Template("test.twig")
   */
  public function index(Request $request, GreetingService $greetingService)
  {
    $greeting = $greetingService->getGreeting('Taro');

    return [
      'Greeting' => $greeting
    ];
  }
}

先ほど作成したGreetingServiceをindexメソッドの引数として受け取ることでサービスを使用できます。getGreetingメソッドの引数にはTaroを指定し、「Hello, Taro!」を$greetingに代入しています。

最後に、TwigテンプレートでConrollerから受け取った変数Greetingを表示させ、GreetingServiceが機能しているか確認します。

{% extends 'default_frame.twig' %}

{% block main %}

<h1>Serviceのテストページです</h1>
<p>{{ Greeting }}</p>

{% endblock %}
「ドメイン/test」の表示。Controllerやテストページは こちらの記事 にて作成しています。

想定通り「Hello, Taro!」が表示されました!

特定の商品情報を取得するServiceを作成し、Controllerで呼び出す

今度は、IDから特定の商品を検索し、商品名と商品説明を取得するServiceを実装してみます。
以下のGetProductServiceクラスを定義したファイルを作成し、「app/Customize/Service」に保存します。

<?php

namespace Customize\Service;

use Eccube\Repository\ProductRepository;

class GetProductService
{
  private $productRepository;

  public function __construct(ProductRepository $productRepository)
  {
      $this->productRepository = $productRepository;
  }

    public function getProduct($productId)
    {
        $product = $this->productRepository->find($productId);
  
        return [
          'name' => $product->getName(),
          'description' => $product->getDescriptionDetail(),
        ];
    }
}

Serviceクラス内でProductRepositoryを呼び出し、findメソッドを利用しています。(Repositoryについては こちらの記事 にて。)

作成したServiceはConrollerで実行し、先ほどと同様Twigテンプレートで表示させてみます。
getProductメソッドの引数には「1」を指定し、ID=1の商品を取得します。

<?php

namespace Customize\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Eccube\Controller\AbstractController;
use Customize\Service\GetProductService;

class TestController extends AbstractController
{
  /**
   * @Route("/test", name="test")
   * @Template("test.twig")
   */
  public function index(Request $request, GetProductService $productService)
  {
    $product = $productService->getProduct(1);

    return [
      'ProductName' => $product['name'],
      'ProductDescription' => $product['description'],
    ];
  }
}
{% extends 'default_frame.twig' %}

{% block main %}

<h1>Serviceのテストページです</h1>
<p>{{ ProductName }}</p>
<p>{{ ProductDescription }}</p>

{% endblock %}
「ドメイン/test」の表示。Controllerやテストページは こちらの記事 にて作成しています。

想定通り、ID=1の商品名と商品説明を表示できました!

本記事のような簡単な実装であれば、わざわざServiceクラスを作らずにControllerですべて実装すれば良いのでは?と思われるかもしれませんが、機能が複雑になったり、関連する機能を纏めたり、複数のControllerで使用したりする場合に便利な機能ですね。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次