On 16 November 2011 00:17, Rasmus Schultz <ras...@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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to