Php文档:键入一个字符串类名,它将始终实现给定的接口
我有一个返回类名(字符串)的函数,但返回的类始终实现相同的接口:Php文档:键入一个字符串类名,它将始终实现给定的接口,php,phpdoc,Php,Phpdoc,我有一个返回类名(字符串)的函数,但返回的类始终实现相同的接口: <?php interface BaseInterface {} class SomeClass implements BaseInterface {} class AnotherClass implements BaseInterface {} /** * @return .... */ function getClassName($someCondition): string { if ($someCon
<?php
interface BaseInterface {}
class SomeClass implements BaseInterface {}
class AnotherClass implements BaseInterface {}
/**
* @return ....
*/
function getClassName($someCondition): string
{
if ($someCondition === 42) {
return SomeClass::class;
} else {
return AnotherClass::class;
}
}
最终的目标是让IDE理解getClassName(…)::myInterfaceMethod()
是有效的
编辑:问题的具体用例
下面是一个可运行的示例,演示了如何在实际代码中使用::class
我重新编写了尽可能短的代码,但它实际上是使用PHP7.4运行的Symfony项目的一部分
其想法是在每个社交网络上实现一个类;所有这些小类都实现了SocialNetworkInterface
,并且只有静态方法。它们从不实例化,但通过调用它们的静态方法来查询它们
注意:变量$user
应键入为user
,但为了缩短代码,我只是在参数中不键入它们
在我的问题(IDE正在抱怨)中解释的问题发生在第79行,在renderLinkForUserNetwork()中
不,不幸的是,它不是这样工作的。您应该在这里指定一个返回类型,即使BaseInterface::class是动态的,它也将是一个返回值(类型为字符串
)。让我澄清一下:在我的问题中,/***@return BaseInterface::class*/
是一个虚构的语法,可以满足我的需要。最终的目标是让IDE理解getClassName(…)::myInterfaceMethod()
是有效的。(问题编辑)谢谢你的澄清。但是从我所看到的,由于函数getClassName()
返回一个字符串,因此您将对返回的字符串调用myInterfaceMethod()
,而不是对您想要的实际类。这听起来越来越像是一场灾难。我认为我们需要查看实际的周围代码才能进一步了解这一点,因为我不认为函数getClassName()
是解决您问题的可行方法,但我可能完全错了。好的,问题已编辑
/** @return BaseInterface::class */
$class = $networkClass::getFontAwesomeLogoClass();
$url = $networkClass::getUrlForUsername($networkUsername);
<?php
interface SocialNetworkInterface
{
public static function getName(): string;
public static function getBaseUrl(): string;
public static function getUrlForUsername(string $username): string;
public static function getFontAwesomeLogoClass(): string;
}
abstract class AbstractSocialNetwork implements SocialNetworkInterface
{
public static function getUrlForUsername(string $username): string
{
// Most social networks use this kind of urls, but of course, this can
// be overloaded in final classes:
$baseUrl = static::getBaseUrl();
return "$baseUrl/$username";
}
public static function getFontAwesomeLogoClass(): string
{
$name = static::getName();
return "fab fa-$name";
}
}
class Facebook extends AbstractSocialNetwork
{
public static function getName(): string
{
return 'facebook';
}
public static function getBaseUrl(): string
{
return ('https://www.facebook.com');
}
}
class Twitter extends AbstractSocialNetwork
{
public static function getName(): string
{
return 'twitter';
}
public static function getBaseUrl(): string
{
return ('https://twitter.com');
}
}
class SocialNetworkHandler
{
public function getSocialNetworksForUser($user): array {
// Should return all the social network classes for which the user has
// information to give (normally depends on the user, fake data is given
// here for simplicity):
return [
Facebook::class,
Twitter::class,
];
}
public function renderLinkForUserNetwork($user, string $networkClass): ?string
{
// Make it runnable for this example, normally retrieved from $user
// and $networkClass:
$networkUsername = 'example';
// An ugly workaround: of course, $networkClass is not an instance of
// SocialNetworkInterface, but calling static methods work the same
// between class name strings and objects:
/** @var SocialNetworkInterface $networkClass */
// When not using the ugly workaround just above, the IDE is complaining
// here (method not found in string):
$class = $networkClass::getFontAwesomeLogoClass();
$url = $networkClass::getUrlForUsername($networkUsername);
return <<< HTML
<a href="$url"><i class="$class"></i></a>
HTML;
}
public function renderLinksForUser($user): string
{
$links = [];
foreach ($this->getSocialNetworksForUser($user) as $networkClass) {
$links[] = $this->renderLinkForUserNetwork($user, $networkClass);
}
return implode("\n", $links);
}
}
$handler = new SocialNetworkHandler();
$user = null; // Should be a User entity
echo $handler->renderLinksForUser($user);