3

抛开政治不谈,我在选择国家时需要提供科索沃作为一种形式选择。

使用 Symfony 的内置表单选择类型country,同时还提供科索沃名称的翻译,最优雅的方式是什么?

这是我到目前为止所做的并且它有效,但我担心这可能有点hack-ish。

<?php

namespace Acme\Bundle\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Intl\Intl;

class LocationType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Kosovo is not listed as a choice provided by the method call
        // `Symfony\Component\Intl\Intl::getRegionBundle()->getCountryNames()`
        // although it is mostly recognized as in independent state, including by Google Maps.
        // This is because no ISO 3166-1 alpha-2 code as been assigned to that country.
        // However, a temporary code 'XK' is available.

        $countries = Intl::getRegionBundle()->getCountryNames();
        $countries['XK'] = "Kosovo";

        $builder
            ->add('country', 'country', array(
                'choices' => $countries,
                'preferred_choices' => array(
                    'XK', // Kosovo
                    'AL', // Albania
                    'MK', // Macedonia
                    'ME', // Montenegro
                    'GB', // United Kingdom
                    'US', // United States
                ),
            ))
            ->add('district', 'text', array('required' => false))
            ->add('town', 'text', array('required' => false))
        ;
    }
}
4

2 回答 2

2

您应该创建您的服务,使用Intl's static 方法(如上)并添加您的自定义国家。然后,将该服务注入您的表单类型。或者(甚至更好),定义您的自定义类型(例如“MyCountry”)并使用它而不是标准类型country

于 2014-07-01T13:15:15.060 回答
0

我还需要将科索沃添加到我的项目的国家列表中,并且此线程中的任何答案都没有用。我为 Symfony 5 提出了一个可行的解决方案:

在您的树枝中,您应该有一个表单,并且国家/地区表单字段应呈现如下:

{{ form_row(form.field_country, {'attr': {'novalidate': 'novalidate', 'class' : 'novalidate' }}) }}

在 Controller 中,该字段的创建方式如下:

->add('field_country', CountryType::class, ['label' => '*Country', 'required' => false  ])

如果上述内容不清楚,请查阅 Symfony 文档以了解表单创建/处理。

现在您必须找到一个名为“CountryType.php”的文件。找到它可能会很棘手,因为它被埋得很深,就我而言,它位于以下位置:

vendor -> symfony -> form -> Extension -> Core -> Type -> CountryType.php

找到以下行:

return array_flip($alpha3 ? Countries::getAlpha3Names($choiceTranslationLocale) : Countries::getNames($choiceTranslationLocale) );

此行生成 CountryType::class 使用的所有国家/地区。

此返回声明需要修改,以便为您提供一个新的扩展国家列表,其中还包括科索沃。为此,您需要获取国家的关联数组,在位置 188(字母 K)处对其进行切片,插入科索沃,然后再次合并数组。

要实现上述目的,请将 IntlCallbackChoiceLoader 函数的整个代码替换为:

  return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3) {

//Get list of courtries from the API with array keys given with 3 letters
$countriesByAlpha3 = Countries::getAlpha3Names($choiceTranslationLocale);
//Splice the original array, insert Kosovo in correct alphabetical order with a 3 letter key, and merge the array again
$countriesByAlpha3 = array_merge(array_slice($countriesByAlpha3, 0, 118), array('XKX' => 'Kosovo'), array_slice($countriesByAlpha3, 118));

//Get list of courtries from the API with array keys given with 2 letters
$countriesByName = Countries::getNames($choiceTranslationLocale);   
//Splice the original array, insert Kosovo in correct alphabetical order with a 2 letter key, and merge the array again     
$countriesByName = array_merge(array_slice($countriesByName, 0, 118), array('KX' => 'Kosovo'), array_slice($countriesByName, 118));
          
               // return array_flip($alpha3 ? Countries::getAlpha3Names($choiceTranslationLocale) : Countries::getNames($choiceTranslationLocale) );
return array_flip( $alpha3 ?  $countriesByAlpha3 :  $countriesByName   );


            });
于 2020-11-25T15:45:27.290 回答