Netbeans Intellisense PHP Iterator Interface - php

I'm using Netbeans 6.9 and writing a PHP class that implements the Iterator interface. I would like to have the IDE offer Intellisense as I iterate over the items in my object. It seems to work for the Zend Framework as I've noticed that when iterating over a Zend_Db_Rowset I get intellisense for a Zend_DB_Row. For example, when I write:
foreach($rowset as $row) {
$row->delete();
}
When I type "$row->" Netbeans pops up its code hints for the member functions of Zend_Db_Row_Abstract. Unfortunately, I can't get this to work for my own code. Below is a sample I tried to get to work:
class Foo {
private $value;
/**
*
* #param string $value
*/
public function setValue($value) {
$this->value = $value;
}
/**
*
* #return string
*/
public function getValue() {
return $this->value;
}
}
class It implements Iterator {
private $data;
public function __construct($data) {
$this->data = $data;
}
/**
*
* #return Foo
*/
public function current() {
return current($this->data);
}
/**
*
* #return Foo
*/
public function key() {
return key($this->data);
}
/**
*
* #return Foo
*/
public function next() {
return next($this->data);
}
/**
*
* #return Foo
*/
public function rewind() {
return reset($this->data);
}
/**
*
* #return bool
*/
public function valid() {
return key($this->data) !== null;
}
}
$a = new Foo();
$b = new Foo();
$a->setValue('Hello');
$b->setValue('Bye');
$testData = array($a, $b);
$myIt = new It($testData);
foreach ($myIt as $obj) {
echo $obj->getValue();
}
Strangely the intellisense seems to think $obj is an object of type It when I want it to think (and it actually is) an object of type Foo.

Within the body of the loop you can provide the type hint in a comment.
/* #var $obj Foo */
+1 for Brian Fisher's suggestion.

Related

change parameter value of dependent method in phpunit

i wrote a sample test case for collection like class but weird thing about this is in my testAdd method that i add a item in CustomCollectionService and it changed my parameter too. how can this happend?
class CustomCollectionService
{
/**
* #var Collection $collection
*/
public $collection;
public function makeCollection($arr)
{
$this->collection = collect($arr);
}
/**
* #param Collection $collection
*/
public function setCollection(Collection $collection): void
{
$this->collection = $collection;
}
/**
* #return mixed
*/
public function getCollection()
{
return $this->collection;
}
public function add($item)
{
return $this->collection->add($item);
}
}
and this is my test:
class CustomCollectionTest extends TestCase
{
public $collectionService;
public $collection;
protected function setUp(): void
{
$this->collectionService = new CustomCollectionService();
}
public function testCollectionCreator()
{
$arr = ['sina','1',5];
$this->assertIsArray($arr);
return $arr;
}
/**
* #param $arr
* #depends testCollectionCreator
*/
public function testAction($arr)
{
$this->collectionService->makeCollection($arr);
$this->assertIsArray($this->collectionService->getCollection()->toArray());
return $this->collectionService->getCollection();
}
/**
* #depends testAction
*/
public function testAdd($col)
{
$actualCount = $col->count();
$this->collectionService->setCollection($col);
$manipulatedCollection = $this->collectionService->add(['xx']);
dump($actualCount); // 3
dump($col->count()); //4
$this->assertEquals($actualCount+1, $manipulatedCollection->count());
}
}
Because it is an object. So when you pass the $col object to the CollectionService and call the add method within the CollectionService, it is still the $col object from your test method that is being used.

json_encode empty with no error [duplicate]

This question already has answers here:
PHP class instance to JSON
(5 answers)
Closed 4 years ago.
I got an object. I need to turn into JSON for storage but when I try to encode it into JSON it returns an empty JSON object. When I tried to use json_last_error.
The code I used
echo $payload["sub"];
echo json_encode($user);
echo json_last_error_msg();
The result I get
"102573480781696194937{}No error".
The User class I'm trying to encode
<?php
/**
* Created by PhpStorm.
* User: Student
* Date: 13-4-2018
* Time: 10:40
*/
namespace php;
class User
{
private $isAdmin = false;
private $registeredFood = array();
private $googleID;
private $name;
private $notes = array();
private $email;
/**
* User constructor.
* #param $googleID
*/
public function __construct($googleID)
{
$this->googleID = $googleID;
}
/**
* #return mixed
*/
public function getGoogleID()
{
return $this->googleID;
}
/**
* #return bool
*/
public function isAdmin()
{
return $this->isAdmin;
}
/**
* #param bool $isAdmin
*/
public function setIsAdmin($isAdmin)
{
$this->isAdmin = $isAdmin;
}
/**
* #return array
*/
public function getRegisteredFood()
{
return $this->registeredFood;
}
/**
* #param array $registeredFood
*/
public function setRegisteredFood($registeredFood)
{
$this->registeredFood = $registeredFood;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return array
*/
public function getNotes()
{
return $this->notes;
}
/**
* #param array $notes
*/
public function setNotes($notes)
{
$this->notes = $notes;
}
/**
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
/**
* #param mixed $email
*/
public function setEmail($email)
{
$this->email = $email;
}
}
?>
I hope someone can help me
It is because your class's properties are private.
An example class with only private properties ...
php > class Foo { private $bar = 42; }
php > $obj = new Foo();
do not expose values:
php > echo json_encode($obj);
{}
But an example class with public properties ...
php > class Bar { public $foo = 42; }
php > $objBar = new Bar();
do it!
php > echo json_encode($objBar);
{"foo":42}
\JsonSerializable
PHP provide an'interafce \JsonSerializable that require a method jsonSerialize. This method is automatically called by json_encode().
class JsonClass implements JsonSerialize {
private $bar;
public function __construct($bar) {
$this->bar = $bar;
}
public function jsonSerialize() {
return [
'foo' => $this->bar,
];
}
}
I prefer this solution because is not good to expose publicly properties
serialization and unserialization ...
If you need to serialize and unserialize php object you can ...
php > class Classe { public $pub = "bar"; }
php > $obj = new Classe();
php > $serialized = serialize($obj);
php > $original = unserialize($serialized);
php > var_dump($original);
php shell code:1:
class Classe#2 (1) {
public $pub =>
string(3) "bar"
}
$serialized variable contains O:6:"Classe":1:{s:3:"pub";s:3:"bar";}. As you can see is not a json, but is a format that allow you to recreate original object using unserialize function.
You have a couple of options here.
Option 1: Make your class properties public
Like what sensorario mentioned, change the visibility of your properties so that it is accessible from outside the class, which is where you are calling json_encode.
Option 2: Introduce a method/function within the class to return the encoded JSON object
Have a toJson() function inside your User class.
Of course, there are way more options - such as extending User so that User is not "contaminated", etc.
But yup, the general problem is your private properties.

PhpStorm type hinting array of objects fails after testing with is_array

I am having trouble getting Phpstorm type hints working on arrays of objects when I test the array with is_array() before iterating over the array.
Can anyone shed some light on why is_array() removes the type hinting of the objects?
$test = new Test();
$testers = $test->getAll();
// Type hinting WORKS for $test
foreach($testers as $test) {
$test->getId(); // Type hinting works
}
// Type hinting does NOT work for $test
if(is_array($testers)) {
foreach($testers as $test) {
$test->getId(); // Type hinting does NOT work
}
}
I can get type hinting to work if I add type hint comment where the array is retrieved, but this is undesirable, as I would prefer Phpstorm to use the object method return type hint info instead of having to specify it all the time:
Adding this works even when is_array is present
/** #var Tester[] $testers */
$testers = $test->getAll();
Test class code in case anyone wants to run the example:
class Tester {
private $id;
private $name;
public function __construct($id, $name) {
$this->id = $id;
$this->name = $name;
}
/**
* #return Integer
*/
public function getId() {
return $this->id;
}
/**
* #return String
*/
public function getName() {
return $this->name;
}
}
class Test {
/**
* #return tester[]
*/
public function getAll() {
$testers = array(
new Tester(1, 'Bob'),
new Tester(2, 'Jane'),
new Tester(3, 'Tim')
);
return $testers;
}
}

How to add more value to a single array in the same function?

When I try the following code, I get just the first output. I wanted to append all the outputs to the array self::$results so that the same function will return that array, but after running the script, the function returns the array but only the first output. That means, it appended only the the first output.
<?php
/**
* #author Ewoenam
* #copyright 2014
*
* #odj class book
*/
class book
{
/**
* #array static $alpha; holds array of accepted words
*/
public static $alpha = array();
/**
* #array static $result; holds array of correct answers
*/
public static $results;
/**
* #string protected $word; parametr
*/
protected $word;
/**
* #var static $alpha; holder of class instance getter
* returns self::getInstance
*/
public static $init;
/**
* #method static getInstance(); class instance getter
* returns self();
*/
function __construct()
{
self::$alpha = array('love','life','health','power','money','God');
}
public static function getInstance()
{
if (self::$init === null)
{
self::$init = new self();
return self::$init;
}
}
/**
* #method static check()
* takes 1 param; self::$word
* returns bool
*/
public static function check($word)
{
for($i=0;$i<=count(self::$alpha)-1;$i++)
{
if(similar_text($word,self::$alpha[$i]) === strlen($word))
{
return true;
}
}
}
/**
* #method static result()
* takes 1 param; self::check()
* returns bool
*/
public static function result($bool)
{
if($bool === true)
{
return 'correct';
}
else
{
return 'wrong';
}
}
/**
* #method static getter()
* takes 1 param; array of words to be searched
* returns array self::$results
*/
public static function getter($array)
{
self::$results = array();
for($i = 0;$i<=count($array)-1;$i++)
{
// i want to add more thn one answers to to $result array but i get only the first answer.
//how do i ddo it?
self::$results[] = self::result(book::check($array[$i]));
return self::$results;
}
}
}
$array = array('love','ama','kofi','money','health','God');
print_r(book::getInstance()->getter($array));
var_dump(book::check('love')) ;
?>
You're returning from $getter inside the loop, so it returns after adding the first element. You should finish the loop and then return:
public static function getter($array)
{
self::$results = array();
for($i = 0;$i<=count($array)-1;$i++)
{
self::$results[] = self::result(book::check($array[$i]));
}
return self::$results;
}
You have your return in the for loop. That's why when it goes through the first time, it returns the function right there instead of continuing the loop.
Change your function to this and it will work how you want it to:
/**
* #method static getter()
* takes 1 param; array of words to be searched
* returns array self::$results
*/
public static function getter($array)
{
self::$results = array();
for($i = 0;$i<=count($array)-1;$i++)
{
// i want to add more thn one answers to to $result array but i get only the first answer.
//how do i ddo it?
self::$results[] = self::result(book::check($array[$i]));
}
return self::$results;
}

PHPDoc and late (static or dynamic) binding

Most PHP IDEs rely on phpdoc to get hints about the type of an expression. Yet, I use frequently this pattern, which doesn't seem to be covered:
class Control {
private $label = '';
/** #return ??? */
public static function Make(){ return new static(); }
/** #return ??? */
public function WithLabel($value){ $this->label = $value; return $this; }
/** #return void */
public function Render(){ /* ... */ }
}
class Textbox extends Control {
private $text = '';
/** #return ??? */
public function WithText($text){ $this->width = $text; return $this; }
}
Now I can use the classes like this:
Textbox::Make() // <-- late static binding, returns Textbox
->WithLabel('foo') // <-- late dynamic binding, returns Textbox
->WithText('bar') // <-- normal binding, returns Textbox
->Render();
Is there any way to replace the '???'s with something so that the typing information is correct?
For static methods in classes that may be extended:
/** #return static */
For final-static methods:
/** #return Control */
For non-static methods:
/** #return $this */
but it's not documented in phpdoc manual
Note that nowadays any Intelij IED (like PhpStorm 2019), does support all three static, $this, and self (as return type in PhpDoc).
Updated answer taking as reference the most popular PHP IDE (PHPStorm 8):
For #return you can use:
self
$this
For #method you can use:
$this
Example:
/**
* Class Model
* #method $this parentMethodA
*/
class Model
{
/**
* #return $this
*/
public function parentMethodB()
{
return $this;
}
/**
* #return self
*/
public function parentMethodC()
{
return $this;
}
}
/**
* Class Person
* #method $this childMethodA
*/
class Person extends Model
{
/**
* #return $this
*/
public function childMethodB()
{
return $this;
}
/**
* #return self
*/
public function childMethodC()
{
return $this;
}
}
$p = new Person();
//In the following lines IDE will recognize those variables as:
$t1 = $p->parentMethodA(); //Instance of Person
$t2 = $p->parentMethodB(); //Instance of Person
$t3 = $p->parentMethodC(); //Instance of Model
$t4 = $p->parentMethodA(); //Instance of Person
$t5 = $p->parentMethodB(); //Instance of Person
$t6 = $p->parentMethodC(); //Instance of Person
Update for PHPStorm 10 (EAP)
It seems that now static can be used too, but only for #return.
Updated cvsguimaraes' answer to include static options:
/**
* Class Bar
* #method $this parentMethodA
*/
class Bar
{
/**
* #return $this
*/
public function parentMethodB()
{
return $this;
}
/**
* #return self
*/
public function parentMethodC()
{
return $this;
}
/**
* #return static
*/
public static function staticMethod()
{
return new static();
}
/**
* #param $id
*
* #return bool
*/
public function load($id)
{
// test
return $id ? true : false;
}
/**
* #param null $id
*
* #return static
*/
public static function get($id = NULL){
$obj = static::staticMethod();
if (is_null($id)) {
return $obj;
}
if ($obj->load($id)) {
return $obj;
}
return false;
}
}
/**
* Class Foo
* #method $this childMethodA
*/
class Foo extends Bar
{
/**
* #return $this
*/
public function childMethodB()
{
return $this;
}
/**
* #return self
*/
public function childMethodC()
{
return $this;
}
}
/**
* Class Bar
*/
class Baz extends Bar
{
}
$p = new Foo();
/** #var Foo $Foo */
$Foo = 'Foo';
$Baz = 'Bar';
// IntelliJ recognizes the following as:
$t1 = $p->parentMethodA(); //Instance of Foo
$t2 = $p->parentMethodB(); //Instance of Foo
$t3 = $p->parentMethodC(); //Instance of Model
$t4 = $p->childMethodA(); //Instance of Foo
$t5 = $p->childMethodB(); //Instance of Foo
$t6 = $p->childMethodC(); //Instance of Foo
$t7 = $Foo::staticMethod(); //Instance of Foo
$t8 = Foo::staticMethod(); //Instance of Foo
$t9 = $p::staticMethod(); //Instance of Foo
$t10 = $Foo::get(); //Instance of Foo
$t12 = Bar::get(); //Instance of Bar
$t11 = $Baz::get(); // Unknown

Categories