英文:
Binding a custom method parameter to a class property
问题
有没有办法在类内部将类属性绑定到方法参数,以便在单击 "Ctrl + 单击" 时建立双向链接?
class Attachments extends Repository
{
public Documents $documents;
public function fromDocuments(callable $scope)
{
$this->scopeOnRepoProperty($scope, 'documents');
}
}
我的意思是,在这种情况下,scopeOnRepoProperty()
方法中的第二个参数 documents
应该引用属性 $documents
。
更广泛的背景:
对我来说,问题在于代码的很大一部分非常类似,即大多数 scopeXXX
/fromXXX
方法都做类似的事情,即执行该方法并将属性存储库作为参数发送给它。例如,在上面的示例中,执行 $scope($this->documents)
;
此外,如果 $this->documents
未初始化,则创建一个新实例。
所以代码看起来像这样:
public function fromDocuments(callable $scope)
{
if (!isset($this->documents)) {
$this->documents = new Documents();
}
$scope($this->documents);
}
我想避免每次编写 if
语句、创建新对象和调用方法,所以我想到了一个方法,它将接受一个可调用对象、属性名称和类型反射类名。
代码运行得很好,不幸的是,由于这个方法,我失去了与这些属性的绑定。在之前的版本中,是 $this->documents
,所以链接是存在的,但现在不是。
我想知道是否有任何方法可以实现这一点。有什么想法吗?
英文:
Is there any way to bind a class property to a method parameter inside that class so that there is a two way link when you click <kbd>Ctrl + Click</kbd>?
class Attachments extends Repository
{
public Documents $documents;
public function fromDocuments(callable $scope)
{
$this->scopeOnRepoProperty($scope, 'documents');
}
}
I mean, that in that case second parameter documents
in scopeOnRepoProperty()
method should refer to property $documents
.
The broader context:
The problem for me is that a large part of the code was very analogous, namely, most of the method scopeXXX
/fromXXX
does something like that, executes the method and sends the property repository to it as a parameter. i.e. in the example above, $scope($this->documents)
is executed;
and additionally, if $this->documents
is not initialized, a new instance is created.
So it's looks:
public function fromDocuments(callable $scope)
{
if (!isset($this->documents)) {
$this->documents = new Documents();
}
$scope($this->documents);
}
I wanted to save myself writing an if
every time, creating a new object and calling a method, and I came up with the idea that I can do it with one method that will take a callable and the name of this property and from type reflection class name.
The code works fine, unfortunately I lost the bindings to these properties because of this. In the previous version it was $this->documents
, so the link was there, but as it is now it is not.
I am wondering if there is any way I can achieve this. Any ideas?
答案1
得分: 2
我想节省每次编写 if 语句的时间。
$scope($this->documents ??= new Documents());
这段代码既引用了属性,也引用了你想要使用的类。这通常比使用表示两者的字符串更好(并且也丢失了对具体属性和具体类名的引用)。
你所做的这种方式也被称为延迟初始化。它的问题是你在类中使用了 new 关键字,导致代码难以测试。尽管如此,这仍然是对使用字符串的改进。
你可能还对 PhpStorm 中的新泛型支持的 @mixin 感兴趣,你可以在这里找到一个示例:
这可能使你能够跳过可调用注入,但我不太清楚你通过这样做能实现什么,所以这只是一个额外的提示,可能不符合你的需求。
参考资料:
- PHP RFC: Null Coalescing Assignment Operator
- PHP 7.4 中的 null 合并赋值运算符 ??= 是什么?
- 回答:“安全地获取已定义和未定义索引的数组元素值”
英文:
> I wanted to save myself writing an if every time
$scope($this->documents ??= new Documents());
This references both the property as well as the class you want to use there. That is often better than using a string that represents both (and also looses the references to both the concrete property and the concrete classname).
What you do there is also called lazy initialization. It has the problem that you have the new keyword within your classes that leads to hard to test code. Still thought it is an improvement over using the string.
You might also be interested for the new Generics support of @mixin in PhpStorm, you can find an example here:
This may allow you to skip the callable injection, but it's not entirely clear to me what you achieve by that, so this is only an additional hint, it must not match your needs.
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论