Có cách nào dễ dàng để đặt giá trị mặc định cho trường mẫu văn bản không?
Có cách nào dễ dàng để đặt giá trị mặc định cho trường mẫu văn bản không?
Câu trả lời:
Có thể được sử dụng trong quá trình tạo dễ dàng với:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
khóa thành'value'
empty_data
data
là vô ích - nó ghi đè lên giá trị đã lưu. empty_data
không hiển thị giá trị, nó sử dụng nó khi gửi giá trị trống và không thể lưu các lựa chọn không được kiểm tra.
bạn có thể đặt giá trị mặc định với empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
Tôi đã từng suy ngẫm về điều này một vài lần trong quá khứ nên nghĩ rằng tôi đã ghi lại những ý tưởng khác nhau mà tôi đã có / sử dụng. Một cái gì đó có thể được sử dụng, nhưng không có giải pháp Symfony2 "hoàn hảo" nào.
Trình xây dựng Trong Thực thể, bạn có thể thực hiện $ this-> setBar ('giá trị mặc định'); nhưng điều này được gọi mỗi khi bạn tải thực thể (db hoặc không) và hơi lộn xộn. Tuy nhiên, nó hoạt động cho mọi loại trường vì bạn có thể tạo ngày hoặc bất cứ thứ gì bạn cần.
Nếu tôi tuyên bố trong get thì tôi sẽ không, nhưng bạn có thể.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Nhà máy / ví dụ . Gọi một hàm tĩnh / lớp thứ cấp cung cấp cho bạn một Thực thể mặc định được điền trước dữ liệu. Ví dụ
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
Không thực sự lý tưởng, bạn sẽ phải duy trì chức năng này nếu bạn thêm các trường bổ sung, nhưng điều đó có nghĩa là bạn đang tách các setters dữ liệu / mặc định và được tạo từ db. Tương tự, bạn có thể có nhiều getFactories nếu bạn muốn dữ liệu mặc định khác nhau.
Các thực thể mở rộng / phản chiếu Tạo một thực thể mở rộng (ví dụ FooCreate mở rộng Foo) cung cấp cho bạn dữ liệu mặc định tại thời điểm tạo (thông qua hàm tạo). Tương tự như ý tưởng Factory / dụ chỉ là một cách tiếp cận khác - cá nhân tôi thích các phương thức tĩnh hơn.
Đặt dữ liệu trước khi xây dựng biểu mẫu Trong các hàm tạo / dịch vụ, bạn biết nếu bạn có một thực thể mới hoặc nếu nó được điền từ db. Do đó, thật hợp lý khi gọi dữ liệu đã đặt trên các trường khác nhau khi bạn lấy một thực thể mới. Ví dụ
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Biểu mẫu Sự kiện Khi bạn tạo biểu mẫu bạn đặt dữ liệu mặc định khi tạo các trường. Bạn ghi đè điều này bằng cách sử dụng trình nghe sự kiện PreSetData. Vấn đề với điều này là bạn đang sao chép khối lượng công việc / sao chép mã mẫu và làm cho việc duy trì / hiểu nó trở nên khó khăn hơn.
Biểu mẫu mở rộng Tương tự như sự kiện Biểu mẫu, nhưng bạn gọi loại khác tùy thuộc vào việc đó có phải là thực thể db / mới không. Điều này có nghĩa là bạn có FooType xác định biểu mẫu chỉnh sửa của bạn, BarType mở rộng FooType này và đặt tất cả dữ liệu vào các trường. Trong bộ điều khiển của bạn, sau đó bạn chỉ cần chọn loại hình để kích hoạt. Điều này thật tệ nếu bạn có một chủ đề tùy chỉnh và thích các sự kiện, tạo ra quá nhiều bảo trì theo ý thích của tôi.
Twig Bạn có thể tạo chủ đề của riêng mình và mặc định dữ liệu bằng cách sử dụng tùy chọn giá trị khi bạn thực hiện trên cơ sở từng trường. Không có gì ngăn cản bạn gói cái này vào một chủ đề biểu mẫu nếu bạn muốn giữ cho các mẫu của bạn sạch sẽ và mẫu có thể tái sử dụng. ví dụ
form_widget(form.foo, {attr: { value : default } });
JS Sẽ là tầm thường khi điền vào biểu mẫu với hàm JS nếu các trường trống. Bạn có thể làm một cái gì đó với giữ chỗ chẳng hạn. Đây là một ý tưởng tồi, xấu.
Biểu mẫu dưới dạng dịch vụ Đối với một trong các dự án dựa trên hình thức lớn tôi đã thực hiện, tôi đã tạo một dịch vụ tạo tất cả các biểu mẫu, thực hiện tất cả quá trình xử lý, v.v ... Điều này là do các biểu mẫu được sử dụng trên nhiều bộ điều khiển trong nhiều môi trường và trong khi các biểu mẫu được tạo / xử lý theo cùng một cách, chúng được hiển thị / tương tác với nhau (ví dụ: xử lý lỗi, chuyển hướng, v.v.). Cái hay của phương pháp này là bạn có thể mặc định dữ liệu, làm mọi thứ bạn cần, xử lý lỗi một cách khái quát, v.v. và tất cả được gói gọn ở một nơi.
Kết luận Như tôi thấy, bạn sẽ gặp vấn đề tương tự hết lần này đến lần khác - dữ liệu mặc định sẽ sống ở đâu?
Cuối cùng, tôi đã tiếp cận vấn đề khác nhau mỗi lần. Ví dụ: tùy chọn "bản tin" của biểu mẫu đăng ký dễ dàng (và logic) được đặt trong hàm tạo ngay trước khi tạo biểu mẫu. Khi tôi đang xây dựng các bộ sưu tập biểu mẫu được liên kết với nhau (ví dụ: các nút radio trong các loại biểu mẫu khác nhau được liên kết với nhau) thì tôi đã sử dụng Trình lắng nghe sự kiện. Khi tôi xây dựng một thực thể phức tạp hơn (ví dụ: một thực thể yêu cầu trẻ em hoặc nhiều dữ liệu mặc định), tôi đã sử dụng một hàm (ví dụ: 'getFactory') để tạo thành phần tử khi tôi cần.
Tôi không nghĩ có một cách tiếp cận "đúng" vì mỗi lần tôi có yêu cầu này thì nó hơi khác một chút.
Chúc may mắn! Tôi hy vọng tôi đã cho bạn một số thực phẩm để suy nghĩ ở mức nào và không lan man quá nhiều;)
Nếu bạn cần đặt giá trị mặc định và biểu mẫu của bạn liên quan đến thực thể, thì bạn nên sử dụng phương pháp sau:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
Nếu không, myField
luôn luôn sẽ được đặt thành giá trị mặc định, thay vì nhận giá trị từ thực thể.
$options['data']->getMyField()
bằng$option['data']['myField']
empty_data
: Tùy chọn này xác định giá trị nào trường sẽ trả về khi giá trị được gửi trống. Nó không đặt giá trị ban đầu
Bạn có thể đặt mặc định cho trường liên quan trong lớp mô hình của mình (theo định nghĩa ánh xạ hoặc tự đặt giá trị).
Hơn nữa, FormBuilder cung cấp cho bạn cơ hội để đặt các giá trị ban đầu với phương thức setData () . Trình xây dựng biểu mẫu được truyền cho createForm () phương thức của lớp biểu mẫu của bạn.
Ngoài ra, hãy kiểm tra liên kết này: http://symfony.com/doc/cản/book/forms.html#USE-a-form-without-a- class
Nếu biểu mẫu của bạn bị ràng buộc với một thực thể, chỉ cần đặt giá trị mặc định trên chính thực thể đó bằng phương thức xây dựng:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Sử dụng setData(...)
cho những điều này.
Cách tiếp cận 1 (từ http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Chỉ cần đặt giá trị mặc định trong thực thể của bạn, trong khai báo biến hoặc hàm tạo:
class Entity {
private $color = '#0000FF';
...
}
hoặc là
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Cách tiếp cận 2 từ một nhận xét trong liên kết trên và câu trả lời của Dmitriy (không phải câu trả lời được chấp nhận) từ Cách đặt giá trị mặc định cho trường biểu mẫu trong Symfony2?
Thêm giá trị mặc định vào thuộc tính dữ liệu khi thêm trường bằng FormBuilder, được điều chỉnh từ câu trả lời của Dmitriy.
Lưu ý rằng điều này giả định rằng thuộc tính sẽ và sẽ chỉ có giá trị null khi nó là một thực thể mới chứ không phải là một thực thể hiện có.
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('color', 'text', array(
'label' => 'Color:',
'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
)
);
}
Bạn có thể đặt một giá trị mặc định, ví dụ cho biểu mẫu message
, như thế này:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
Trong trường hợp biểu mẫu của bạn được ánh xạ tới một Thực thể, bạn có thể đi như thế này (ví dụ: tên người dùng mặc định):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Một giải pháp chung cho mọi trường hợp / cách tiếp cận, chủ yếu bằng cách sử dụng một biểu mẫu không có lớp hoặc khi chúng tôi cần truy cập vào bất kỳ dịch vụ nào để đặt giá trị mặc định:
// src/Form/Extension/DefaultFormTypeExtension.php
class DefaultFormTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (null !== $options['default']) {
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($options) {
if (null === $event->getData()) {
$event->setData($options['default']);
}
}
);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('default', null);
}
public function getExtendedType()
{
return FormType::class;
}
}
và đăng ký gia hạn mẫu:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Sau đó, chúng ta có thể sử dụng default
tùy chọn trong bất kỳ trường mẫu nào:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Đừng sử dụng:
'data' => 'Default value'
Đọc tại đây: https://symfony.com/doc/cản/reference/forms/types/form.html#data
"Tùy chọn dữ liệu luôn ghi đè giá trị được lấy từ dữ liệu miền (đối tượng) khi kết xuất. Điều này có nghĩa là giá trị đối tượng cũng bị ghi đè khi biểu mẫu chỉnh sửa một đối tượng đã tồn tại, khiến nó mất giá trị bền vững khi biểu mẫu được gửi."
Sử dụng như sau:
Giả sử, trong ví dụ này, bạn có Entity Foo và có một trường "hoạt động" (trong ví dụ này là CheckBoxType, nhưng quy trình này giống với mọi loại khác), mà bạn muốn được kiểm tra theo mặc định
Trong lớp FooFormType của bạn thêm:
...
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
...
public function buildForm( FormBuilderInterface $builder, array $options )
{
...
$builder->add('active', CheckboxType::class, array(
'label' => 'Active',
));
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event){
$foo = $event->getData();
// Set Active to true (checked) if form is "create new" ($foo->active = null)
if(is_null($foo->getActive())) $foo->setActive(true);
}
);
}
public function configureOptions( OptionsResolver $resolver )
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle:Foo',
));
}
'data' => $data['myfield'] ?? 'Default value'
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null) {
$form->add('position', IntegerType::class, array('data' => 0));
}
});
$event->setData()
thay vì làm lại lĩnh vực có thể làm cho nó thậm chí còn tốt hơn.
Chỉ để tôi hiểu vấn đề.
Bạn muốn điều chỉnh cách xây dựng biểu mẫu dựa trên dữ liệu trong thực thể của bạn. Nếu thực thể đang được tạo thì sử dụng một số giá trị mặc định. Nếu thực thể tồn tại sử dụng giá trị cơ sở dữ liệu.
Cá nhân, tôi nghĩ rằng giải pháp của @ PolarMans là con đường để đi. Tôi thực sự sẽ đặt các giá trị mặc định trong hàm tạo hoặc trong câu lệnh thuộc tính. Nhưng bạn dường như không thích cách tiếp cận đó.
Thay vào đó bạn có thể làm theo điều này: http://symfony.com/doc/cản/cookbook/form/dynamic_form_modification.html
Bạn treo một trình lắng nghe trên loại biểu mẫu của bạn và sau đó bạn có thể kiểm tra thực thể của mình và điều chỉnh trình xây dựng-> thêm các câu lệnh phù hợp dựa trên việc tạo ra một thực thể mới hoặc hiện có. Bạn vẫn cần chỉ định các giá trị mặc định của mình ở đâu đó mặc dù bạn chỉ có thể mã hóa chúng trong trình nghe của mình. Hoặc chuyển chúng vào loại hình.
Có vẻ như rất nhiều công việc mặc dù. Tốt hơn là chỉ chuyển thực thể vào biểu mẫu với các giá trị mặc định đã được đặt.
Thông thường, đối với các giá trị mặc định của mẫu i sử dụng đồ đạc. Bởi vì cách này không dễ nhất, nhưng rất thoải mái.
Thí dụ:
class LoadSurgeonPlanData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$surgeonPlan = new SurgeonPlan();
$surgeonPlan->setName('Free trial');
$surgeonPlan->setPrice(0);
$surgeonPlan->setDelayWorkHours(0);
$surgeonPlan->setSlug('free');
$manager->persist($surgeonPlan);
$manager->flush();
}
}
Tuy nhiên, trường loại symfony có dữ liệu tùy chọn .
Thí dụ
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
Có một cách rất đơn giản, bạn có thể đặt mặc định như sau:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Nếu bạn đặt 'dữ liệu' trong biểu mẫu tạo của mình, giá trị này sẽ không được sửa đổi khi chỉnh sửa thực thể của bạn.
Giải pháp của tôi là:
public function buildForm(FormBuilderInterface $builder, array $options) {
// In my example, data is an associated array
$data = $builder->getData();
$builder->add('myfield', 'text', array(
'label' => 'Field',
'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
));
}
Tạm biệt.
'data' => $data['myfield'] ?? 'Default value',
Giá trị mặc định được đặt bằng cách định cấu hình thực thể tương ứng. Trước khi ràng buộc thực thể để hình thành, đặt trường màu của nó thành "# 0000FF":
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Nếu trường đó được liên kết với một thực thể (là một thuộc tính của thực thể đó), bạn có thể chỉ cần đặt một giá trị mặc định cho nó.
Một ví dụ:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Tôi thường chỉ đặt giá trị mặc định cho trường cụ thể trong thực thể của mình:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
Điều này sẽ làm việc cho các hồ sơ mới hoặc nếu chỉ cập nhật những hồ sơ hiện có.
'empty_data'
một cuộc gọi lại được sử dụng để cho phép các tham số hàm tạo trên thực thể.
Như Brian đã hỏi:
Empty_data dường như chỉ đặt trường thành 1 khi nó được gửi không có giá trị. Còn khi bạn muốn biểu mẫu mặc định hiển thị 1 trong đầu vào khi không có giá trị thì sao?
bạn có thể đặt giá trị mặc định với empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])