6

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?

Community
  • 1
  • 1
TheHud
  • 347
  • 3
  • 10

2 Answers2

0

You can't override a trait, but you can rename it.

An example of it here!

https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L47-L50

geggleto
  • 2,605
  • 1
  • 15
  • 18
  • I'm not sure that helps in my scenario - I need to define the mapping against the $tags property, but I don't see how that can work when you rename the properties - the methods in the trait would still have to reference the property I'm having to define in the implementations. :\ – TheHud Aug 07 '15 at 08:18
0

Late, but it might help someone. You can use association or attributes override (annotations @AssociationOverrides, @AttributeOverrides) as described in section 6.4. Overrides.

kabirbaidhya
  • 3,264
  • 3
  • 34
  • 59
brano111
  • 1
  • 2