daa/addressable-bundle

此包的最新版本(0.6.0)没有提供许可证信息。

Symfony扩展包,用于使实体可寻址以及提供地理空间服务以搜索和比较它们的经纬度

安装次数: 12,564

依赖项: 0

建议者: 0

安全: 0

星标: 6

关注者: 3

分支: 11

类型:symfony-bundle

0.6.0 2022-06-17 07:35 UTC

This package is not auto-updated.

Last update: 2024-09-20 18:23:43 UTC


README

Build Status

Symfony Addressable Bundle

这是一个Symfony扩展包,用于简化实体的可寻址性和地理定位。

它包含一个谷歌地图表单类型,用于搜索和设置地址(带有纬度/经度),并提供地理空间服务,以简化使用这些经纬度对象进行距离计算、排序和筛选等操作。

Symfony 5/6 安装

将以下内容添加到 composer.json 中

"require": {
    ...
    "daa/addressable-bundle": "^0.6"
}

在 config/bundles.php 中注册该扩展包

return [
    ...
    Addressable\Bundle\AddressableBundle::class => ['all' => true]
]

在 config/packages/twig.yml 中包含类型布局的twig模板

twig:
    default_path: '%kernel.project_dir%/templates'
    form_themes:
        - '@Addressable/Form/fields.html.twig'

Symfony 2/3 安装

将以下内容添加到 composer.json 中

"require": {
    ...
    "daa/addressable-bundle": "0.5"
}

在 app/AppKernel.php 中注册该扩展包

new Addressable\Bundle\AddressableBundle(),

在 app/config/config.yml 中包含类型布局的twig模板

twig:
    form_themes:
          - '@Addressable/Form/fields.html.twig' # or AddressableBundle:Form:fields.html.twig in older versions of symfony

用法

现在您的实体或文档必须

  1. 实现包含的 AddressableInterface
  2. 使用相关的特性(ORM或PHPCR版本)或手动复制所需字段、获取器和设置器
    namespace Your\Project\Entity;

    use Addressable\Bundle\Model\AddressableInterface;
    use Addressable\Bundle\Model\Traits\ORM\AddressableTrait;
    # for optional email, tel, fax fields also include and use these
    use Addressable\Bundle\Model\ContactableInterface;
    use Addressable\Bundle\Model\Traits\ORM\ContactableTrait;

    class YourEntity implements AddressableInterface, ContactableInterface
    {
        use AddressableTrait;
        use ContactableTrait;
        
        /**
         * @ORM\Column(type="text")
         */
        protected $yourOtherField;
        
        ...
    }

注意,如果您使用的是不支持特性的旧版PHP,则必须手动将特性代码复制到实体中。

一旦设置好实体,我们可以以下方式将地址地图选择器添加到表单中

use Addressable\Bundle\Form\Type\AddressMapType;
use Addressable\Bundle\Form\Type\ContactDetailsType; # optional email, tel, fax

// if you are using standard symfony form type
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('address', AddressMapType::class, array(
            'google_api_key' => 'yourKeyHere'
        ))
    ...
}

// if you are using Sonata Admin
protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->with('Location')
            ->add('address', AddressMapType::class, array(
                'google_api_key' => 'yourKeyHere'
            ))
        ->end()
        ...
}

/**
 * if you are doing it directly in a controller Action
 * 
 * @Route("/", name="homepage")
 * @Template("@App/page.html.twig")
 */
public function indexAction(Request $request)
{
    $entity = new AddressableEntity();
    $form = $this->createForm(AddressMapType::class, $entity, array(
        'google_api_key' => 'yourKeyHere'
    ));
    
    /* or alternatively when using the nested/related versions:
    $form = $this->createFormBuilder($entity)
        ->add('address', AddressMapType::class, array(
            'google_api_key' => 'yourKeyHere'
        ))
        ->add('contactDetails', ContactDetailsType::class)
        ->getForm();
    */

    // replace this example code with whatever you need
    return [
        'form' => $form->createView(),
    ];
}

注意:如果使用地址作为子项或关系,请记得设置'data_class'选项指向Address对象。

选项

我们可以覆盖多个选项

->add(
    'address',
     AddressMapType::class,
     array(
        'google_api_key' => 'yourKeyHere',
         'map_width' => '100%',    // the width of the map
         'map_height' => '300px',  // the height of the map
         'default_lat' => 51.5,    // the starting position on the map
         'default_lng' => -0.1245, // the starting position on the map
         'include_current_position_action' => true, // whether to include the set current position button
         'street_number_field' => array(
             'name' => 'streetNumber',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'street_name_field' => array(
             'name' => 'streetName',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'city_field' => array(
             'name' => 'city',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'zipcode_field' => array(
             'name' => 'zipCode',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'country_field' => array(
             'name' => 'country',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'latitude_field' => array(
             'name' => 'latitude',
             'type' => 'hidden',
             'options' => array(
                 'required' => false
             )
         ),
         'longitude_field' => array(
             'name' => 'longitude',
             'type' => 'hidden',
             'options' => array(
                 'required' => false
             )
         ),
         'administrative_area_level_1_field' => array(
             'name' => 'administrativeAreaLevel1',
             'type' => 'text',
             'options' => array(
                 'required' => false
             )
         ),
         'administrative_area_level_2_field' => array(
             'name' => 'administrativeAreaLevel2',
             'type' => 'text',
             'options' => array(
                 'required' => false
             )
         )
     )
);

# And same for the optional contact details fields
->add(
    'contactDetails',
    ContactDetailsType:class,
    array(
        'email_field' => array(
            'name' => 'email',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
        'phone_field' => array(
            'name' => 'phoneNumber',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
        'fax_field' => array(
            'name' => 'fax',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
    )
);

国家特性

如果您为"country_field"使用"country"类型(Symfony\Component\Form\Extension\Core\Type\CountryType),地理空间辅助程序将使用谷歌返回的短码填充下拉列表中的国家短码。

进一步自定义

如果您不希望该扩展包使用自己的脚本,可以覆盖 address_map_scripts 块为空;然后将 vendor/daa/addressable-bundle/Resources/public/js/address_map.js 中的javascript复制并粘贴到您的js文件中。

要在地址更新后添加额外功能,只需覆盖 address_map_callback 块并扩展以添加额外功能(或将其留空并在js代码中定义 var gmap_callback)。

    {% block address_map_callback %}
        <script>
            var gmap_callback = function(location, gmap){
                // your callback code here
            }
        </script>
    {% endblock %}

截图

Sonata实现

View screenshot

地理空间辅助服务

您可以从控制器中获取 addressable_bundle.geospatial_helper 服务;从其他任何地方,您可以直接实例化 GeospatialHelper 类。

示例

  public function symfonyControllerAction()
  {
      $helper = $this->get('addressable_bundle.geospatial_helper');

      $centerPoint = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $point1 = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $point2 = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $points = array($point1, $point2);

      // getting distance in KM between two points
      $distanceInKm = $helper->getDistanceBetweenPoints($point1, $point2);

      // filtering an array of points by radius from a center point
      $pointsWithinRadius = $helper->filterPointsWithinRadius($centerPoint, $points, $radius);

      // sort an array of addressable objects to be ordered by distance from a center point
      $orderedPoints = $helper->sortAroundCenterPoint($centerPoint, $points);
  }