Skip to content

Instantly share code, notes, and snippets.

@bobbybouwmann
Last active March 7, 2016 11:39
Show Gist options
  • Save bobbybouwmann/a8b33ebbeec33ccd64f5 to your computer and use it in GitHub Desktop.
Save bobbybouwmann/a8b33ebbeec33ccd64f5 to your computer and use it in GitHub Desktop.
HRManager

So I’m building a system that connects to multiple HR-applications. So I was thinking about using the Builder (Manager) pattern, like socialite is doing. So you can say this user is using HR-application AFAS so I new up a AFASProvider and do all my calls in there. And then I simply need to create a provider for each HR-application we support and I give them the same interface and make sure they all return the same information structure so I can work with that.

However the hard part here is that some HR-applications don’t support some functionalities that others do. So we were thinking about creating our own provider which can be used as well. So for example retrieve documents for a user is supported by AFAS but not by VISMA. So if the user is using the VISMA provider we need to make sure that for documents it’s using the local provider. Now that might not be that hard, but that means that the VISMA provider cannot use the normal interface, since the interface says it has a documents function.

So to fix that we can use multiple interfaces, like shown in the code examples. However this means that there are possibly around 20 interfaces and for each functionalty there needs to be a check on which provider should be used.

So what we really want is a flexible way to call a method on one of the providers if that provider is supporting the functionality. So my question is how can we make a good architecture that can manage this kind of behavior?

<?php
class HRManager extends Manager
{
protected $driver;
public function __construct(Application $app, $driver) {
parent::__construct($app);
$this->driver = $driver;
$this->driver($driver); // Create the import driver
}
public function getProvider($interface)
{
$provider = $this->getDrivers()[$this->driver];
if ($provider instanceof $interface) {
return $provider;
}
$this->driver('local'); // Create the backup driver if it doesn't exist
return $this->getDrivers()[$this->getDefaultDriver()];
}
public function documents()
{
$provider = $this->getProvider(DocumentProvider::class);
$provider->documents();
}
public function user()
{
$provider = $this->getProvider(UserProvider::class);
$provider->user();
}
public function createVismaDriver()
{
echo 'CreateVismaProvider<br>';
return new VismaProvider();
}
public function createLocalDriver()
{
echo 'CreateLocalDriver<br>';
return new LocalProvider();
}
public function getDefaultDriver()
{
return 'local';
}
}
<?php
// Create the manager that will generate the providers
$manager = new \App\HR\HRManager(app(), 'visma');
$manager->documents(); // Get the documents from the provider
$manager->user(); // Get the user from the provider
// Expected outcome
CreateVismaProvider
CreateLocalProvider
Local documents
Visma user
<?php
class LocalProvider implements DocumentProvider, UserProvider
{
public function documents()
{
echo 'Local documents<br>';
}
public function user()
{
echo 'Local user<br>';
}
}
<?php
class VismaProvider implements UserProvider
{
public function user()
{
echo 'Visma user<br>';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment