如何配置服务类以将BazingaGeocoderBundle与Symfony 3.4一起使用

问题描述 投票:0回答:1

我正在使用Symfony 3.4构建的应用程序。我有以下服务类(myproject / src / AppBundle / Utils / OutletScraper.php):

<?php 
// src/AppBundle/Utils/OutletScraper.php
namespace AppBundle\Utils;

use Goutte\Client;
use GuzzleHttp\Client as GuzzleClient;

class OutletScraper
{
    private $url;
    public $outlets;
    public $abnormalFormatOutlets;

    public function __construct($url = null)
    {
        $this->url                      = $url;
        $this->outlets                  = [];
        $this->abnormalFormatOutlets    = [];
    }

    private function geocodeAddress()
    {

    }
}

我在这个类中有一些其他的方法,我省略了。此服务类的配置位于(myproject / src / app / config / services.yml)中,如下所示:

AppBundle\Utils\OutletScraper:
    public: false

我可以毫无问题地使用该服务(我已经在命令中实现了它)。

我现在正致力于在应用程序中实现地理编码功能。我已经安装了BazingaGeocoderBundle,我很难理解如何将它集成到我的服务类(OutletScraper.php)中,以便我可以对地址进行地理编码。我相信我已经正确安装了捆绑包,因为我能够使用命令:php bin/console geocoder:geocode来成功地对地址进行地理编码。

根据bundle文档,我在myproject / src / app / config / config.yml文件中添加了以下内容:

bazinga_geocoder:
    providers:
        acme:
            factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory
            options:
                api_key: 'myapikey'

我知道我应该能够从服务容器调用GoogleMapsProvider,但我的服务类(OutletScraper)无法访问服务容器。应该在OutletScraper配置中将其指定为参数吗?

感谢是否有人可以帮助我更好地理解这个主题。

php symfony service geocoding
1个回答
1
投票

应该在OutletScraper配置中将其指定为参数吗?

是的,但您还必须将其作为参数添加到构造函数中。

所以你的课应该是这样的:

use Geocoder\Provider\Provider;

class OutletScraper
{
    private $url;
    private $geocodingProvider;
    public $outlets;
    public $abnormalFormatOutlets;

    public function __construct(Provider $geocodingProvider, $url = null)
    {
        $this->geocodingProvider        = $geocodingProvider;
        $this->url                      = $url;
        $this->outlets                  = [];
        $this->abnormalFormatOutlets    = [];
    }

    private function geocodeAddress()
    {
         $this->geocodingProvider->geocodeQuery(...);
    }
}

然后您的配置可能看起来像这样:

AppBundle\Utils\OutletScraper:
    public: false
    arguments:
        $geocodingProvider: '@bazinga_geocoder'
        $url: ~ # represents null (also default), but can be replaced with any url string

我不知道URL是否适用,但是当这种情况发生很大变化时,您可能需要为每个URL创建多个服务,或者稍后将其传递给公共方法。这可能不是问题,但有时很难看出服务的哪个部分实际上不是服务定义的一部分,导致复杂的解决方法,这就是我提出这个问题的原因。如果这是地理编码服务的IP,您可能根本不需要它,因为这已经在您从服务容器获取的提供程序中定义。

您的服务的另一个问题是2个公共属性$outlets$abnormalFormatOutlets。您的服务将在调用之间保留这些值,这可能会在您调用方法时导致问题,并且它会重用以前的值而不需要它。您可以做的是确保每个OutletScraper注入某个地方都会获得一个新实例,换句话说,通过将shared: false添加到您的服务配置中不再共享该服务。可能更好:在方法范围内移动这些变量,以确保每个调用都覆盖它们。

因此,为了更好地使用依赖注入,您的类可能看起来像这样:

use Geocoder\Provider\Provider;

class OutletScraper
{
    private $url;
    private $geocodingProvider;

    public function __construct(Provider $geocodingProvider)
    {
        $this->geocodingProvider = $geocodingProvider;
    }

    private function geocodeAddress($url = null)
    {
         $outlets = [];
         $abnormalFormatOutlets = [];

         $this->geocodingProvider->geocodeQuery(...);
         ...
    }
}

公共属性不会在方法调用之间存储在类中,从而降低过时数据产生错误结果的可能性。该服务不再依赖于url,需要为与其一起使用的每个url创建多个实例。是否需要进行任何更改取决于您的实施,因此请谨慎进行这些更改。

© www.soinside.com 2019 - 2024. All rights reserved.