如何使用相同的 class 使用多个服务

How to consume multiple services using same class

我需要一种方法来处理具有相同 class 的多个不同服务。假设我有一个本地数据库,其中存储了我的本地 post。每次我将 post 保存到这个本地数据库时,我也需要 post 使用这些服务。所以他们肯定需要一个适配器模式,这样我就可以始终使用相同的方法。这很清楚,但我不确定如何使主要 class 可互换,以便我可以动态加载所需的平台和服务。

结构可能是这样的:

App              App
 Adapters         Adapters
  ServiceA         ServiceB   
   Post.php         Post.php
   Category.php     Category.php
   ...              ...

通过在 Post.php 中使用适配器模式方法,将采用相同的方法 sendPost()deletePost()

现在我可以使用相同的 sendPost() 方法为每个平台发送 post。我可以这样做。

$post = Post::create($form_array);
$services = Service::get();

foreach ($services as $service){
    $class = '\App\Adapters\'.$service->name.'\Post';
    $service = new $class;
    $service->sendPost($post); 
}

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

实际上这个方法可行,但它似乎(感觉)不是正确的方法。例如,每次我需要另一个服务时 Post 我需要创建另一个实例。

$class = '\App\Adapters\'.$service->name.'\Category';
$service = new $class;
$service->deletePost($post->id); 

我看起来更像。

$service = new Service('ServiceA');
$service->post->sendPost($post);
$service->category->create($cat);

那我可以

$post = Post::where('id', 44);
$services = Service::get();

foreach ($services as $service){
    $service = new Service($service->name)
    $service->post->deletePost($post->id); 
}

我知道这不是一个非常详细的表示,但你明白了。我想使用多种服务并能够使用我的本地系统来实现它。那么正确和最好的方法是什么?

在将方法添加到现有 Class 方面,我不是专家。这个问题一直困扰着我,我一直在研究一个可能不是最干净的解决方案,但我认为你会喜欢它。

最后,这就是我能够访问每个 Post.php 个文件中的方法的方式。

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

为了做到这一点,我没有你的原始服务文件,所以我在 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;
    }
}

主要目的是扫描适配器中的所有内容,并根据父目录创建实现 class 的方法。

如果您喜欢,我可以根据需要提供更多解释。