管理货币类型以编辑实体


Managing currency type to edit Entity

我正在使用一个包含价格信息的费用实体,我选择将金额(int(与货币(字符串(分开。

/**
 * @var integer
 * 
 * @ORM'Column(name="price_amount", type="integer")
 */
private $priceAmount;
/**
 * @var string
 * 
 * @ORM'Column(name="price_currency", type="string", length=10)
 */
private $priceCurrency;

我正在使用MoneyBundle(通过TBBC捆绑包(让创建表单显示支持的货币列表,并让用户选择正确的货币。验证表单后,价格货币将作为字符串存储在数据库中。

         // ExpenseType.php
         [...]
         use Tbbc'MoneyBundle'Form'Type'CurrencyType;
         [...]
         $builder
            ->add('priceAmount', NumberType::class, array(
                'label' => 'Amount spent',
                'attr' => array(
                    'placeholder' => "Amount",
                    'autocomplete' => 'off'
            )))
            ->add('priceCurrency', CurrencyType::class, array(
                'label' => 'Currency'
            ))

我正在尝试创建另一种表单类型ExpenseEditType(扩展上面的ExpenseType(,它将帮助用户修改金额(金额本身+其货币(;显然,当我加载ExpenseEditType表单时,symfony试图从我的学说实体创建一个CurrencyType,但它只在数据库中找到一个字符串(例如"CAD","EUR"等(。

    $form = $this->createForm(new ExpenseEditType(), $expense);

引发的异常:

给定类型为"货币"、"字符串"的预期参数

我的

问题是:我怎样才能创建与创建表单相同的表单,并要求symfony显示相同的货币列表,选择一个默认值,并在我的price.currency字段中找到它?

我正在考虑 2 个选项(但我可能完全错了(:- 使用DataTransformer,但只是从Symfony开始,我真的对这种东西一无所知- 在我的费用实体中有一个额外的货币字段,它将金额+货币信息存储在一个货币字段中,在我的 2 个分隔字段(金额/货币(之上;我想坚持使用这两个单独的字段,以便更好地查询数据库中的可能性和准确性。

非常感谢您的帮助和建议!文森特

感谢Heah和Jason的建议,我选择了DataTransformer解决方案,它运行良好:)我的代码基于官方文档。

在下面找到结果:

字符串到货币变形金刚.php

<?php
namespace VP'AccountsBundle'Form'DataTransformer;
// some uses
class StringToCurrencyTransformer implements DataTransformerInterface {
    private $manager;
    public function __construct(ObjectManager $manager) {
        $this->manager = $manager;
    }
    /**
     * Transforms a String (currency_str) to a Currency
     * 
     * @param String|null $currency_str
     * @return Currency The Currency Object
     * @throws UnknownCurrencyException if Currency is not found
     */
    public function transform($currency_str) {
        if (null === $currency_str) {
            return;
        }
        try {
            $currency = new Currency($currency_str);
        } catch (UnknownCurrencyException $ex) {
            throw new TransformationFailedException(
            sprintf(
                    'The currency "%s" does not exist', $currency_str
            ));
        }
        return $currency;
    }
    /**
     * Transforms a Currency (currency) to a String
     * @param Currency $currency
     * @return String|null The ISO code of the currency
     * @throws TransformationFailedException if currency is not found
     */
    public function reverseTransform($currency) {
        // if no currency provided
        if (!$currency) {
            return;
        }
        $currency_str = $currency->getName();
        return $currency_str;
    }
}

我的新费用编辑类型.php

<?php
// some uses
class ExpenseEditType extends ExpenseType   {
    private $manager;
    public function __construct(ObjectManager $manager) {
        $this->manager = $manager;
    }
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options) {
        parent::buildForm($builder, $options);
        $builder->remove('submitnew')
                ->remove('priceCurrency')
                ->add('priceCurrency', CurrencyType::class, array(
                    'label' => 'Devise',
                    'invalid_message' => 'Currency not found'
                ))
                ->add('submitnew', SubmitType::class, array(
                    'label' => 'Edit expense',
                    'attr' => array(
                        'class' => 'btn btn-primary',
                    )
        ));
        $builder->get('priceCurrency')
                ->addModelTransformer(new StringToCurrencyTransformer($this->manager));
    }
    /**
     * @return string
     */
    public function getName() {
        return 'vp_accountsbundle_expenseedit';
    }

我的服务.yml:

services:
    app.form.type.expenseedit:
        class: VP'AccountsBundle'Form'ExpenseEditType
        arguments: ["@doctrine.orm.entity_manager"]
        tags:
            - { name: form.type }

我从控制器的呼叫:

$form = $this->createForm(ExpenseEditType::class, $expense);

再次感谢伙计们!