Proper Way to Document Class in Netbeans PHP - php

For reasons of ease of maintenance AND IDE class auto-completion and member hinting, I've used PHPDoc in my project. Given this example class:
class my_class {
public $id;
public $name;
public $number;
public function __construct() {
//Do something
}
public function Rename($name) {
$this->name = $name;
}
}
I would prefer to document all properties ($id, $name and $number) with the class documentation itself, which is above the class declaration, and then place documentation for methods (if necessary) above each method. Here is what I ultimately want my class to look like:
/**
* Represents an example class for Stackoverflow
*
* #property int $id The id of the object
* #property string $name The name of the object
* #property int $number The number of the object
*/
class my_class {
public $id;
public $name;
public $number;
public function __construct() {
//Do something
}
/**
* Renames the object
* #param string $name Name to rename object
*/
public function Rename($name) {
$this->name = $name;
}
}
This is precisely what I prefer to have as documentation, however Netbeans' autocomplete fails to operate correctly, as it lists each property twice. For example, if I start typing $my_class_object->i the auto-complete will list two $id properties: one as described in my PHPDoc, and another is described as an unknown variable with "PHPDoc Not Found".
There is a solution that works to solve the Netbeans issue - add a #var PHPDoc block above each property, however I think it unnecessarily clutters up my class, especially some of my classes that have 10+ properties.
Is there a [good] solution to both of my issues (clean doc, proper Netbeans hinting), or am I going about this incorrectly?

The "property" tag is specifically and explicitly for "magic" properties, meaning any that don't actually appear in the code itself. That's the key reason why the tag occurs only in the class docblock. As such, I'm guessing IDEs that recognize the "property" tag do so from that "it's NOT seen in the code" perspective. Granted, I could understand an expectation that autocomplete should recognize the existence of such a property, and therefore make it available for you. However, my bet is that the IDEs will stick with using only the code itself to build a model, and only use docblock info to supplement the elements that it already sees in the code.
Using the "var" tag is the one proper way to document your "coded" properties. If you want to minimize the lines required in order to use that tag on all the properties, use a one-line docblock:
/** #var int */
public $id;
Also, you could use the docblock template to cut down on docblocks, where tag similarity fits your code:
/** #var string */
public $name;
/**##+ #var int */
public $id;
public $number;
/**##-*/
That doesn't seem like much savings in this short list, but it does help when there are lots of properties. Also, it works fine around methods.

I prefer to use #var above each property and no #property at all. I feel that this allows you to more closely associate the comments with the thing that is being commented on. I.e., the comments for a property are always right next to the property. If you're using the #property style and you've got a big class with a ton of properties, it's entirely possible that the comment which describes a property is pages away from it.

I am not sure about the exact syntax but I am sure that netbeans will adhere to the standard php documentation.
http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.pkg.html
http://www.phpdoc.org/

Related

Whats the difference between a #property annotation and a protected variable in PHP?

I've a question. During a PHP class development I've set in the constructor a class property like this:
public function __construct() {
$this->a = 'ABC';
}
Now my IDE told me that the property was declared dynamically and I should add this property to my class. Now I have two options:
A variable at the top of the class:
protected string $a = '';
Or an annotation in the class doc:
/**
* Class ABC
*
* #property string a
*
* #package Johnny
*/
class ABC {
So whats the difference here and which one should I use? Sometimes I have an error that a property is not defined when using the annotation above so the fix was a protected or private variable.
Thanks for you help!
A protected property can only be accessed from methods in the same class or subclasses. Declaring the property protected prevents it from be assigned or read outside the class.
Adding the #property annotation in a docblock simply lets the IDE know that the property exists. It will use this to suppress warnings like the one you got, and do property name completion, just like it does for properties that are declared explicitly in the class definition. It has little effect on the way PHP itself deals with the property; access control is specified by whether the property is declared public, private, or protected.
You can also create public and private properties in the class definition.
public string $a;
private string $a;
Public means the property can be accessed from outside the class (just like your dynamically-created property), private means it can only be accessed from the class itself (not subclasses).
If you don't declare a property explicitly, and create it dynamically using an assignment, it's automatically public. If you want to prevent this, see Is there a way to disable adding properties into a class from an instance of the class?
This is an explicit declaration of a property type:
protected string $a = '';
This is an internally enforced restriction. If you try to assign something other than a string to $a, you'll get a TypeError exception. Declaring a property type hint like this is a feature that was introduced in 7.4. You should prefer this method if you know your environment will be 7.4+.
This is a docblock:
/**
* #var string
*/
public $a;
It's a comment that has no effect on the runtime of your script. It exists only so that IDEs like PHPStorm or NetBeans can provide hints in your development environment. If you use explicit type hints like above, then these docblock declarations are redundant and unneeded. I.e., there's no need to do this:
/**
* #var string
*/
public string $a;
Note there are quite a few libraries that use comment docblocks to provide special runtime meaning. These libraries use reflection to parse docblock comments on the fly and react to them. In other words, PHP itself is not affected by docblock comments, but your script has the ability to look at them, and is thus capable of basing conditions off them. For example, with Doctrine, you can use docblock comments to explain what your database fields look like:
/**
* #ORM/Column(type="int")
* #ORM/Id
*/
protected $id;

PHPDocumentor. Can I add link to property from it's getter description?

/**
* #property $Property
*/
class SomeClass {
public function __get($name){
return $this->{'get'.$name};
}
/**
* Some description
* #return bool
*/
public function getProperty(){
return true;
}
}
So the question is - how can I see description from getProperty() by viewing documentation of $Property? Or just see link to getProperty() documentation...
The question seems to be the reverse of the title. Do you want to look at the property and see the getter's description, or do you want to look at the getter and see the property's description?
I'll assume you want both. However, you can't actually get either. At most, one's description could contain a link to the other, but not actually contain the other's description in its own description.
Here, the property's description will contain a link to the getter's doc.
/**
* #property $Property is controlled by {#link getProperty()}.
*/
class SomeClass {
public function __get($name){
return $this->{'get'.$name};
}
/**
* Gets the value of {#link $Property}.
* #return bool
*/
public function getProperty(){
return true;
}
}
There are two complications here: with regard to how magic things appear in the actual docs (and how IDEs display them); and with whether or not the {#link} inline tags actually do anything.
In phpDocumentor 1.x, magic stuff only appears as extra information listed on the class itself. In phpDocumentor 2.x, both magic properties and magic methods will appear as if they were true properties and methods. The 2.x behavior is a strong improvement. For IDEs, and I can only speak for Eclipse PDT, I see that it matches the 1.x behavior.
In phpDocumentor 1.x, the inline {#link} tag does function, and normally becomes a hyperlink to the document for the element (property, method) that it points to. However, since 1.x does not actually create a dedicated doc for magic things identified by #property and #method, then "{#link $Property}" cannot actually point to anything. It's possible that the text in the class docblock where the "#property $Property" description is shown might correctly show a link to getProperty(), but only because getProperty() is a true method, and as such it has its own doc. Had getProperty() been a magic method denoted by "#method getProperty()", then "{#link getProperty()}" would not have anywhere to point to.
In phpDocumentor 2.x, the inline {#link} tag is not implemented, and therefore it will end up just a visible text as if it had no tag purpose. Once 2.x implements this inline tag, then my solution above should be able to solve both of your potential questions.
I think the best you can manage is
#property $Property
#see getProperty
Use a class-level PHPDoc comment
/**
* #method string getMyFirstProperty() Return value of the property called first
* #method float getMySecondProperty() Return value of the property called second
*/
And yes, magic getters will appear in the IDE, which is really what makes it useful

Eclipse IDE: Code completion for the private and protected properties accessed by magic functions

As it states that it's ok to answer my own question and having found some trick to achieve code completion in Eclipse IDE (for PHP) I would like to share this with other users.
I found some solution here but somehow I can't make doxygen work properly with such declared properties, I found some workaround.
The problem
If you use magic methods, especially for property overloading __get(), __set(), (probably it concerns also __call() and __invoke()), there is a problem, that property names defined in somehow dynamic (as variable variables) and not visible in any scope. It is possible because their names are passed as strings and can be manipulated in any way.
So it is not possible to have those magically accessed properties (or methods) in code completion, and in my case (don't know why, but it doesn't matter), in the generated documentation of the class.
(The code-completion is when the editor helps the programmer by showing all possible properties and methods, thus letting avoid some errors.)
Consider we have the following class:
/**
* Test class
*/
class myClass {
private $field_someValue1;
private $field_someValue2;
/**
* Magic method getter for hidden properties.
* #param string $name
* #return mixed
*/
public function __get($name){
switch($name){
case 'foo': return $this->$field_someValue1; break;
case 'bar': return $this->$field_someValue2; break;
default:
// handle non-existing property error here
}
}
/**
* Simply do nothing, but be some public part of the class.
* #return void
*/
public function doNothing(){
}
}
$a = new myClass();
So in my code when I type $a-> the editor should help me by hinting that there are two properties for my object: foo and bar. Of course it can't show $field_someValue1 and $field_someValue2 as they are private.
How to make Eclipse help me?
The solution
My solution (or rather workaround) is to create a new file that will contain the same classes names as in the main files of the project. I created a special directory for that.
There I can easily declare all the hidden properties I access via __get() (__set(), __isset() etc.) like this:
class myClass {
/**
* Some accessible hidden property.
* #var string $foo
*/
public $foo;
/**
* Another accessible hidden property.
* #var bool $bar
*/
public $bar;
}
And that's all.
This makes Eclipse allow help me by hinting the class's properties (it combines all properties of two same-named classes) and also gives doxygen the proper info for documentation.
The problem is doxygen will generate this file in its "Files" section; if you don't care, it's ok.
Please note that in my "documentation file" I did not need to re-type the doNothing() method as it's visible (because it's public).
Hope this helps to anyone.
More elegant would be use phpdoc #property in the same class file:
/**
* Test class
* #property foo $foo
* #property bar $bar
*/
class myClass {
private $field_someValue1;
private $field_someValue2;

NetBeans autocomplete & PHP; force __get() type

Quick one on NetBeans 7.0 and autocomplete for PHP;
I'm trying to figure out (if possible) how to force __get() implemented in a class to return (refer to) a certain type, the type being the same class in which __get() is implemented, always.
Right now, I have (in View):
/**
* #param string $key
* #return View
*/
public function __get($key){
return $this->getView($key);
}
Accessed like so:
$view->foo-> // should populate with methods from View
^
Now I've been reading about the #property, but I'm not sure if that's correct for what I'm doing. The other thing is (and this would be a nice feature if possible) typically views are nested, so it's not uncommon in my implementation to see this:
$view->foo->bar->baz-> // should populate with methods from View
^
Any idea on how to force this, or am I stuck?
Update:
So #property seems to be heading the correct direction, however there doesn't seem to be support for wildcarding the property names. So to elaborate on my question, does anyone know of any NetBeans plugins, or undocumented (or just plain hard to find) PHPDoc syntax for supporting wildcard #property names?
I'm thinking in one of these directions:
/**
* #property View *
* #property View ...
* #property View $var,...
*/
Of course, none of these variations work, however the last would seem most logical, as they seem to support a similar syntax for variadic function parameter lists.
Netbeans can work that magic for you with the #property like shown in the example below.
As you already have figured out you will have to define each property in the doc block.
Another possible solution for your $x->y->z->view example is listed below.
Copy & paste this into Netbeans and it will show the methods of the Bar class:
<?php
/**
* #property Bar $prop
*/
class foo {
}
class bar {
public function xyz() {
}
public function abc() {
}
}
$x = new foo();
$x->prop->
When you move the cursor here and press ctrl+space you will see:
If you want autocomplete for a longer resulton chain you can also use
/** #var Viewclass $foo */
$foo = $x->y->z->view;
$foo->autoCompleteWorksNow();
anywhere in your code.

Variable type hinting in Netbeans (PHP)

Just curious if there's a way in netbeans to give type hints for regular variables, so that intellisense picks it up. I know you can do it for class properties, function parameters, return types, etc. but I can't figure out how to do it for regular variables. It's something that would really help in situations where you have a method that can return different object types (like a service locator).
ex something like:
/**
* #var Some_Service $someService
*/
$someService = ServiceLocator::locate('someService');
Where using $someService afterward, netbeans would provide all available methods defined in the class Some_Service.
A single line is all you need:
/* #var $varName Type_Name */
See this article in the NetBeans PHP Blog: https://blogs.oracle.com/netbeansphp/entry/defining_a_variable_type_in
Note: At least, in version 8.2; The key seems to be:
The single asterisk (/* instead of /**).
Placing the type after the variable name.
Having nothing before and after the type-hinting
(except white-space, but even that is not allowed
when the comment is not in a single line).
I know this is an older question, but I was looking for a similar answer for Eclipse/Zend Studio and this solved it as well.
**Note though that it must be on a single line with the opening and closing explicitly in this style...
/* #var $varName Type_Name */
No other formats whether...
/**
* #var $varName Type_Name
*/
or...
// #var $varName Type_Name
seemed to work at all. Hope that helps someone.
Are you looking to document those pesky magic variables? (I did; This question currently ranks top result for that in Google. I hope this helps someone!)
The #property tag allows you to document magic php variables - those implemented using __get() and __set(). The tag should be used in the documentation immediately preceding the class definition:
/**
* Class Contact
* #property string $firstName
* #property string $lastName
*/
class Contact extends Model {
...
This notation triggers autocomplete, tested in Netbeans 8.1 and PhpStorm 2016.1.
According to this bug report, the syntax will change in NetBeans 9:
/* #var $variable VarType */ // vdoc1 (legacy syntax)
/** #var VarType $variable */ // vdoc (new syntax)
Also, it's worth mentioning that you can append [] to a class name to indicate an array of objects:
/* #var $foos Foo[] */
$foos = // ...
foreach ($foos as $foo) {
// $foo will be hinted as Foo here
}
And don't forget your use statement, e.g. use Foo;
In netbeans 8.0.2, the vdoc template gives you this:
/* #var $variable type */
Netbeans will not recognize this however, and will not give you the correct autocomplete list for your objects. Instead use this, just before your variable declaration :
/** #var objectType $varName */
I have not really seen a great use for the stock vdoc Template, especially for class variables that are going to be used as PDO or PDOStatement objects.
One solution I use is actually to go into
Tools / Options / Editor / Code Templates (with PHP selected as your Language), and add a new Template. I called mine hint . Then under Expanded Text, use the following template:
/** #var ${VAR_TYPE variableFromNextAssignmentType default="ClassName"} $$${VARIABLE variableFromNextAssignmentName default="variable"} */
For NetBeans IDE 8.2 syntax is like this:
class foobar{
/** #var string $myvar: optional description here **/
protected static $myvar;
}
This will provide the type hints properly for static variables at least.

Categories