首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现API类的PHP/Laravel接口

实现API类的PHP/Laravel接口
EN

Stack Overflow用户
提问于 2021-06-30 21:39:02
回答 2查看 205关注 0票数 1

我有一个带有搜索功能的界面:

代码语言:javascript
复制
interface Searcher
{
    public function search($text,$limit)
}

我有一些基于API的实现

代码语言:javascript
复制
class APISeach implements Searcher
{
   public function search($text,$limit)
   {
        $params = [
            'name' => $sName,
            'maxRows' => $iLimit,
        ];
        $response = Http::get('http://some_api_service/search', $params)->json();
   }
}

我有一些使用这个搜索的代码:

代码语言:javascript
复制
class MyController extends Controller
{
    private $seacher;
    
    public function __construct(Searcher $mySeacher)
    {
         $this->seacher = $mySeacher;
    }

    public function search($text,$limit=10)
    {
         $this->seacher->search($text,$limit)
    }
}

一切看起来都很好(可能是这样)。但是,如果我需要改变API实现,它将需要另一个参数。例如:

代码语言:javascript
复制
class AnotherAPISeach implements Searcher
{
   public function search($text,$language,$fuzzy,$limit)
   {
       $ApiObjectFromLib = new ApiObjectFromLib();
       $response = $ApiObjectFromLib->search($text,$language,$fuzzy,$limit)->json();
   }
}

所以它不能再实现Searcher接口了。有没有为API函数使用接口的方法?所有的API都需要不同的参数,如果我需要为每个API更改接口或控制器代码,这是不好的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-30 21:44:33

您可以使用variadic arguments

代码语言:javascript
复制
interface Searcher
{
    public function search($text, $limit, ...$additional);
}

如果这与interface的目的背道而驰,则由您来决定?​

票数 1
EN

Stack Overflow用户

发布于 2021-07-01 23:40:43

像这样(demo)怎么样?

代码语言:javascript
复制
public function search(string $name, int $limit = \Search\Limit::DEFAULT)
{
    return $this->api->search(
        new \Search\Name($name),
        new \Search\Limit($limit)
    );
}

public function lookup(
    string $name,
    string $language = \Search\Language::DEFAULT,
    bool $fuzzy = \Search\Fuzzy::DEFAULT,
    int $limit = \Search\Limit::DEFAULT
) {
    return $this->api->search(
        new \Search\Name($name),
        new \Search\Language($language),
        new \Search\Fuzzy($fuzzy),
        new \Search\Limit($limit)
    );
}

这些“规范”看起来像这样:

代码语言:javascript
复制
namespace Search
{
    interface Specification
    {
        public function __invoke(array $params): array;
    }
    
    class Name implements Specification
    {
        private $name = null;
        
        public function __construct(string $name)
        {
            $this->name = $name;
        }
        
        public function __invoke(array $params): array
        {
            return [
                'name' => $this->name,
            ];
        }
    }
    
    class Language implements Specification
    {
        const DEFAULT = 'en';
        
        private $language = null;
        
        public function __construct(string $language)
        {
            $this->language = $language;
        }
        
        public function __invoke(array $params): array
        {
            return [
                'language' => $this->language ?? 'en',
            ];
        }
    }
    
    class Fuzzy implements Specification
    {
        const DEFAULT = true;
        
        private $fuzzy = null;
        
        public function __construct(bool $fuzzy)
        {
            $this->fuzzy = $fuzzy;
        }
        
        public function __invoke(array $params): array
        {
            return [
                'fuzzy' => $this->fuzzy,
            ];
        }
    }
    
    class Limit implements Specification
    {
        const DEFAULT = 10;
        
        private $max = null;
        
        public function __construct(int $limit)
        {
            $this->limit = $limit;
        }
        
        public function __invoke(array $params): array
        {
            return [
                'maxRows' => $this->limit ?: self::DEFAULT,
            ];
        }
    }
}

可搜索API的组成如下所示:

代码语言:javascript
复制
interface Searchable
{
    public function search(\Search\Specification... $criteria);
}

class Search implements Searchable
{
    private $url = '/search';
    
    private $defaults = [
        'maxRows' => \Search\Limit::DEFAULT,
    ];
    
    public function search(\Search\Specification ...$criteria)
    {
        return \Http::get($this->url, array_reduce(
            $criteria,
            fn($params, $criteria) => $criteria($params) + $params,
            $this->defaults
        ))->json();
    }
}

Specification Pattern很有趣,因为它意味着进入域的请求实际上只是一系列决策,这些决策导致可以在其他地方应用的配置。

例如,请注意上面的$criteria($params)对象被赋予了请求的当前$params,对于该请求,它可以覆盖参数、读取和修改参数,或者潜在地结合规范检查来验证参数。

关于array + array语法的说明,这是一种合并数组的方法:

代码语言:javascript
复制
['foo' => 'bar'] + ['foo' => 'baz'] // left takes precedence: ['foo' => 'bar']

Filter/Criteria非常相似;我倾向于认为那些与应用它的对象(Repository、Query或Collection)的链接比Specification更紧密,在我看来,Specification更多地应用于要返回的内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68195905

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档