Re: some notes about traits

From: Date: Wed, 16 Nov 2011 09:11:02 +0000
Subject: Re: some notes about traits
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-56339@lists.php.net to get a copy of this message
On 16 November 2011 00:17, Rasmus Schultz <rasmus@mindplay.dk> wrote: > Here's a better example of something useful that actually works: > >  trait Accessors >  { >    public function __get($name) >    { >      return $this->{'get'.$name}(); >    } > >    public function __set($name, $value) >    { >      $this->{'set'.$name}($value); >    } >  } > >  class OrderLine >  { >    use Accessors; > >    public $price; >    public $amount; > >    public function getTotal() >    { >      return $this->price * $this->amount; >    } >  } > >  $line = new OrderLine; > >  $line->price = 20; >  $line->amount = 3; > >  echo "Total cost: ".$line->total; I like that example. It shows, at a fairly simple level, the ability to compose a class from potentially multiple traits. Putting the __magic_methods in a trait, what a great idea. This mechanism is allows for all sorts of easy to expand ideas. You _COULD_ use this trait to implement discrete getters and setters ... <?php /** * Trait to provide setter and getter functionality * with an exception for any missing method. */ trait Accessors { public function __get($name) { if (method_exists($this, 'get' . $name)) { return $this->{'get' . $name}(); } elseif (property_exists($this, $name)) { return $this->{$name}; } else { throw new Exception("Cannot retrieve value of '$name'."); } } public function __set($name, $value) { if (method_exists($this, 'set' . $name)) { $this->{'set' . $name}($value); } elseif (property_exists($this, $name)) { $this->{$name} = $value; } else { throw new Exception("Cannot set value for '$name'."); } } } /** * @property float $price * @property float $amount * @property float $tax * @property-readonly float $total */ class OrderLine { use Accessors; protected $price; protected $amount; protected $tax; public function getTotal() { return $this->price * $this->amount * (1 + ($this->tax / 100)); } protected function getPrice() { return $this->price; } protected function getAmount() { return $this->amount; } protected function setPrice($price) { $this->price = $price; } protected function setAmount($amount) { $this->amount = $amount; } } $line = new OrderLine; $line->price = 20; $line->amount = 3; $line->tax = 10; echo "Total cost: ".$line->total; ?> outputs ... Total cost : 66 So, the actual methods are hidden from public, but a developer can extend the class to add additional processing. Interestingly, I've used property_exists to expose public access to protected properties. I suppose that is always possible. Bad design really. I would guess you wouldn't mix the different access mechanisms (public/protected/private, __get/__set, getter()/setter()). Richard. -- Richard Quadling Twitter : EE : Zend : PHPDoc : Fantasy Shopper @RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY : bit.ly/lFnVea : fan.sh/6/370

« previous php.internals (#56339) next »