Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PhpStorm Trait method autocompletion does not work

Tags:

oop

php

phpstorm

I have a problem with an autocompletion in PhpStorm...

class Main
{
    use Something;

    /**
     * @var SplObjectStorage
     */
    private $container;

    public function __construct()
    {
        $this->container = new SplObjectStorage();
    }

    public function addSth()
    {
        $this->add();
    }
}


trait Something
{
    public function add()
    {
        $this->container->attach(new stdClass());
    }
}

$m = new Main();
$m->add();

var_dump($m);  

Everything works fine but $this->container->attach(new stdClass()); throws that method attach is not found... Anyone can help? I think that properly configured PHPDoc should help.

like image 917
Mati Avatar asked Jul 26 '16 18:07

Mati


2 Answers

The Trait has no way of knowing what type its $container is. In your example it is SplObjectStorage, but what if it isn't?

You need to place $container inside the Trait as well and declare it as SplObjectStorage. Then it should work. This way, you'll also be sure that whoever is declaring that Trait actually has a $container to have it work on.

trait Something {
    /**
     * @var SplObjectStorage 
     */
    private $container;

    ...

I suppose you can force the issue:

public function add()
{
    /**
     * @var $cont SplObjectStorage 
     */
    $cont = $this->container;
    $cont->attach(new stdClass());
}
like image 65
LSerni Avatar answered Sep 20 '22 10:09

LSerni


There's a couple of other ways to make this work.

  1. Define $container inside the trait (as @Iserni suggested), but define the variable itself. This actually makes more sense to define it within the trait anyways, since the trait methods actually rely on it.

    trait Something {
        /** @var \SplObjectStorage */
        protected $container;
    
        public function add() {
            $this->container->attach(new stdClass());
        }
    }
    
  2. Pass it as an argument in your function

    public function add(\SplObjectStorage $container) {
        $container->attach(new stdClass());
    }
    

PHPStorm has to have a way to refer back to the class to do things like autocomplete. Your trait cannot inherit its docs from the calling class. Your class, however, can inherit docs from the included trait.

like image 35
Machavity Avatar answered Sep 17 '22 10:09

Machavity