使用第 3 方 API 并在 Laravel 中创建域时使用适配器模式
Using adapter pattern when consuming 3rd party APIs and creating a domain in Laravel
在我的 Laravel REST API 项目中,我主要使用第 3 方 API。为此,我有一个按 APIs(住宿、计划、折扣等)分组的“Services”文件夹,用于向 APIs 发送正确的参数并获取原始数据。
我觉得我需要在这里使用适配器模式,因为这个 3rd 方输出需要格式化。
让我试着举个例子。
我有一个 EventDao 接口(数据访问对象)和一个或多个具体的 EventDao classes,例如 EventbriteDao。
对于每个具体的 DAO,我还有一个 适配器。例如:EvenbriteAdapter
我将在某处有一些业务逻辑,所以我需要一个事件 实体 class。要将适配器的数据传递给实体,我需要一个 EventDTO class (数据传输对象)
我终于可以调用 eventDao(通过接口感谢 Laravel 的服务提供商)
我将其原始输出传递给适配器,然后将适配器的输出传递给实体。然后我可以调用实体 class 的方法之一。 (之后我需要将其转换为适当的 json 数据,但这是简单的部分。)
我不知道在哪里放置其他 CRUD 逻辑,如 updateEvent、deleteEvent、getAll 等。我应该直接在控制器中调用它们还是创建存储库(存储库模式)?我对此感到困惑。
这是一个好方法还是过度设计?因为除了controller我还有5-6个classes/interfaces
另一个问题是直接在控制器中调用EventbriteAdapter。我应该有一个接口吗?在这种情况下,我需要将服务和适配器接口绑定到 AppServiceProvider 中的实现。
我的另一个问题是实体块的集合。如果我调用 getAll() 方法,我可以遍历数据并创建一个对象数组,但我对此并不满意。 Laravel 的集合会很有用,但我想将应用程序层与域分开。什么是好的解决方案?
这里我提到的一些文件的示例代码是:
interface EventAdapter
{
public function getId();
public function getName();
public function getStartDate();
public function getLocationName();
}
class EventbriteAdapter implements EventInterface
{
private $raw;
public function __construct(array $raw)
{
$this->raw = $raw;
}
public function getName()
{
return $this->raw['name'];
}
public function getStartDate()
{
return $this->raw['start'];
}
public function getLocation()
{
return $this->raw['venue']['name'].' '.$this->raw['venue']['address'];
}
}
// Fetch event from Eventbrite (or other third-party)
$result = fetchEventFromEventbrite();
// Wrap event in adapter
$adapter = new EventbriteAdapter($result);
I don't get where to put other CRUD logic like updateEvent,
deleteEvent, getAll etc. Should I call them directly in controller or
create repositories (the repository pattern)? I am confused about it.
您可以使用the Gateway pattern封装所有与第3方交互的逻辑API。网关可以包含获取数据和保存数据的方法。例如:
interface EventGatewayInterface
{
/**
* Get an event by id
*
* @param mixed $id unique identifier of an event
* @return Event the event
*/
public function getById($id);
/**
* Get all events
*
* @return Event[] list of events
*/
public function getAll();
/**
* Add an event
*
* @param Event $event the event which will be added
*/
public function add(Event $event);
/**
* Update an event
*
* @param Event $event the event which will be updated
*/
public function update(Event $event);
/**
* Delete an event
*
* @param Event $event the event which will be removed
*/
public function delete();
}
Would it be a good approach or over-engineering? Because I have 5-6
classes/interfaces other than controller.
其实你用的是the Adapter pattern to translate one representation (raw representation) to another (object representation). But the Adapter pattern is used to translate one program interface into a compatible program interface. To convert representations used the Mapper pattern。您可以实现简单的映射器,例如:
class RawEventMapper
{
/**
* Map raw data to an event object
*
* @param array $data raw data
* @return Event the event object
*/
public function map(array $data)
{
$event = new Event();
$event->name = $data['name'];
$event->startDate = $data['start'];
$event->location = $data['venue']['name'].' '.$data['venue']['address'];
return $event;
}
}
并在 Gateway 中使用它来将原始数据转换为对象。
class ConcreteEventGateway implement EventGatewayInterface
{
/** @var RawEventMapper data mapper */
protected $mapper;
/**
* Constructor
*
* @param RawEventMapper $mapper data mapper
*/
public function __construct(RawEventMapper $mapper)
{
$this->mapper = $mapper;
}
/** @inheritdoc */
public function getById($id)
{
// get raw data from 3rd party API
return $this->mapper->map($raw);
}
}
Laravel's collections would be useful, but I want to separate
application layer from domain. What would be a good solution for it?
如果您打算创建一个独立于框架的域层,则不应使用 Laravel 集合。
在我的 Laravel REST API 项目中,我主要使用第 3 方 API。为此,我有一个按 APIs(住宿、计划、折扣等)分组的“Services”文件夹,用于向 APIs 发送正确的参数并获取原始数据。
我觉得我需要在这里使用适配器模式,因为这个 3rd 方输出需要格式化。
让我试着举个例子。
我有一个 EventDao 接口(数据访问对象)和一个或多个具体的 EventDao classes,例如 EventbriteDao。
对于每个具体的 DAO,我还有一个 适配器。例如:EvenbriteAdapter
我将在某处有一些业务逻辑,所以我需要一个事件 实体 class。要将适配器的数据传递给实体,我需要一个 EventDTO class (数据传输对象)
我终于可以调用 eventDao(通过接口感谢 Laravel 的服务提供商)
我将其原始输出传递给适配器,然后将适配器的输出传递给实体。然后我可以调用实体 class 的方法之一。 (之后我需要将其转换为适当的 json 数据,但这是简单的部分。)
我不知道在哪里放置其他 CRUD 逻辑,如 updateEvent、deleteEvent、getAll 等。我应该直接在控制器中调用它们还是创建存储库(存储库模式)?我对此感到困惑。
这是一个好方法还是过度设计?因为除了controller我还有5-6个classes/interfaces
另一个问题是直接在控制器中调用EventbriteAdapter。我应该有一个接口吗?在这种情况下,我需要将服务和适配器接口绑定到 AppServiceProvider 中的实现。
我的另一个问题是实体块的集合。如果我调用 getAll() 方法,我可以遍历数据并创建一个对象数组,但我对此并不满意。 Laravel 的集合会很有用,但我想将应用程序层与域分开。什么是好的解决方案?
这里我提到的一些文件的示例代码是:
interface EventAdapter
{
public function getId();
public function getName();
public function getStartDate();
public function getLocationName();
}
class EventbriteAdapter implements EventInterface
{
private $raw;
public function __construct(array $raw)
{
$this->raw = $raw;
}
public function getName()
{
return $this->raw['name'];
}
public function getStartDate()
{
return $this->raw['start'];
}
public function getLocation()
{
return $this->raw['venue']['name'].' '.$this->raw['venue']['address'];
}
}
// Fetch event from Eventbrite (or other third-party)
$result = fetchEventFromEventbrite();
// Wrap event in adapter
$adapter = new EventbriteAdapter($result);
I don't get where to put other CRUD logic like updateEvent, deleteEvent, getAll etc. Should I call them directly in controller or create repositories (the repository pattern)? I am confused about it.
您可以使用the Gateway pattern封装所有与第3方交互的逻辑API。网关可以包含获取数据和保存数据的方法。例如:
interface EventGatewayInterface
{
/**
* Get an event by id
*
* @param mixed $id unique identifier of an event
* @return Event the event
*/
public function getById($id);
/**
* Get all events
*
* @return Event[] list of events
*/
public function getAll();
/**
* Add an event
*
* @param Event $event the event which will be added
*/
public function add(Event $event);
/**
* Update an event
*
* @param Event $event the event which will be updated
*/
public function update(Event $event);
/**
* Delete an event
*
* @param Event $event the event which will be removed
*/
public function delete();
}
Would it be a good approach or over-engineering? Because I have 5-6 classes/interfaces other than controller.
其实你用的是the Adapter pattern to translate one representation (raw representation) to another (object representation). But the Adapter pattern is used to translate one program interface into a compatible program interface. To convert representations used the Mapper pattern。您可以实现简单的映射器,例如:
class RawEventMapper
{
/**
* Map raw data to an event object
*
* @param array $data raw data
* @return Event the event object
*/
public function map(array $data)
{
$event = new Event();
$event->name = $data['name'];
$event->startDate = $data['start'];
$event->location = $data['venue']['name'].' '.$data['venue']['address'];
return $event;
}
}
并在 Gateway 中使用它来将原始数据转换为对象。
class ConcreteEventGateway implement EventGatewayInterface
{
/** @var RawEventMapper data mapper */
protected $mapper;
/**
* Constructor
*
* @param RawEventMapper $mapper data mapper
*/
public function __construct(RawEventMapper $mapper)
{
$this->mapper = $mapper;
}
/** @inheritdoc */
public function getById($id)
{
// get raw data from 3rd party API
return $this->mapper->map($raw);
}
}
Laravel's collections would be useful, but I want to separate application layer from domain. What would be a good solution for it?
如果您打算创建一个独立于框架的域层,则不应使用 Laravel 集合。