You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Psalm方法参数协变问题求解

PHP Psalm方法参数协变问题求解

嗨,各位大佬,我最近在PHP Psalm的类型校验上卡壳了,想请教下有没有合适的解法😅

先给大家说下我的场景:我定义了一个Node接口,还有一堆实现它的子类(比如TaskNode、ProjectNode);然后有个Handler接口,里面有个handleNode()方法,这个方法本质上只需要处理Node类型的实例就行,不关心具体是哪个子类。但现在我实现Handler的子类时,比如TaskHandler只想处理TaskNode,ProjectHandler只想处理ProjectNode,Psalm就会报类型不兼容的错误。

我把核心代码贴出来方便大家理解:

<?php

interface Node {}
class TaskNode implements Node {}
class ProjectNode implements Node {}

interface Handler {
    /**
     * @param Node $node
     */
    public function handleNode(Node $node): void;
}

class TaskHandler implements Handler {
    /**
     * @param TaskNode $node
     */
    public function handleNode(TaskNode $node): void {}
}

class ProjectHandler implements Handler {
    /**
     * @param ProjectNode $node
     */
    public function handleNode(ProjectNode $node): void {}
}

$handlers = [new TaskHandler(), new ProjectHandler()];

foreach ($handlers as $handler) {
    $handler->handleNode(new TaskNode()); // 这里Psalm会报错,因为ProjectHandler的handleNode只接受ProjectNode
}

我本来想找合适的@template参数组合来解决这个问题,但试了好几种都没成功。而且在实际项目里,不能直接把Handler接口里的@param改成TaskNode|ProjectNode这种联合类型——因为这类Node子类有很多,后续还会新增,要是每次都要去更新100+类似的方法注释,维护成本太高了,完全不现实。

有没有朋友遇到过类似的场景?能不能给我指点下,用什么Psalm注解或者类型技巧,既能让这个场景通过校验,又不用硬编码所有的Node子类类型?

备注:内容来源于stack exchange,提问作者Jan Sverre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 15:05:29