Doctrine Common
  1. Doctrine Common
  2. DCOM-3

Public value property in Base annotation class

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0.0-BETA2
    • Component/s: None
    • Labels:
      None

      Description

      1) If our annotation doesn't need any parameters, it stll can accept one ('value').
      2) We can intercept set and get of annotation properties via __set and __get methods which is not final, but not for 'value'.
      Example of interception

      class Annotation extends \Doctrine\Common\Annotations\Annotation
      {
      
          private $someProperty;
          
          public function __set($name, $value)
          {
              $setMethod = 'set' . ucfirst($name);
              if (method_exists($this, $setMethod)) {
                  return $this->{$setMethod}($value);
              }
              return parent::__set($name, $value);
          }
          
          public function __get($name)
          {
              $getMethod = 'get' . ucfirst($name);
              if (method_exists($this, $getMethod)) {
                  return $this->{$getMethod}();
              }
              return parent::__get($name);
          }
      
          public function getSomeProperty()
          {
              //some logic
              return $this->someProperty;
          }
      
          protected function setSomeProperty($someProperty)
          {
              //some logic
              $this->someProperty = $someProperty;
          }
      }
      

        Activity

        Hide
        Benjamin Eberlei added a comment -

        Why is this even relevant? can't you just ignore the value property?

        Show
        Benjamin Eberlei added a comment - Why is this even relevant? can't you just ignore the value property?
        Hide
        Roman S. Borschel added a comment - - edited

        I think there is something not clear here. __get and __set on Annotation are not used to set or get values but to intercept calls to non-existant values.
        Annotations are populated through their constructors.

        Second, you don't need to extend from Annotation (not in HEAD at least). Any class can be used as an annotation as long as it has a constructor that takes an array with values.

        Annotation values are set through the constructor, not through setters or public properties. This allows you to even use immutable classes as annotations:

        class MyClass {
             private $a, $b;
             public function __construct(array $values) {
                  $this->a = $values['a'];
                  $this->b = $values['b'];
             }
            //... only getters...
        }
        
        /** @MyClass(a="Hello", b="World") */
        class Other {
            //...
        }
        

        The default "value" will still be in $values['value'] if set. So this should work, too:

        class MyClass {
             private $value;
             public function __construct(array $values) {
                  $this->value = $values['value'];
             }
            //...
        }
        
        /** @MyClass("Hello World") */
        class Other {
            //...
        }
        
        Show
        Roman S. Borschel added a comment - - edited I think there is something not clear here. __get and __set on Annotation are not used to set or get values but to intercept calls to non-existant values. Annotations are populated through their constructors. Second, you don't need to extend from Annotation (not in HEAD at least). Any class can be used as an annotation as long as it has a constructor that takes an array with values. Annotation values are set through the constructor, not through setters or public properties. This allows you to even use immutable classes as annotations: class MyClass { private $a, $b; public function __construct(array $values) { $ this ->a = $values['a']; $ this ->b = $values['b']; } //... only getters... } /** @MyClass(a= "Hello" , b= "World" ) */ class Other { //... } The default "value" will still be in $values ['value'] if set. So this should work, too: class MyClass { private $value; public function __construct(array $values) { $ this ->value = $values['value']; } //... } /** @MyClass( "Hello World" ) */ class Other { //... }
        Hide
        Roman S. Borschel added a comment -

        So my suggestion would be: Just don't extend from Doctrine\Common\Annotations\Annotation and you don't have the public $value property.

        Show
        Roman S. Borschel added a comment - So my suggestion would be: Just don't extend from Doctrine\Common\Annotations\Annotation and you don't have the public $value property.
        Hide
        Kirill chEbba Chebunin added a comment -

        Oh, i got it. It was my miss, because there was subclass checking in previous versions.
        Also, is it a good idea not to have some base class or interface for all annotations, may be it will be better to have an interface with a constructor? based on this restriction
        "Any class can be used as an annotation as long as it has a constructor that takes an array with values". Of course using constructors in interfaces not really good, but if we have such restriction...
        For example

        interface SomeCommonAnnotationInterface
        {
            public function __construct(array $values);
        }
        
        Show
        Kirill chEbba Chebunin added a comment - Oh, i got it. It was my miss, because there was subclass checking in previous versions. Also, is it a good idea not to have some base class or interface for all annotations, may be it will be better to have an interface with a constructor? based on this restriction "Any class can be used as an annotation as long as it has a constructor that takes an array with values". Of course using constructors in interfaces not really good, but if we have such restriction... For example interface SomeCommonAnnotationInterface { public function __construct(array $values); }

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Kirill chEbba Chebunin
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: