首页 > 解决方案 > 如何使用同一类使用多个服务

问题描述

我需要一种方法来处理同一个类的多个不同服务。假设我有一个本地数据库,用于存储我的本地帖子。每次我将帖子保存到这个本地数据库时,我也需要发布这些服务。所以他们肯定需要一个适配器模式,这样我就可以总是使用相同的方法。这很清楚,但我不确定如何使主类可互换,以便我可以即时加载所需的平台和服务。

结构可能如下:

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

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

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

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

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

标签: phplaraveladapterapi-gateway

解决方案


在将方法添加到当前现有的类时,我不是专家。这个问题一直萦绕在我的脑海中,我一直在研究一个可能不是最干净的解决方案,但我认为你会喜欢它。

最后,这就是我能够访问每个 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;
    }
}

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

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


推荐阅读