Blog スタッフブログ

EC-CUBE システム開発

[EC-CUBE]EC-CUBE4のOrderItemのカラム追加と購入時データの保存方法

システム開発担当のTFです。

※EC-CUBE4系統対応

メモ

OrderItemにカラムを追加し、購入時のdtb_product_classの内容を保存する際、
dtb_order_itemが作成されるタイミングで(createOrderItemsFromCartItemsの拡張)、保存をかけても
確認画面に進んだ際に、nullになってしまう。
その為、PurchaseFlowの方で、保存を行う。

やり方

  • OderItemにカラムを追加する
  • createOrderItemsFromCartItemsを拡張し、保存する(確認画面でnullが入ってしまうため没)
  • OrderItemのカラム保存用の、PurchaseFlowを追加する(こちらは、nullで上書きされない)

参考

  ご注文内容のご確認画面への表示項目の追加をしたい。
  バックエンド – 購入直前
  購入フローのカスタマイズ
  [EC-CUBE]EC-CUBE4のカラムの追加

サンプル

<?php
namespace Customize\Entity;

use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation as Eccube;
use Eccube\Annotation\EntityExtension;

/**
  * @EntityExtension("Eccube\Entity\OrderItem")
 */
trait OrderItemTrait
{
	/**
     * @ORM\Column(name="price01", type="integer", nullable=true)
	 * @Eccube\FormAppend(
	 *     auto_render=false,
	 *     options={
	 *         "required"=false
	 *     },
	 *	   type="\Symfony\Component\Form\Extension\Core\Type\TextType",
	 * )
     */
    public $price01;
	
	/**
	 * @return integer|null
	 */
	public function getPrice01()
	{
		return $this->price01;
	}

	/**
	 * @param integer $price01
     *
     * @return OrderItem
	 */
	public function setPrice01($price01)
	{
		$this->price01 = $price01;
		return $this;
	}
}
// プロジェクト直下に移動
cd プロジェクトのパス

// Proxy作成
php bin/console eccube:generate:proxies

// キャッシュ削除
php bin/console cache:clear --no-warmup
// テーブルに反映(dtb_order_item テーブル に price01 カラムが追加される)
php bin/console doctrine:schema:update --dump-sql --force

PurchaseFlowを追加する

<?php
namespace Customize\Service\PurchaseFlow\Processor;

use Eccube\Annotation\ShoppingFlow;
use Eccube\Service\PurchaseFlow\Processor\AbstractPurchaseProcessor;

use Eccube\Common\EccubeConfig;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Repository\OrderRepository;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Util\StringUtil;

/**
 * @ShoppingFlow
 * OrderItemのカスタマイズ.
 */
class CustomOrderItemProcessor extends AbstractPurchaseProcessor
{
    /**
     * @var EccubeConfig
     */
    private $eccubeConfig;

    /**
     * @var OrderRepository
     */
    private $orderRepository;

    /**
     * OrderNoProcessor constructor.
     *
     * @param EccubeConfig $eccubeConfig
     * @param OrderRepository $orderRepository
     */
    public function __construct(EccubeConfig $eccubeConfig, OrderRepository $orderRepository)
    {
        $this->eccubeConfig = $eccubeConfig;
        $this->orderRepository = $orderRepository;
    }
	
	/**
     * {@inheritdoc}
     */
    public function prepare(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        // Order以外の場合は何もしない
        if (!$itemHolder instanceof Order) {
            return;
        }

        foreach ($itemHolder->getProductOrderItems() as $item) {
            $ProductClass = $item->getProductClass();
			if( empty($ProductClass) ) continue;
			
			// 追加した項目の再セット
			$item->setPrice01($ProductClass->getPrice01());
        }
    }

}

下記は、没コード
一旦は保存されるが、確認画面に入るとnullで上書きされてしまう為、没

services:
    # OrderHelperを拡張
	Customize\Service\OrderHelper:
        decorates: Eccube\Service\OrderHelper
<?php
namespace Customize\Service;

use Eccube\Service\OrderHelper as BaseOrderHelper;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\CartItem;
use Eccube\Entity\Master\OrderItemType;
use Eccube\Entity\OrderItem;
use Eccube\Repository\DeliveryRepository;
use Eccube\Repository\Master\DeviceTypeRepository;
use Eccube\Repository\Master\OrderItemTypeRepository;
use Eccube\Repository\Master\OrderStatusRepository;
use Eccube\Repository\Master\PrefRepository;
use Eccube\Repository\OrderRepository;
use Eccube\Repository\PaymentRepository;
use SunCat\MobileDetectBundle\DeviceDetector\MobileDetector;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class OrderHelper extends BaseOrderHelper
{
    /**
     * @param Collection|ArrayCollection|CartItem[] $CartItems
     *
     * @return OrderItem[]
     */
    protected function createOrderItemsFromCartItems($CartItems)
    {
		$ProductItemType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);

        return array_map(function ($item) use ($ProductItemType) {
            /* @var $item CartItem */
            /* @var $ProductClass \Eccube\Entity\ProductClass */
            $ProductClass = $item->getProductClass();
            /* @var $Product \Eccube\Entity\Product */
            $Product = $ProductClass->getProduct();

            $OrderItem = new OrderItem();
            $OrderItem
                ->setProduct($Product)
                ->setProductClass($ProductClass)
                ->setProductName($Product->getName())
                ->setProductCode($ProductClass->getCode())
                ->setPrice($ProductClass->getPrice02())
                ->setQuantity($item->getQuantity())
                ->setOrderItemType($ProductItemType);
				
			// 拡張したカラムに値の保存(一旦は保存されるが、確認画面に入るとnullで上書きされてしまう)
			$OrderItem->setPrice01($ProductClass->getPrice01());

            $ClassCategory1 = $ProductClass->getClassCategory1();
            if (!is_null($ClassCategory1)) {
                $OrderItem->setClasscategoryName1($ClassCategory1->getName());
                $OrderItem->setClassName1($ClassCategory1->getClassName()->getName());
            }
            $ClassCategory2 = $ProductClass->getClassCategory2();
            if (!is_null($ClassCategory2)) {
                $OrderItem->setClasscategoryName2($ClassCategory2->getName());
                $OrderItem->setClassName2($ClassCategory2->getClassName()->getName());
            }

            return $OrderItem;
        }, $CartItems instanceof Collection ? $CartItems->toArray() : $CartItems);
    }
}