I'm using traits to implement some Taggable behaviour in a Symfony app, using Doctrine2 for persistence, and annotations to configure that.
The main annoyance I have is that in the trait, my IDE has no idea of the type of $this->tags, and throws up a bunch of warnings. I'm being pretty OCD about getting my code documented here, so that it's really easy for other developers to pick up.
trait TaggableMethods {
    /** @var \Doctrine\Common\Collections\Collection */
    protected $tags; // <-- Can't seem to define here…
    public function addTag(Tag $tag) {
        $this->tags->add($tag);
    }
    public function removeTag(Tag $tag) {
        $this->tags->removeElement($tag);
    }
    public function getTags() {
        return $this->tags;
    }
}
class TaggableThingA {
    use TaggableMethods;
    /**
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\ManyToMany(targetEntity="Tag")
     * @ORM\JoinTable(name="ThingA__Tag")
     */
    protected $tags; // <--… because PHP complains about this
}
class TaggableThingB {
    use TaggableMethods;
    /**
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\ManyToMany(targetEntity="Tag")
     * @ORM\JoinTable(name="ThingB__Tag")
     */
    protected $tags;
}
My problem, so far as I can tell, is that I can't define the $tags property in the trait, as I need to override the annotations.
I can avoid defining $tags at all in TaggableMethods, but to me, this breaks encapsulation, or at least makes the code a little harder to read.
I can configure persistence using Yaml or XML, but all the rest of my entities use annotations.
So I'm looking for a way to avoid the runtime notice that gets generated, which Symfony turns into a ContextErrorException, killing my script during development.
This is probably related to "can we use traits to map manyToOne relationship with doctrine2?" and "Traits - property conflict with parent class"
Also, the behaviour for inherited methods mentioned in "PHP 5.4: why can classes override trait methods with a different signature?" sounds very close to what I want for properties - can anyone explain why the difference between properties and methods exists?
 
     
     
     
    