I am making usage of
/* #var $var Type */
really often for NetBeans can then autocomplete methods and stuff in code.
Still I think its a very useful feature but sometimes I got objects of
classes extending one more class and implementing multiple interfaces.
Or I even got a transitive class hierarchy.
I don't know a way to tell NetBeans that it shall be using autocomplete for
all these interfaces and upper-layer parent classes.
I would like to do so for of course every of these interfaces / classes got
dedicated methods (which are defined somewhere in case of interfaces...)
I tried something like this:
/* #var $var TypeA|\TypeB|\TypeC */
because I saw NetBeans will generate a similar documentation for methods returning
different class objects due a switch/case. But this seems to work only for the
#return notation.
I also tried
/* #var $var TypeA|TypeB */
Also not working...
NetBeans will autocomplete the last told Type in this case but not a combination of both/all told classes.
How can I document so my autocomplete works as desired (a summary of methods of all classes /interfaces I listed)?
regards!
If I understand you correctly, you are asking to chain hint through your PHP code.
The problem is netbeans has no way of knowing what an object actually is; unless you tell it. The solution is to use the #property command in your object decleration to forward type define the objects members , be it a class or interface.
/**
#property classMyClass1 $clsMyClass1
#property classMyClass2 $clsMyClass2
*/
class baseClass{
public $clsMyclass1;
public $clsMyClass2;
public function __construct() {
$this->clsMyClass1 = new classMyClass1();
$this->clsMyClass2 = new classMyClass2();
}
}
$foo = new baseClass();
Now when you type your code in netbeans it will know what hinting to display on your last typed object
$foo->clsMyClass1->
So long as each class has a forward property decleration you can chain as long as you want
$foo->class1->class2->class3->...
The above code would need the autoload() function to load the correct class files....
Hope this helps you!
Related
This is just an example to illustrate my issue. Quite often, I am looking for (vendor) code that executes a method, but end up in the interface (which I guess is implemented by the code I am looking for).
In a Symfony app, I have a function Example()that uses $logger, which is typehinted with LoggerInterface. I use the correct interface by adding to my file: use Psr\Log\LoggerInterface;. In my function I use $logger to log an error with the method error() like so:
public function Example(LoggerInterface $logger)
{
$logger->error('There was some error.')
}
When I open the file that contains the LoggerInterface I can see how this method:
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* #param string $message
* #param array $context
*
* #return void
*/
public function error($message, array $context = array());
This can be useful for the documentation and for seeing which arguments one must pass.
My question: how do I find the method that does the actual work (i.e. that is being executed) and how does the $logger 'finds' this through the interface?
In a more generic PHP example, when I need a dateTime object I will use new DateTime(); (with a use statement: use DateTime;). Then I could call the method format() on it. When I want to find out exactly what format() does, looking for it in the class DateTime, all I find is:
/**
* Returns date formatted according to given format.
* #param string $format
* #return string
* #link https://php.net/manual/en/datetime.format.php
*/
public function format ($format) {}
Again I wonder: how to find the method doing the work?
Psr\Log\LoggerInterface is, as its name suggests, an interface. This means that it specifies the methods an inheriting class must implement, but – as you've seen – it doesn't provide any code for those methods.
Any class written to implement Psr\Log\LoggerInterface must include all the methods listed in the interface. Any such class will satisfy the type declaration in the method signature.
The actual class of your object can be determined by running get_class() on the object in question, e.g.
public function Example(LoggerInterface $logger)
{
$logger->error("I am an instance of class " . get_class($logger));
}
With respect to native PHP classes, although the documentation may be written to look like they are standard PHP classes with methods and properties, this is not the case. They are written in C, which you can find in the repository.
Taking your example of DateTime::format(), it's first defined as a method of the DateTimeInterface. This is implemented by the DateTime class, where it is simply specified as an alias to the date_format method. Unless you're very good with C, I'd suggest sticking to the documentation
Multi-tier question, deserves a multi-tier answer.
1. Configuration
Specifically for logger, it can be any logger that follows Psr\Log standards, but symfony is configured to use monolog.
You can see detail on: https://symfony.com/doc/current/logging.html (disclaimer: I'm not symfony expert but this looks logical).
So - logger is whatever you configure.
2. Programming style
When you are programming - anywhere inside a function and want to know exact instance of logger (or any other object), you can call get_class() function and get a specific instance class name.
Details on: https://secure.php.net/manual/en/function.get-class.php
3. Debugger
You can use Xdebug, add breakpoint to specific function and in variable view check instance class name.
4. PHP native objects
You can find exact functionality in PHP source code: https://github.com/php/php-src
let's say I have the following
class Something extends ClassWithMagicMethods{}
Normally I would add a docblock for any properties I know exist even if accessed via a magic method
/**
* #property string $someVar
* #method SomeClass getSomeClass()
*/
class Something extends ClassWithMagicMethods{}
Which works great, but what I'm wondering is if we can have that docblock separate from the definition of the class. Two possible usecases:
Third party package that doesn't include the docblock but I want autocompletion from my IDE - I'd like to be able to just add my own docblock somewhere for it.
An extension system - In the file where the extension is defined I'd like to document the new properties this extension adds to the class.
I'm aware I could technically create a dummy ide_helper.php file that never actually gets run - just indexed by the IDE - unfortunately this causes any decent IDE to complain about duplicate declarations which I don't want as it also makes code navigation slower.
So - is it possible to document a PHP class by composing multiple docblocks external from the class definition?
Most of the results I've pulled up on SO are referencing just documenting unknown types where you use them which isn't what I need. I.E:
/** #var Something $something */
$something = FactoryMethodThing::create('Something');
See if this can help you :
phpdoc -d path/to/my/project -f path/to/an/additional/file -t path/to/my/output/folder
Source: http://docs.phpdoc.org/guides/running-phpdocumentor.html
I am running into trouble making IntelliJ IDEA display inherited methods correctly.
I have an abstract BaseController class holding two protected field variables (f3 and db). In the extending ForumController class, db works fine, but the static f3 does not (see screenshots below).
The framework used is FatFree, if that helps.
Any help or suggestion would be highly appreciated.
Use the tags of phpdoc to document all classes, properties and methods. IntelliJ uses those to determine what possible values a property or variable may hold. In this case documenting the $f3 property could be sufficient:
/**
* #var Base
*/
protected $f3;
After typing the first /** on the line before the property and pressing enter IntelliJ will generate a docblock for you with what it knows already.
In fatfree framework, the instance of Base class ($f3 in your code) is passed to the constructor, so you can use type hinting there:
public function __construct(Base $f3){
$this->f3 = $f3;
Though retrieving the instance from the registry via the static call Base::instance(); and using phpdoc comments as in the accepted answer is fine as well.
In CakePHP 1.3 I usually add model property definitions and PHPDoc to my models and controllers like so:
/**
* #var Vegetable
*/
public $Vegetable;
In Netbeans this gives "Intellisense"-style autosuggestion, displays PHPDoc information, and is generally a boon. Unfortunately in CakePHP 2 it seems that this causes the model lazy-loading to fail because the magic methods __isset() and __get() are never called for properties that already exist.
The lack of autosuggest would be a bitter pill to swallow - has anyone come across this issue, and can you see any workarounds?
Use #property annotation (in class decription).
How can we have autocomplete on property when this one isn't define in the same php file.
for example, with ZF, in the controller we can do
$this->view->voiture = new My_Voiture();
and in the view, we have a variable $this->voiture, but how can i have the autocomplete on it ?
i try /* #var $this->voiture My_voiture */ and no result...
for the moment, my answer is to do in the view
/* #var $voiture My_Voiture */
$voiture = $this->voiture;
but i don't like it. Have you better ?
Documenting the original variable in its original source is actually the best way to go, I think. All other usages of your view in other files should inherit the autocompletion just by documenting it at its one source.
In order to get the autocompletion that I would expect, I would do these things:
In the My_Voiture class, make sure you have docblocks for your variables and your methods. This isn't technically necessary for the autocompletion itself, but it will allow the autocompletion popups to contain much more info that just variables and methods.
In the My_View class, where $voiture is first declared (not used), I would place the #var docblock that identifies its type as My_Voiture. This should be enough to make any usage of its $voiture variable inherit the properties of My_Voiture.
In the My_Controller class, where $view is first declared (not used), I would place the #var docblock that identifies its type as My_View. This should be enough to make any usage of its $view variable inherit the properties of My_View.
Now, in your code file where you are expecting autocompletion on $this->view->voiture -- if it has nothing in it that indicates that $this is a My_Controller object, then Eclipse has nowhere to start when it tries to identify $this (and then all of its properties). I think I've seen some MVC code before where this is prevalent, due to much "dynamic" properties relying on "variable variables" like $$foo.