phpDoc and Code Completion via '->' T_OBJECT_OPERATOR in NetBeans 8.0 - php

How can code completion occur with phpDoc blocks loaded using the T_OBJECT_OPERATOR without having to preset the variables as is shown is the source below?
The only class that matters is the parentExample as it set's the needed $cc that does offer a working solution but it is not desired to preset variables in this manner.
The example code shows the undesired solution and multiple non-working attempts.
As code completion is based on previously set information, preferred to use the full example script not just pieces. Also, as it does relate to phpDocumentor basic phpDoc blocks were included as well. It is desired that these docBlocks get loaded as part of the code completion not just named objects.
<?php
/**
* This is a parent class.
*
* #package Examples/doubledVars
*/
class parentExample
{
/* #var $a parentExample */
public $a;
/**
* This is a var named b
* #var $b parentExample
*/
public $b;
public $c;
public $cc;
// notice^ <------------------------------------------------------SEE ME
/**
* A basic contructor
*/
public function __construct()
{
echo '::PE Class initiated::';
$this -> a = 'we are value "a" in the parent class';
$this -> b = 'we are value "b" in the parent class';
$this -> c = 'we are value "c" in the parent class';
}
}
/**
* This is an Example of doubling occuring due to failed to __construct()
*
* #package Examples/doubledVars
*/
class doubledVars extends parentExample
{
/**
* Value is obtained via parent constuctor.
*
* #return string assigned during construction of parent class.
*/
public function getA()
{
return $this -> a;
}
}
/**
* This is an Example of no doubling occuring due to __construct()
*
* #package Examples/doubledVars
*/
class noDouble extends parentExample
{
/**
* an empty constructor used to prevent doubling during construction.
* child class makes use of parent constructor unless it has it's own.
* or none exsist.
*/
public function __construct()
{
}
/**
* Empty string return
*
* Shows an example of returning values set based on the constructor
* class. In this case there is no default values set at any point, but
* rather value is assigned during the construction of a object.
*
* #return string This string is empty
*/
public function getB()
{
return $this -> b;
}
}
/**
* This is an Example of no doubling occuring due to __construct()
* #see noDouble
*
* #package Examples/codeCompletion
*/
class codeCompletion extends parentExample
{
/**
* #see noDouble::__construct()
*/
public function __construct()
{
//empty constructor prevents doubling
}
public function getC()
{
return $this -> c;
}
}
/** #var $parentExampleDV parentExample */
$parentExampleDV = new parentExample;
// Tried this for Code completion, it did not work <------------------SEE ME
/** #var $doubledVars doubledVars */
$parentExampleDV->doubledVars = new doubledVars;
/* output on next 'echo' will be as follows */
//::PE Class initiated::::PE Class initiated::we are in the parent class
echo '##'.$parentExampleDV->doubledVars->getA().'##';// NO CC <-------SEE ME
echo '<br><br>----------<br><br>';
/** #var $parentExampleDV parentExample */
$parentExampleND = new parentExample;
// Tried this for Code completion, it did not work <------------------SEE ME
/** #var $parentExample->noDouble noDouble */
$parentExampleND -> noDouble = new noDouble;
/* output on next 'echo' will be as follows */
//we are in the parent class
echo '!!'.$parentExampleND->noDouble->getB().'!!';// NO CC <----------SEE ME
echo '<br><br>----------<br><br>';
$parentExampleCC = new parentExample;
$parentExampleCC->cc = new codeCompletion;
echo '##'.$parentExampleCC->cc->getC().'##';//CC working <------------SEE ME
echo '<br><br>----------<br><br>';

I guess It is not possible at this time...

Related

How inform PhpStorm about method position used in DependencyInjection way, which it "thinks" that doesn't exist?

Is there any option to inform PhpStorm that method which it says that not exist, is beyond his scope and is defined somewhere else ?
In simpler words:
I have method execution:
Db::transactional($this)->transactionalUpdate($result);
I have got method definition also:
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...';
}
Unfortunately PhpStorm doesn't know that execution : ->transactionalUpdate($result); should run public function transactionalUpdate.
Is there any option to write PhpDoc or some other tag to inform it that in case of name refactorization it should change the original function name too ?
P.S. My class structure looks like this:
class Db
{
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
class ApiObject
{
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
}
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
EDIT AFTER ANSWER:
#Nukeface and #Dmitry caused me to come up with the answer on my Question:
Lets see again into my files structure:
class Db
{
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
class ApiObject
{
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
//EDIT//Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
/** #var self $thisObject */
//Line above informs PhpStorm that $thisObject is ApiObject indeed
$thisObject = Db::transactional($this)
$thisObject->transactionalUpdate($result);
}
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
You should make use of Typehints. Updated your code below:
/**
* Class Db
* #package Namespace\To\Db
*/
class Db
{
/**
* #param $object
* #return ApiObject (per your line comment)
*/
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
/**
* Class ApiObject
* #package Namespace\To\ApiObject
*/
class ApiObject
{
/**
* #return void (I see no "return" statement)
*/
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
}
/**
* #param ImportantObjectButNotMuch $baconWithButter
* #return void
*/
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
You can quickly create basic docblocks and typehints by typing /** then pressing either "enter" or "space". Enter if you want a docblock and space if you want a typehint.
Examples of own code below:
/**
* Class AbstractEventHandler
* #package Hzw\Mvc\Event
*/
abstract class AbstractEventHandler implements EventManagerAwareInterface
{
/**
* #var EventManagerInterface
*/
protected $events;
/**
* #var EntityManager|ObjectManager
*/
protected $entityManager;
/**
* AbstractEvent constructor.
* #param ObjectManager $entityManager
*/
public function __construct(ObjectManager $entityManager)
{
$this->setEntityManager($entityManager);
}
/**
* #param EventManagerInterface $events
*/
public function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers([
__CLASS__,
get_class($this)
]);
$this->events = $events;
}
/**
* #return EventManagerInterface
*/
public function getEventManager()
{
if (!$this->events) {
$this->setEventManager(new EventManager());
}
return $this->events;
}
/**
* #return ObjectManager|EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* #param ObjectManager|EntityManager $entityManager
* #return AbstractEventHandler
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
return $this;
}
}
In the above example, PhpStorm knows what every function requires and returns. It knows the types and as some "return $this" it knows about the possibility to chain functions.
As an addition, the above code example uses only "docblocks". Below some "inline typehints" from within a function. Especially useful when it's not going to be immediately clear what is going to be returned. That way, again, PhpStorm knows from where to get functions, options, etc. to show you.
/** #var AbstractForm $form */
$form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions));
/** #var Request $request */
$request = $this->getRequest();
As a final hint. If you create a bunch of properties for a class, such as in my example protected $events or protected $entityManager, you can also generate the getters & setters. If your properties contain the docblocks, it will also generate the docblocks for you on these functions.
E.g. the property below
/**
* #var EntityManager|ObjectManager
*/
protected $entityManager;
When using "Alt + Insert" you get a menu at cursor location. Choose "Getters/Setters". In the pop-up, select "entityManager" and check the box at the bottom for "fluent setters". Then the code below is generated for you:
/**
* #return ObjectManager|EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* #param ObjectManager|EntityManager $entityManager
* #return AbstractEventHandler
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
return $this;
}
The closes thing you can do to what you want to do is to use #return with multiple types.
/**
* #param $object
* #return ApiObject|AnotherApiObject|OneMoreApiObject
*/
public static function transactional($object)
{
return TransactionalProxy::newInstance($object);
}

Php typehinting in called method of object, created in base class

I have the following situation:
class Main {
function get() {
return new Query();
}
}
class Order extends Main {
public $id;
public $name;
}
class Query {
/**
* #return Main
*/
function execute() {
/// some code here
return $parsedObject;
}
}
When I use this code to execute() and get Order objects (as parsed object), I'm writing this:
$order = new Order();
$result = $order->get()->execute();
$result->id; /// typehint not works, cuz $result is type of Main, not more concrete type Order
So my question is - is there any way to pass a type of base (abstract class, interface) class implementation to method, that is called from that base class, for getting beautiful typehint of created object. Cuz i can create User, that extends Main class, with his own fields. But calling new User()->get()->excute() will give me the same result - an object of type Main
You can annotate just about anything, here is your code with everything annotated.
/**
* Class Main
*/
class Main {
/**
* #return Query
*/
function get() {
return new Query();
}
}
/**
* Class Order
*/
class Order
extends Main {
/** #var int */
public $id;
/** #var string */
public $name;
}
/**
* Class Query
*/
class Query {
/**
* #return Main
*/
function execute() {
/// some code here
return $parsedObject;
}
}

Code Completion When Using Factory Class

I am using Netbeans 8 for a Symfony2 project.
I have created a factory class for my model queries (they are static calls and mess up testing).
E.g
<?php
namespace My\Custom\Bundle\Classes\Factories;
use My\Custom\Bundle\Model\UserQuery;
class QueryFactory
{
/**
* Class name
* #access public
*/
const CLASS_NAME = __CLASS__;
/**
* newUserQuery()
*
* Creates a new user query object.
* #access public
* #return My\Custom\Bundle\Model\UserQuery
*/
public function newUserQuery()
{
return UserQuery::create();
}
}
What I want is for the auto complete to work on a variable that is created from a factory method (in this case the Propel methods for the User query).
<?php
namespace My\Custom\Bundle\Controller;
use My\Custom\Bundle\Classes\Factories\QueryFactory;
class ReportingController
{
private $queryFactory;
public function __construct(QueryFactory $query_factory)
{
$this->queryFactory = $query_factory;
}
public function fubar()
{
$user = $this->queryFactory->newUserQuery();
// now want auto complete on the $user (in this case the propel methods)
// $user->filterById(1);
}
}
Any ideas?
I think the problem is #return pointing to My\Custom\Bundle\Classes\Factories\My\Custom\Bundle\Model\UserQuery
try changing it to this
/**
* ...
* #return UserQuery
*/
Without the use statement it should be like this
/**
* ...
* #return \My\Custom\Bundle\Model\UserQuery
*/

PHPUnit-Skelgen 1.2.0 not creating Namespace

I have a sample class attached, that when I try to generate the test file for it, using the PHPUnit-Skelgen 1.2.0 on PHP 5.4.11, I do not get the namespace added to the file, so the test fails. However, all the methods are picked up.
Source File:
<?php
namespace lib\Parameters;
class COMMAND_LINE implements \Iterator
{
private $CommandLineOptions_ = array();
/**
* Create the Command Line Options Class
* #param boolean $AddHelpOption - Optionally add the -h/--help option automatically
*/
public function __construct($AddHelpOption = TRUE)
{
if( $AddHelpOption == TRUE)
{
}
}
/**
* An internal pointer to the current position in the Command Line Options
* #var integer
*/
protected $Position = 0;
/**
* This method takes the pointer back to the beginning of the dataset to restart the iteration
*/
public function rewind()
{
$this->Position = 0;
}
/**
* This method returns the value at the current position of the dataset
* #return COMMAND_LINE_OPTION
*/
public function current()
{
return $this->CommandLineOptions_[$this->Position];
}
/**
* Return the current value of the pointer
* #return integer
*/
public function key()
{
return $this->Position;
}
/**
* Move the pointer to the next element
*/
public function next()
{
++ $this->Position;
}
/**
* Returns where the next item is valid or not
* #return boolean
*/
public function valid()
{
return isset($this->CommandLineOptions_[$this->Position]);
}
}
?>
Command line, with the class in the current directory:
>phpunit-skelgen --test -- lib\Parameters\COMMAND_LINE COMMAND_LINE.class COMMAND_LINE_Test COMMAND_LINE.class.test
PHPUnit Skeleton Generator 1.2.0 by Sebastian Bergmann.
Wrote skeleton for "COMMAND_LINE_Test" to "COMMAND_LINE.class.test".
Test class created has the functions, but does not have the Namespace:
<?php
/**
* Generated by PHPUnit_SkeletonGenerator 1.2.0 on 2013-02-04 at 17:50:23.
*/
class COMMAND_LINE_Test extends PHPUnit_Framework_TestCase
{
/**
* #var COMMAND_LINE
*/
protected $object;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
$this->object = new COMMAND_LINE;
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown()
{
}
/**
* #covers lib\Parameters\COMMAND_LINE::rewind
* #todo Implement testRewind().
*/
public function testRewind()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* #covers lib\Parameters\COMMAND_LINE::current
* #todo Implement testCurrent().
*/
public function testCurrent()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* #covers lib\Parameters\COMMAND_LINE::key
* #todo Implement testKey().
*/
public function testKey()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* #covers lib\Parameters\COMMAND_LINE::next
* #todo Implement testNext().
*/
public function testNext()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* #covers lib\Parameters\COMMAND_LINE::valid
* #todo Implement testValid().
*/
public function testValid()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
}
Trying it from the root directory with relative file paths does not work either. If I use a fully qualified namespace (which I can not, as I need to be relative), then the class is not located, and only the setUp and tearDown methods are found.
You can give namespace to your generated test class like this.
>phpunit-skelgen --test -- lib\Parameters\COMMAND_LINE COMMAND_LINE.class lib\Parameters\COMMAND_LINE_Test COMMAND_LINE.class.test

Netbeans Auto-Complete Not Working For Custom PHP Class

I've got the following class in a Zend Framework project:
<?php
/**
* User's class
*
* This class should be responsible for all
*
* #author Steve Davies
* #copyright 2012
* #version SVN: $Id$
*/
class Api_Admin_Users extends Api_Core
{
/**
* Class Constructor
*
* #return void
*/
public function __construct() {
parent::__construct();
}
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
$user = self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
echo $user->getFullName();
}
}
However when I try and use code hinting on $user->getFullName();, it doesn't work.
Using the following trick from here, it works:
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
/* #var $user \UserManagement\Users */
$user = self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
echo $user->getFullName();
}
But, I don't want to have to include that comment line everytime I instantiate the object. When I try to move this to the Class definition - or even the method definition, it fails to work.
Can anyone provide an answer for this?
PHP is a dynamic language and as such it is not trivial to infer variable types from static code analysis (like it is in Java for example).
It's especially difficult with factory methods like yours getRepository('UserManagement\Users').
NetBeans currently has no way of knowing how to translate the function argument to the type of returned variable (unless you're satisfied with some parent class from which all subclasses returned by that factory derive). Unfortunatelly vdoc's are the only way to deal with such cases.
Create a method in Api_Admin_Users to access the repository and add the type hint there. This will benefit all methods in the class. As long as the methods in the repository are type-hinted correctly, you're all set.
class Api_Admin_Users extends Api_Core
{
/**
* Class Constructor
*
* #return void
*/
public function __construct() {
parent::__construct();
}
/**
* Get the repository
*
* #return \UserManagement\Users
*/
public static function getRepository() {
return self::_instance()->_em->getRepository('UserManagement\Users');
}
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
$user = self::getRepository()->find('1');
echo $user->getFullName();
}
}

Categories