【EC-CUBE4】商品規格に項目を追加し、バリデーションを入れる

EC-CUBE4で商品規格に必須項目を追加する方法

EC-CUBE4で商品や受注に項目を追加するには、 @EntityExtensionアノテーションを使って拡張を行います。

https://doc4.ec-cube.net/customize_entity

この際、@Eccube\FormAppendアノテーションを使うことで、 管理画面の登録フォームにも項目を追加できるのですが、 商品規格の項目に対して、ここでバリデーションを適用しようとすると、 登録しない規格の組み合わせ(つまりチェックを入れていないもの)に関しても、 アノテーションに設定したバリデーションが走ってしまいます。 必須項目にしたい時などは、これによって登録自体が できなくなってしまうのです。

今回はそれを回避し、かつ、srcフォルダ内を直接触らなくても良い方法を紹介します。

※ 以下では、商品規格に必須項目を追加することを想定しています。

商品規格を拡張する

まずは商品や受注の項目を拡張する時と同様、 @EntityExtensionアノテーションを使って商品規格の項目を作成します。

<?php

namespace Customize\Entity\ProductClass;

use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @EntityExtension("Eccube\Entity\ProductClass")
 */
class ProductClassExtension
{
    /**
     * @ORM\Column(type="string", nullable=true)
     * @Eccube\FormAppend(
     *     auto_render=true,
     *     type="text",
     *     options={
     *         "required": false,
     *         "label": "素材"
     *     }
     * )
     */
    private $material;

    /**
     * @return string
     */
    public function getMaterial()
    {
        return $this->material;
    }

    /**
     * @param string $material
     *
     * @return $this
     */
    public function setMaterial($material)
    {
        $this->material = $material;

        return $this;
    }
}

ここでのポイントは、requiredをfalseとすることです。 trueにするとブラウザ側でバリデーションが走ってしまい、 登録できなくなってしまいます。

その後、商品規格の登録・編集ページのテンプレートに項目を追加します。 この時点で、新しい項目の登録はできるようになります。

※ データベースへのカラム追加は完了していると仮定しています。

商品規格独自のバリデーションを改修

ここからがミソなのですが、商品規格ページではチェックを入れているものと、 そうでないものとで分けてから、 バリデーションをかけるという独自の処理があります。 それが、ProductClassEditType.phpで行われていますので、 これを継承してそこに今回追加した項目のバリデーションを行います。

<?php

namespace Customize\Form\Type\Admin;

use Eccube\Form\Type\Admin\ProductClassEditType as BaseProductClassEditType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Validator\Constraints as Assert;

class ProductClassEditType extends BaseProductClassEditType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        // 追加した項目のバリデーションを検証するイベントリスナーを追加
        $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
            $form = $event->getForm();
            $data = $form->getData();

            // 有効な組み合わせのみバリデーション検証を行う
            // (isEnable == falseなものは、チェックを入れていない規格の組み合わせを表す)
            if ($data['checked'] && $data['stock_unlimited']) {
                // 規格が有効でかつ在庫無制限の場合のバリデーション
                if (empty($data['material'])) {
                    $form['material']->addError(new FormError('素材が入力されていません。'));
                }
            } elseif ($data['checked']) {
                // 規格が有効の場合のバリデーション
                if (empty($data['material'])) {
                    $form['material']->addError(new FormError('素材が入力されていません。'));
                }
            }
        });
    }
}

こうすることで、チェックを入れている規格の組み合わせだけに、 バリデーションをかけることができます。