バージョン選択

フォーラム

メニュー

オンライン状況

78 人のユーザが現在オンラインです。 (66 人のユーザが フォーラム を参照しています。)
登録ユーザ: 0
ゲスト: 78
もっと...

サイト内検索

質問 > フロント機能 > ご注文手続き画面に新たにラジオボタン項目を追加したい

フロント機能

新規スレッドを追加する

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
gwkozaki
投稿日時: 2019/11/12 15:31
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
ご注文手続き画面に新たにラジオボタン項目を追加したい
▼テンプレート
[EC-CUBE] EC-CUBE4.0.3、新規インストール
[レンタルサーバ] ローカル環境

[現象]

現在、ご注文手続き画面にラジオボタンの項目追加を考えております。

以下のEntityのカスタマイズを参照しながら、データベースの追加までは出来ました。
https://doc4.ec-cube.net/customize_entity

app\Customize\Entity\Example.phpと、app\Customize\Repository\ExampleRepository.phpを追加し、idとnameを持ったテーブルを作成し、
Migrationファイルを作成し、id=1とid=2の2つのデータをExampleテーブルに追加しております。

その後、app\Custmize\Entity\OrderTrait.phpにより、Orderテーブルにexample_idをExampleテーブルのidとJoinする形で追加しました。

しかしその後、OrderTraitのexample_idに@FormAppendを追記してラジオボタンを表示しようとすると、以下のエラーが発生し表示できない状態です。
Expected value of type "Customize\Entity\Example" for association field "Eccube\Entity\Order#$example_id", got "integer" instead.


int型になっていないとのエラーだと思うのですが、Exampleテーブルのid、Orderに追加したexample_id共にint(10)でテーブルが作成してあります。
また、mappedをfalseにするとラジオボタン 自体は表示されていたため、データのやり取りができていないのではと考えています。

以下にExample.phpとOrderTrait.phpを添付いたしますので、
どこかおかしな点があれば、ご教授いただけると幸いです。
何卒よろしくお願い申し上げます。


Example.php
<?php

namespace Customize\Entity;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Mapping\ClassMetadata;

if (!class_exists('\Eccube\Entity\Example')) {
    /**
     * Shop
     *
     * @ORM\Table(name="dtb_example")
     * @ORM\InheritanceType("SINGLE_TABLE")
     * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
     * @ORM\HasLifecycleCallbacks()
     * @ORM\Entity(repositoryClass="Customize\Repository\ExampleRepository")
     */
    class Example extends \Eccube\Entity\AbstractEntity
    {
        /**
         * @ORM\Column(name="id", type="integer", options={"unsigned":true})
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

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

        /**
         * Get id.
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * Set name.
         * @param string $name
         * @return Example
         */
        public function setName($name)
        {
            $this->name = $name;
            return $this;
        }

        /**
         * Get name.
         * @return string
         */
        public function getName()
        {
            return $this->name;
        }
    }
}



OrderTrait.php
<?php

namespace Customize\Entity;

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

/**
 * @Eccube\EntityExtension("Eccube\Entity\Order")
 */
trait OrderTrait
{
    /**
     * @var \Customize\Entity\Example
     * @ORM\ManyToOne(targetEntity="Customize\Entity\Example")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="example_id", referencedColumnName="id", nullable=true)
     * })
     * @Assert\NotBlank
     * @Eccube\FormAppend(
     *  auto_render=true,
     *  type="Symfony\Component\Form\Extension\Core\Type\ChoiceType",
     *  options={
     *  "eccube_form_options":{
     *    "auto_render":true
     *  },
     *  "choices":{
     *    "選択肢1":1,
     *    "選択肢2":2,
     *  },
     *  "label":"テスト",
     *  "required":true,
     *  "expanded":true,
     *  "multiple":false,
     *  "data":1,
     *  })
     */
    private $example_id;

    /**
     * @param  integer  $example_id
     * @return Order
     */
    public function setExampleId($example_id = 1)
    {
        $this->example_id = $example_id;
        return $this;
    }

    /**
     * @return integer
     */
    public function getExampleId()
    {
        return $this->example_id;
    }
}
umebius
投稿日時: 2019/11/12 23:59
対応状況: −−−
登録日: 2016/7/22
居住地:
投稿: 2085
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
$example_idですが、ManyToOneのリレーションになっているので、
formのdataは1などの数値ではなく、Customize\Entity\Exampleエンティティインスタンスになります。

ChoiceTypeではなく、Eccube\Form\Type\MasterTypeあたりを使うと良いように思います。


----------------
EC-CUBEカスタマイズ・高速化・脆弱性対策・SEO ご相談ください。

2系・3系から4系へのバージョンアップ実績豊富

gwkozaki
投稿日時: 2019/11/13 10:48
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
umebius様
ご教授いただきありがとうございます。

引用:
$example_idですが、ManyToOneのリレーションになっているので、
formのdataは1などの数値ではなく、Customize\Entity\Exampleエンティティインスタンスになります。

リレーションによって宣言に違いがあるのですね。

エンティティインスタンスでの宣言に変更し、TypeをMasterTypeに切り替えた上でまた試行錯誤してみます。
行き詰まりましたら、また改めてこちらで質問をさせていただけたらありがたいです。
gwkozaki
投稿日時: 2019/11/14 14:55
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
連絡が遅くなり失礼いたしました。
再び行き詰まってしまったため、ご教授いただけませんでしょうか。

あれからMasterTypeを利用すべく、
・Customize\Repository\Master\ExampleRepositoryの設置。
・ExampleテーブルをCustomize\Entity\Master\Exampleに移動し、dtbからmtbに変更。
・Customize\Form\Type\Master\ExampleTypeの追加。
・Customize\Form\Extension\Shopping\OrderTypeExtensionの追加。
・Customize\Entity\OrderTraitにてOrderテーブルにexample_id及びそのセッタとゲッタの設置。
を行いました。

【現状】
・mtbにテーブルの追加はできている。
・ご注文手続き、ご注文確認ともにデータの受け渡しはできており、表示もできる。
・注文確認画面で注文するボタンを押下すると、注文完了画面ではなく購入エラー画面に飛ばされる。
・購入エラー後にOrderテーブルを見ると、新たに受注が立っており、example_idに選択した値が含まれているが受注一覧には表示されていない。

【試したこと】
・ShoppingController.phpの以下の348行部分でvar_dumpを行ったところ、追加した値がNullになっている。
注文処理で一度OrderのUpdateが行われる際にNullになっているのではと考えていますが、間違いございませんでしょうか。
・エラーとしてはShoppingControllerの$form->isValid()がfalseになっていることで、注文処理に入ることすらできていない。(var_dump下のif文の条件が$form->isValid()がtrueでないと入れない。)

ShoppingController.php(一部抜粋)
// フォームの生成.
        $form = $this->createForm(OrderType::class, $Order, [
            // 確認画面から注文処理へ遷移する場合は, Orderエンティティで値を引き回すためフォーム項目の定義をスキップする.
            'skip_add_form' => true,
        ]);
        $form->handleRequest($request);
        var_dump($Order->getExampleId());exit; //☆この部分で取得した値がNullになっている。
        if ($form->isSubmitted() && $form->isValid()) {
            log_info('[注文処理] 注文処理を開始します.', [$Order->getId()]);

            try {
                /*
                 * 集計処理
                 */
                log_info('[注文処理] 集計処理を開始します.', [$Order->getId()]);
                $response = $this->executePurchaseFlow($Order);
                $this->entityManager->flush();



【分からないこと】
1.そもそもこのやり方で大丈夫かどうか。
2.処理として足りていない部分はどこか。
3.注文するボタン押下後、どのような処理が走るか。

以下に関連のあるソースを添付いたしますので、
おかしな点があればご指摘いただけたらありがたいです。
よろしくお願いいたします。

ExampleRepository.php
<?php

namespace Customize\Repository\Master;

use Customize\Entity\Master\Example;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Eccube\Repository\AbstractRepository;

class ExampleRepository extends AbstractRepository
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, Example::class);
    }
}


Example.php
<?php

namespace Customize\Entity\Master;

use Doctrine\ORM\Mapping as ORM;

/**
 * Example
 *
 * @ORM\Table(name="mtb_example")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Entity(repositoryClass="Customize\Repository\Master\ExampleRepository")
 * @ORM\Cache(usage="NONSTRICT_READ_WRITE")
 */
class Example extends \Eccube\Entity\Master\AbstractMasterEntity
{
}
}


ExampleType.php
<?php

namespace Customize\Form\Type\Master;

use Eccube\Form\Type\MasterType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ExampleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $options['example_options']['required'] = $options['required'];
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'class' => 'Customize\Entity\Master\Example',
            'expanded' => true,
            'placeholder' => false,
        ]);
    }

    public function getParent()
    {
        return MasterType::class;
    }

    public function getBlockPrefix()
    {
        return 'example';
    }
}


OrderTypeExtension.php
<?php

namespace Customize\Form\Extension\Shopping;

use Eccube\Entity\Order;
use Eccube\Form\Type\Shopping\OrderType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
use Customize\Form\Type\Master\ExampleType;

class OrderTypeExtension extends AbstractTypeExtension
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('example_id', ExampleType::class, [
            'label' => 'テストです',
            'required' => true,
            'expanded' => true,
            'multiple' => false,
            'constraints' => [
                new Assert\NotBlank(),
            ],
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return OrderType::class;
    }
}


OrderTrait.php
<?php

namespace Customize\Entity;

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

/**
 * @Eccube\EntityExtension("Eccube\Entity\Order")
 */
trait OrderTrait
{
    /**
     * @var \Customize\Entity\Master\Example
     * @ORM\ManyToOne(targetEntity="Customize\Entity\Master\Example")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="example_id", referencedColumnName="id", nullable=true)
     * })
     */
    private $Example;

    /**
     * @param \Customize\Entity\Master\Example|null $example_id
     * @return Order
     */
    public function setExampleId(\Customize\Entity\Master\Example $example_id = null)
    {
        $this->Example = $example_id;
        return $this;
    }

    /**
     * @return \Customize\Entity\Master\Example|null
     */
    public function getExampleId()
    {
        return $this->Example;
    }
}

umebius
投稿日時: 2019/11/16 22:54
対応状況: −−−
登録日: 2016/7/22
居住地:
投稿: 2085
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
詳しく確認した訳ではありませんが、
「注文確認画面で注文するボタンを押下すると、注文完了画面ではなく購入エラー画面に飛ばされる。」
「$form->isValid()がfalseになっていることで、注文処理に入ることすらできていない」
ということであれば、OrderTypeExtensionでskip_add_formオプションを考慮していないためではないでしょうか。

ShoppingController.phpnのコメントにあるように
確認画面から注文処理へ遷移する場合は, Orderエンティティで値を引き回すためフォーム項目の定義をスキップする.必要があります。


----------------
EC-CUBEカスタマイズ・高速化・脆弱性対策・SEO ご相談ください。

2系・3系から4系へのバージョンアップ実績豊富

gwkozaki
投稿日時: 2019/11/18 9:24
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
お返事が遅くなってしまい、申し訳ございません。
ご助力いただき、非常に助かります。ありがとうございます。
引用:
「注文確認画面で注文するボタンを押下すると、注文完了画面ではなく購入エラー画面に飛ばされる。」
「$form->isValid()がfalseになっていることで、注文処理に入ることすらできていない」
ということであれば、OrderTypeExtensionでskip_add_formオプションを考慮していないためではないでしょうか。

skip_add_formオプションというフォームの定義をスキップするオプションのようなものがあるのですね。確認してみます!
gwkozaki
投稿日時: 2019/11/28 10:38
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
またまたご返答遅くなり申し訳ございません!

skip_add_form周りを調整し、動くようにするのに手間取ってしまいましたが、解決いたしました!
ご助力いただいた umebius 様、大変お世話になりました。感謝いたします。

解決方法を以下に記述いたします。
上記のOrderTypeExtensionを以下のように変更することで解決いたしました。

OrderTypeExtension.php
<?php

namespace Customize\Form\Extension\Shopping;

use Eccube\Entity\Order;
use Eccube\Form\Type\Shopping\OrderType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
use Customize\Form\Type\Master\ExampleType;

class OrderTypeExtension extends AbstractTypeExtension
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //☆追加した部分
        if ($options['skip_add_form']) {
            return;
        }
        //追加した部分 END

        $builder->add('example_id', ExampleType::class, [
            'label' => 'テストです',
            'required' => true,
            'expanded' => true,
            'multiple' => false,
            'constraints' => [
                new Assert\NotBlank(),
            ],
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return OrderType::class;
    }
}

こちら、OrderTypeのbuildFormメソッド内にも記述があったため、OrderTypeを拡張したOrderTypeExtensionには記述の必要はないように思っていましたが、必要なようですね。

問題は解決となりましたが、解決にあたり疑問に思ったことが1点あったため解る方がいらっしゃいましたらご教授いただきたいです。

【質問】
1. TypeのExtensionの拡張の仕組み
 OrderTypeExtension側でbuildFormを拡張していますが、OrderTypeのbuildForm内にある以下の記述が、OrderTypeExtensionで追加したフォームに適用されなかったということは、Extensionはその拡張しているフォームのTypeとは完全に別物として呼ばれているということなのでしょうか。
 
if ($options['skip_add_form']) {
    return;
}
umebius
投稿日時: 2019/11/28 10:52
対応状況: −−−
登録日: 2016/7/22
居住地:
投稿: 2085
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
引用:
1. TypeのExtensionの拡張の仕組み
 OrderTypeExtension側でbuildFormを拡張していますが、OrderTypeのbuildForm内にある以下の記述が、OrderTypeExtensionで追加したフォームに適用されなかったということは、Extensionはその拡張しているフォームのTypeとは完全に別物として呼ばれているということなのでしょうか。


いえ考え方としては逆でして、同じものだから最後のフォームが表示されない注文確認画面では(必須項目の)フォーム要素を追加するとまずいんですね。

確認画面から注文処理へ遷移する場合は、画面にフォームがないのでデータは送られないけど、$form->isValid()である必要があり

項目を追加しないためのオプションとしてskip_add_formを使っています。

Extensionでもその際は追加しないよう対処してやる必要があります
gwkozaki
投稿日時: 2019/11/28 16:01
対応状況: −−−
常連
登録日: 2019/7/30
居住地: 日本
投稿: 53
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
umebius様

早速のご回答ありがとうございます!非常に勉強になります!

引用:
いえ考え方としては逆でして、同じものだから最後のフォームが表示されない注文確認画面では(必須項目の)フォーム要素を追加するとまずいんですね。

確認画面から注文処理へ遷移する場合は、画面にフォームがないのでデータは送られないけど、$form->isValid()である必要があり

項目を追加しないためのオプションとしてskip_add_formを使っています。

Extensionでもその際は追加しないよう対処してやる必要がありま

なるほど、確認画面にFormが表示されてないという見た目に騙されていたということですね。
見た目上表示されていなくとも、確認画面ではフォームが生成されていて、生成されることで入力画面で入力したにも関わらず、真っさらなフォームが作られNullとなると。
そして必須のNullがあることで$form->isValid()がfalseとなり購入エラーになるということですかね。
そこでskip_add_formをオプションとして指定して、確認画面で新たにフォームを作成させないようにするというところでしょうか。

まだ分からないのですが、同じものとして扱われるのであればOrderTypeにさえskip_add_formに関する記述があればExtensionにも反映されそうな気がするのですが、なぜExtensionにも記述が必要なのでしょうか?
理解が遅く申し訳ございませんが、ご教授いただけますと幸いです。
よろしくお願いいたします。
umebius
投稿日時: 2019/11/28 18:59
対応状況: −−−
登録日: 2016/7/22
居住地:
投稿: 2085
Re: ご注文手続き画面に新たにラジオボタン項目を追加したい
あくまでイメージですが
OrderTypeのbuildFormメソッドを処理した上で(注文確定の際にはskip_add_formで何もaddされません)
ExtensionのbuildFormメソッドが呼ばれ処理されます。

1つでもNotBlankのフォームがaddされてしまうとisValidがfalseになってしまうため、skip_add_formオプションがtrueの時はaddしてはいけないということになります。

(1) 2 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ


 



ログイン


EC-CUBE公式 Amazon Payプラグイン

統計情報

総メンバー数は95,938名です
総投稿数は111,632件です

投稿数ランキング

1
seasoft
7369
2
468
3217
3
AMUAMU
2712
4
nanasess
2325
5
umebius
2085
6
yuh
1893
7
h_tanaka
1850
8
red
1574
9
mcontact
1535
10
tsuji
958
11
fukap
907
12
shutta
835
13
tao_s
804
14 ramrun 789
15 karin 689
16 sumida 641
17
homan
633
18 DELIGHT 572
19
patapata
502
20
flealog
485


ネットショップの壺

EC-CUBEインテグレートパートナー

Copyright© EC-CUBE CO.,LTD. All Rights Reserved.