首页 文章

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

提问于
浏览
0

我正在使用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,我正确地安装了捆绑包,因为我能够使用命令: 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配置中将其指定为参数吗?

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

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创建多个实例 . 是否需要进行任何更改取决于您的实施,因此请谨慎进行这些更改 .

相关问题