我正在使用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配置中将其指定为参数吗?
感谢是否有人可以帮助我更好地理解这个主题。
应该在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创建多个实例。是否需要进行任何更改取决于您的实施,因此请谨慎进行这些更改。