gfg / hek
Hek plugin to provide integration between your webservices (service gateway pattern)
Installs: 9 042
Dependents: 2
Suggesters: 0
Security: 0
Stars: 2
Watchers: 9
Forks: 0
Open Issues: 0
Requires
- gfg/dto-context: 1.0.*
- gfg/dto-url: 1.0.*
- guzzlehttp/guzzle: 6.0.*
- psr/log: 1.0.*
Requires (Dev)
- pdepend/pdepend: @stable
- phploc/phploc: @stable
- phpmd/phpmd: @stable
- phpunit/php-invoker: @stable
- phpunit/phpunit: @stable
- sebastian/phpcpd: @stable
- squizlabs/php_codesniffer: @stable
- sstalle/php7cc: @stable
README
INTRODUCTION
Communication between services is never an easy task. Aiming to facilitate and keep things consistent, Hek makes use of the context-oriented datawrapper library DTO-Context to ensure the data integrity and normalization, and still be flexible enough to be applied to any kind of service.
CONCEPT
The concept is pretty simple: create your data entities (dataWrappers); map the actions that your service does and create a context for each of them. After that you can let Hek take care to deliver the information to the responsible component.
Hek is a library that contains the base files to implement the thin communication layer that will use specific contexts. It's based on a Service Gateway Pattern and a good example of implementation is the Hek-Marketplace that uses DTO-Marketplace
STRUCTURE
Exceptions //All the exceptions used in the library
├─ InvalidInput.php //Malformed Json
├─ MethodNotAllowed.php //When a service method that doesn't exist is requested
├─ ResponseInteface.php //Interface that all Hek implementations exceptions must implement
└─ RetryMessage.php //Exception used by the ApiClient
Interfaces //All the interfaces needed to create a Hek implementation
├─ Configuration.php //Some configurations needed for Hek to work properly
├─ Context.php //What is expected for a context to be used by Hek
└─ ServiceFactory.php //Hek must know how to create your services
ApiClient.php //Client that handles HTTP requests
CommandBus.php //Proxies the commands to the responsible objects
Manager.php //Handle the dependencies
EXAMPLE OF USE
As mentioned above, the library is a base library to develop a layer of communication for a specific service (Service Gateway). We will use an example of service that creates a person, update the person's name and receive a creation confirmation. We will call it MyHek.
To do so we need to follow the steps below:
- Create the DataWrappers;
- The Contexts;
- The Service factory;
- The Services;
- The Context factory.
Example 1: Implementing directly (without separating it in a composable library)
Proposed Structure
MyHek
Datawrappers
└─ Person.php
Contexts
├─ Person
├─ Create.php
└─ UpdateName.php
└─ ConfirmCreate.php
└─Factory.php
Services
├─ Configuration.php
├─ Manager.php
└─ Person.php
└─ Factory.php
1 DataWrapper
<?php namespace MyHek\DataWrapper; use GFG\DTOContext\DataWrapper\Base; /** * @SuppressWarnings(PHPMD.UnusedPrivateField) * @method string getName() * @method integer getHeight() * @method integer getWeight() * @method integer getAge() * @method string getNationality() * @method \MyHek\DataWrapper\Person setName(string $name) * @method \MyHek\DataWrapper\Person setHeight(integer $height) * @method \MyHek\DataWrapper\Person setWeight(integer $weight) * @method \MyHek\DataWrapper\Person setAge(integer $age) * @method \MyHek\DataWrapper\Person setNationality(string $nationality) */ class Person extends Base { private $name; private $height; private $weight; private $age; private $nationality; }
2. Contexts
CreatePerson Context
<?php namespace MyHek\Context\Person; use GFG\Hek\Interfaces\Context as HekContext; use GFG\DTOContext\Context\Base as BaseContext; class Create extends BaseContext implements HekContext { public function getHttpMethod() { return 'post'; } public function getUrl() { return 'create-person'; } /** * In this method, we'll use only the data that is needed for * this action */ public function exportContextData() { $dataWrapper = $this->getDataWrapper(); return $this->prepareExport([ 'name' => $dataWrapper->getName(), 'height' => $dataWrapper->getHeight(), 'weight' => $dataWrapper->getWeight(), 'age' => $dataWrapper->getAge(), 'nationality' => $dataWrapper->getNacionality() ]); } }
UpdateName context
<?php namespace MyHek\Context\Person; use GFG\Hek\Interfaces\Context as HekContext; use GFG\DTOContext\Context\Base as BaseContext; class UpdateName extends BaseContext implements HekContext { public function getHttpMethod() { return 'put'; } public function getUrl() { return 'update-name'; } public function exportContextData() { $dataWrapper = $this->getDataWrapper(); return $this->prepareExport([ 'name' => $dataWrapper->getName() ]); } }
ConfirmCreation
<?php namespace MyHek\Context\Person; use GFG\Hek\Interfaces\Context as HekContext; use GFG\DTOContext\Context\Base as BaseContext; class ConfirmCreate extends BaseContext implements HekContext { public function getHttpMethod() { return 'put'; } public function getUrl() { return 'confirm-create'; } public function exportContextData() { $dataWrapper = $this->getDataWrapper(); return $this->prepareExport([ // ... ]); } }
3. Service Factory
<?php namespace MyHek; class Factory implements GFG\Hek\Interfaces\ServiceFactory { public function build(GFG\Hek\Interfaces\Context $context) { $parts = array_slice(explode('.', $context->getName()), -2, 1); // ['Person'] $className = ucfirst(current($parts)); // Person $serviceName = "\MyHek\Services\{$className}"; return new $serviceName; } }
4. Services
Configuration
<?php namespace MyHek\Services; use GFG\Hek\Interfaces; class Configuration implements Interfaces\Configuration { public function isEnabled() { return true; } public function getUserKey() { return 'myUserKey'; } public function getBaseUrl() { return 'http://person.service.com'; } public function getAccessToken() { return 'access token'; } public function getHttpUser() { return 'user'; // or false } public function getHttpPass() { return 'password'; // or false } }
5. Context Factory
<?php namespace MyHek\Context; use GFG\Hek\DTO-Context\Factory\Base as BaseFactory; class Factory extends BaseFactory { const PERSON_CREATE = 'person.create'; const PERSON_UPDATENAME = 'person.updatename'; const PERSON_CONFIRMCREATE = 'person.confirmcreate'; protected static $mappedContext = [ self::PERSON_CREATE => 'MyHek\Context\Person\Create', self::PERSON_UPDATENAME => 'MyHek\Context\Person\UpdateName', self::PERSON_CONFIRMCREATE => 'MyHek\Context\Person\ConfirmCreate' ]; public function getMappingList() { return self::$mappedContext; } }
Sending a request
<?php use MyHek\Context\Factory; use GFG\DTOContext\Manager; $manager = (new Manager())->setFactory(new Factory()); $context = $manager->build(...);