vendredi 26 avril 2019

Using adapter pattern when consuming 3rd party APIs and creating a domain in Laravel

In my Laravel REST API project I mainly consume 3rd party APIs. For that, I have a 'Services' folder grouped by APIs (Accommodation, Planning, Discount etc) to send correct parameters to APIs and get the raw data.

I feel that I need to use adapter pattern here, because this 3rd party outputs need to be formatted.

Let me try to give an example.

I have an EventDao interface (Data access object) and one or multiple concrete EventDao classes like EventbriteDao.

I also have an adapter for each concrete DAO. e.g: EvenbriteAdapter

I will have some business logic somewhere so I need to have an Event entity class. To pass the adapter's data to the entity, I need an EventDTO class (data transfer object)

Finally I can call the eventDao (via interface thanks to Laravel's service providers)

I pass its raw output to the adapter, then adapter's output to the entity. Then I can call one of methods of the entity class. (After that I need to convert it to a proper json data, but it is the easy part.)

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.

Would it be a good approach or over-engineering? Because I have 5-6 classes/interfaces other than controller.

Another problem is calling EventbriteAdapter directly in the controller. Should I have an interface for it? In this case I will need to bind both service and adapter interfaces to its implementations in AppServiceProvider.

Here example codes for some of the files I mentioned are:

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);

1 commentaire: