Как настроить класс обслуживания для использования BazingaGeocoderBundle с Symfony 3.4 - PullRequest
0 голосов
/ 10 сентября 2018

Я работаю над приложением, созданным с использованием 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 для успешного геокодирования адресов.

Согласно документации пакета, я добавил следующее в свой myproject / src /Файл app / config / config.yml:

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

Я понимаю, что должен иметь возможность вызывать GoogleMapsProvider из контейнера службы, но мой класс обслуживания (OutletScraper) не имеет доступа к контейнеру службы.Должно ли указываться в качестве аргумента в конфигурации OutletScraper?

Спасибо, если кто-нибудь поможет мне лучше понять эту тему.

1 Ответ

0 голосов
/ 10 сентября 2018

Должно ли указываться в качестве аргумента в конфигурации 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 в конфигурацию вашей службы.Возможно, даже лучше: переместите эти переменные в область действия метода, чтобы каждый вызов перезаписывал их.

Таким образом, чтобы лучше использовать Dependency Injection, ваш класс может выглядеть примерно так:

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-адреса, с которым она используется.Необходимость какого-либо из этих изменений зависит от вашей реализации, поэтому вносите эти изменения с осторожностью.

...