仅在存在时才实现接口?

问题描述 投票:0回答:3

我试图找到一种方法,仅当该接口可用时才实现该接口。

有问题的接口是

PrestaShop\PrestaShop\Core\Module\WidgetInterface

来自 Prestashop。它在模块中使用。

问题是,为了兼容多个版本的 Prestashop,代码必须处理

WidgetInterface
不存在的情况。

我想测试一下接口是否存在,然后导入它,就像这样:

if (interface_exists('PrestaShop\PrestaShop\Core\Module\WidgetInterface')) {
    use PrestaShop\PrestaShop\Core\Module\WidgetInterface
} else {
    interface WidgetInterface {}
}

但是,当然,不可能在 if 语句中使用

use

然后我尝试做一些 try/catch,但这是同样的问题(可惜它不是 Python)。

只有在可用时我才能做

implements WidgetInterface

php prestashop
3个回答
2
投票

您无法像您所说的那样动态实现接口,但您可以编写自己的接口,并且仅在另一个接口不存在时才

require

即:您的界面将类似于

widget_interface.php
,或者您想称呼它的任何名称,只要它不符合 PSR-0/4,或者以您通常采用的任何方式自动加载即可。

<?php    

namespace PrestaShop\PrestaShop\Core\Module;

/**
 * This is the replacement interface, using the same namespace as the Prestashop one
 */
interface WidgetInterface
{
}

然后,在课堂上,您可以执行以下操作:

<?php

namespace App;

if (!interface_exists('\PrestaShop\PrestaShop\Core\Module\WidgetInterface')) {
    require __DIR__ . '/path/to/widget_interface.php';
}

class WhateverClass implements \PrestaShop\PrestaShop\Core\Module\WidgetInterface
{

}

仅当 Prestashop 界面不存在时才会加载您的替换界面。


1
投票

确实,您不能将

use
放入
if
块中,但
use
只是为类设置一个别名。它不会尝试加载该类。所以它可以安全地位于
if
区块之外。

并且您可以

if
内定义类或接口本身。

就是 Symfony 处理这个问题的方式,继承自一个可能不存在的接口:

namespace Symfony\Contracts\EventDispatcher;

use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;

if (interface_exists(PsrEventDispatcherInterface::class)) {
    interface EventDispatcherInterface extends PsrEventDispatcherInterface
    {
        public function dispatch($event);
    }
} else {
    interface EventDispatcherInterface
    {
        public function dispatch($event);
    }
}

就我个人而言,为了保持事物干净并包含在一个地方,我会像这样定义您自己的接口,该接口继承自

PrestaShop
接口(如果可用)或提供自己的实现,然后让您的类继承该接口。


0
投票

我必须为 Laravel 应用程序执行此操作才能支持版本 9 和 10。这并不完全相同,因为两个版本中都存在接口。但是,我没有创建垫片接口或处理加载文件,而是这样做了:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;              // 9.0 interface
use Illuminate\Contracts\Validation\ValidationRule;    // 10.0 interface

if (!interface_exists(ValidationRule::class)) {
    class_alias(Rule::class, ValidationRule::class);
}

class MyRule implements ValidationRule {
    // ...
}

现在当我提到

ValidationRule
时,它要么是10.0中的实际接口,要么是9.0中的别名。

我认为文件中包含非类代码违反了 PSR-2 或 12,但当规则妨碍时我并不坚持这些规则。

© www.soinside.com 2019 - 2024. All rights reserved.