我正在使用一个包含价格信息的费用实体,我选择将金额(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);
再次感谢伙计们!