Модуль представляет из себя набор классов:
- AbstractPostService.php - абстрактный класс, который наследуется парсером каждой службы (ServiceFI.php, ServiceNL.php и ServiceSG.php)
- ParseHelper.php - класс, в котором реализовано 2 метода для отправления curl запроса, и возвращения ответа - parse_post() и parse_get()
- SearchTrack.php - непосредственно класс, с которым работает модель трекинга
- ServiceFI.php, ServiceNL.php и ServiceSG.php - классы, характеризующие алгоритмы парсинга каждого сервиса, наследуются от AbstractPostService.php
Дальше приведу код:
AbstractPostService.php:
(метод isAvailable() публичный, чтобы была возможность реализовать простое правило валидации в модели)
Код: Выделить всё
<?php
namespace app\modules\tracking\classes;
use Yii;
abstract class AbstractPostService
{
/*
Абстрактный метод, возвращаемое значение - массив с данными об отправлении.
*/
abstract public function getResult($track);
/*
Метод для перевода статуса, используется google api.
*/
public static function translateText($text)
{
if(Yii::$app->params['googleTranslate']['active'] == false)
{
return '-';
}
$text = rawurlencode($text);
$apiKey = Yii::$app->params['googleTranslate']['key'];
$apiLink = 'https://www.googleapis.com/language/translate/v2?key='.$apiKey.'&q='.$text.'&source=en&target=ru';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $apiLink);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$rawResponse = curl_exec($curl);
curl_close($curl);
$response = json_decode($rawResponse);
if(isset($response->data->translations[0]->translatedText))
{
return $response->data->translations[0]->translatedText;
}
else
{
return '-';
}
}
}
Код: Выделить всё
<?php
namespace app\modules\tracking\classes;
/*
Класс-помощник, предоставляет упрощенный интерфейс парсинга страницы.
*/
class ParseHelper
{
//Метод для парсинга пост-запросом
public static function parse_post($url, $params){
if( $curl = curl_init() ) {
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
$out = curl_exec($curl);
curl_close($curl);
return $out;
}
}
//Метод для парсинга гет-запросом
public static function parse_get($url){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
$out = curl_exec($curl);
curl_close($curl);
return $out;
}
}
Код: Выделить всё
<?php
namespace app\modules\tracking\classes;
use Yii;
/*
Используется для получения информации о почтовом управлении.
*/
class SearchTrack
{
// непосредственно текстовое значение "трек-номера"
private $track_number;
public function __construct($track_number)
{
$this->track_number = $track_number;
}
/*
Метод проверяет существует ли стратегия для данного типа трек-номера.
*/
public function isAvailable()
{
$type = $this->getType(); // get type
if(!class_exists($this->getServiceName())) //check if service exists
{
return false;
}
return true;
}
/**
* Метод, используется для поиска информации по предоставленному трек-номеру.
* Используется идентификатор отпарвления (track_number), переданный в конструкторе.
* Результат возвращается в виде массива PHP
*/
public function getParcelInfo()
{
if($this->isAvailable())
{
$serviceName = $this->getServiceName();
$service = new $serviceName();
$result = $this->getArrayInfo($service);
return $result;
}
return false;
}
/*
Метод для непосредственного поиска информации об отправлении по предоставленному алгоритму
*/
private function getArrayInfo(AbstractPostService $service)
{
return $service->getResult($this->track_number);
}
/*
Метод для определения типа отправления.
Может быть расширен при добавлении нового типа трека.
На данный момент тип получается путем получения двух последних символов:
***FI - тип "FI" и т.д.
*/
private function getType()
{
//return 2 last characters of the track number
return substr($this->track_number, strlen($this->track_number)-2, 2);
}
/*
Метод для получения полного имени класса сервиса (алгоритма).
*/
private function getServiceName()
{
$type = $this->getType();
$serviceName = '\Service'.$type;
$serviceModel = __NAMESPACE__.$serviceName;
return $serviceModel;
}
}
Код: Выделить всё
<?php
namespace app\modules\tracking\classes;
use app\modules\tracking\classes\AbstractPostService;
use app\modules\tracking\classes\ParseHelper;
/*
Класс-алгоритм, используемый для поиска информации для треков с типом "FI"(финляндия)
*/
class ServiceXX extends AbstractPostService
{
public function getResult($track)
{
//код непосредственно парсинга и формирование массива
return $result;
}
}
Код: Выделить всё
...
$searchTrack = new SearchTrack($this->trackNumber);
$searchResults = $searchTrack->getParcelInfo();
...
Мне на данный момент не очень нравится переводчик статусов хранить в сервиске, но с другой стороны это лишь одна функция, и создавать отдельный класс для нее было-бы излишним.
Что скажите насчет такого подхода? И можно ли данный подход назвать фабрикой?