1

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 Ctrl + Click?

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?

LazyOne
  • 158,824
  • 45
  • 388
  • 391
LordF
  • 407
  • 5
  • 18
  • For references: https://intellij-support.jetbrains.com/hc/en-us/community/posts/12727826642834-Binding-a-custom-method-parameter-to-a-class-property – LordF Jul 27 '23 at 10:00
  • @hekre, the reference is the same post on jetbrains, so there is nothing more than here, atleast right now. – LordF Jul 27 '23 at 11:28
  • no access rights to display the website contents I mean with not working. the URL does not work for me. _"OOPS You're not authorized to access this page Take me back to the home page"_ – hakre Jul 27 '23 at 11:29
  • Maybe it's only me, but it's difficult to understand what you are trying to do. For instance, why do you need to pass the prop name as `$this->scopeOnRepoProperty($scope, 'documents')` instead of referring to it in the `scopeOnRepoProperty` method directly. The second snippet looks fine, but you are apparently not satisfied with it: _"The code works fine, unfortunately I lost the bindings to these properties because of this."_. What bindings? Do you mean that PHPStorm doesn't bring you to the prop. declaration when you click on `$this->documents`? – Ruslan Osmanov Jul 27 '23 at 16:13
  • @RuslanOsmanov Yes, i mean that PHPStorm doesn't bring me to the prop, and vice verse when I click on prop. And this is the question: There is any way to tell PHPStorm that string passed as second parameter in method is refering to method in that class when is used. I just want PHPStorm to take me to a property when I click on this string. – LordF Jul 28 '23 at 11:21
  • @LordF, AFAIK, it's impossible. If the arg is a static string literal, then why not refer to the property itself? If we have to pass different values as the second arg, for instance, then we could refer to it as `$this->document` (objects are passed by reference so no need in &). I don't understand, how `'document'` is better than `$this->document`. If the 2nd arg is a dynamic string, then you still can refer to the poperties dynamically: `$this->{$prop}`, but that would be a runtime value that PhpStorm wouldn't know, of course. – Ruslan Osmanov Jul 28 '23 at 18:56

1 Answers1

2

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:

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Your solution is very elegant, I forgot the ??= operator because I rarely use it. Now I'm debating whether to accept your answer, because it is a good solution, but only in this particular case, and does not answer the right question. Nevertheless, it is certainly helpful. Thank you, I will use it in this particular case. – LordF Jul 27 '23 at 11:49
  • 1
    @LordF: Then keep the question open and wait for more answers. There is no requirement to jump on the first answer to accept it. Not accepting it will give you the benefit that other users see you're still open for the "answer in PhpStorm" which is indeed a bit short in my answer as it suggested more explicit code as the solution (and Phpstorm supports that). I'd also recommend this over IDE configuration, but that can depend on style. Do you know about https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html ? – hakre Jul 27 '23 at 11:56