I need a way to handle multiple different services with the same class. Let's say I have a local data base where my local posts are stored. Each time I save a post to this local database I need to post with those services as well. So they will need a adapter pattern for sure so that I can always use the same methods. That is clear but I am not sure how I could make the main class interchangable so that I can load the needed platform and service on the fly.
The structure could be like:
App App
Adapters Adapters
ServiceA ServiceB
Post.php Post.php
Category.php Category.php
... ...
By using the adapter pattern methods within Post.php
will have adapted the same methods sendPost()
and deletePost()
.
Now I will be able to send post for each platform using the same sendPost() method. I could do like this.
$post = Post::create($form_array);
$services = Service::get();
foreach ($services as $service){
$class = '\\App\\Adapters\\'.$service->name.'\\Post';
$service = new $class;
$service->sendPost($post);
}
or
$post = Post::where('id', 44);
$services = Service::get();
foreach ($services as $service){
$class = '\\App\\Adapters\\'.$service->name.'\\Post';
$service = new $class;
$service->deletePost($post->id);
}
Actually this aproach works but it doesn't seem (feel) to be the right way to go. Here for instance each time I need another service instead Post I would need to create another instance.
$class = '\\App\\Adapters\\'.$service->name.'\\Category';
$service = new $class;
$service->deletePost($post->id);
I am looking more something like.
$service = new Service('ServiceA');
$service->post->sendPost($post);
$service->category->create($cat);
then I could
$post = Post::where('id', 44);
$services = Service::get();
foreach ($services as $service){
$service = new Service($service->name)
$service->post->deletePost($post->id);
}
I know this is not a very detailed representation but you get the idea. I want to consume multiple services and being able to implement it with my local system. So what is the right and best way to do this?
I'm not an expert when it come to adding method to currently existing Class. This questions stuck in my head and I've been working on a solution that may be not the most clean, but I think you can like it.
In the end, this is how I've been able to access a method inside each Post.php files.
public function __construct()
{
$this->service = Service::boot();
}
public function test()
{
$service = Service::getService('ServiceB');
return $service->post->testPost();
}
public function testGlobal()
{
return $this->service->serviceA->post->testPost();
}
public function testAllServices()
{
$service = Service::boot();
return $service->serviceA->post->testPost();
}
To achieve this, I did not had your original Service file, so I made one at App/Adapters
<?php
namespace App\Adapters;
class Service
{
public static function boot() {
$directory = dirname(__DIR__).'/Adapters';
$services = array_diff(scandir($directory), array('..', '.'));
$container = new class {};
foreach($services as $key => $service) {
if (is_dir(dirname(__DIR__).'/Adapters/'.$service)) {
$container->{lcfirst($service)} = new class {};
$directory = dirname(__DIR__).'/Adapters/'.$service;
$classes = array_diff(scandir($directory), array('..', '.'));
foreach($classes as $secondary_key => $class) {
$class = str_replace('.php', '', $class);
$namespace = 'App\Adapters\\'.$service.'\\'.$class;
$container->{lcfirst($service)}->{lcfirst($class)} = new $namespace;
}
}
}
return $container;
}
public static function getService($service) {
$container = new class {};
$directory = dirname(__DIR__).'/Adapters/'.$service;
$classes = array_diff(scandir($directory), array('..', '.'));
foreach($classes as $secondary_key => $class) {
$class = str_replace('.php', '', $class);
$namespace = 'App\Adapters\\'.$service.'\\'.$class;
$container->{lcfirst($class)} = new $namespace;
}
return $container;
}
}
The main purpose is to scan everything within Adapters and creating method that implement the class depending on the parent directory.
If you like that, I can provide more explanation if needed.