我试图在控制器内为具有行为的模型使用自动完成功能。
使用:
/** @var ModelName **/
public $ModelName;
它只是自动完成ModelName内的任何内容,并且:
/** @var BehaviorNameBehavior **/
public $ModelName;
只是自动完成了BehaviorNameBehavior中的任何内容,但我认为这有点明显。我查看了PHPdoc文档,但我没有看到任何方法为变量指定两个类。
还有问题,在CakePHP中,行为函数的第一个参数总是(Model $ model),但该参数在CakePHP框架内部指定,并且在控制器/模型中调用函数时不包含该参数
有没有人能够让这个工作?
编辑:添加了示例
class ModelName extends AppModel {
public $actsAs = array("BehaviorName");
public function someModelFunction() {}
}
class BehaviorNameBehavior extends ModelBehavior {
public function someBehaviorFunction(Model $model, $param) {}
}
class ControllerNameController extends AppController {
/** @var BehaviorNameBehavior|ModelName $ModelName */
public $uses = array("ModelName");
public function someAction() {
// Type hinting here thinks model should be first parameter but that's not how CakePHP works
$this->ModelName->someBehaviorFunction("some param value");
}
}
答案 0 :(得分:0)
不可能像这样自动化行为完成,PhpStorm将始终看到实际的方法签名,这要求第一个参数为Model
类型。
为模型对象提供适当的代码完成的唯一方法是定义"继承"方法一个接一个地通过the @method
tag,即
/**
* @method returnType someBehaviorFunction(argumentType $param)
*/
class ModelName extends AppModel {
public $actsAs = array("BehaviorName");
public function someModelFunction() {}
}
/**
* @property ModelName $ModelName
*/
class ControllerNameController extends AppController {
public $uses = array("ModelName");
public function someAction() {
$this->ModelName->someBehaviorFunction("some param value");
}
}
或者使用虚拟接口,这是一个更干的,并且通过使用PhpStorms重构功能从行为类中提取接口并稍微修改它更容易创建。
/**
* @internal
*/
interface IBehaviorNameBehaviorStub {
/**
* @param argumentType $param
* @return returnType
*/
public function someBehaviorFunction($param);
}
/**
* @property IBehaviorNameBehaviorStub|ModelName $ModelName
*/
class ControllerNameController extends AppController {
public $uses = array("ModelName");
public function someAction() {
$this->ModelName->someBehaviorFunction("some param value");
}
}
注意,似乎有一个错误,PhpStorm有时会在只有一个时正确识别@property
标签!似乎是一个缓存问题,添加额外的@property
标记并在以后删除它通常会解决问题。