2013-12-13 3 views
0

Я делаю класс BaseModel и хочу использовать магические методы __set и __get вместо определения сеттеров и геттеров для каждого отдельного свойства.Есть ли лучший способ определить __get без использования переменных переменных или массива для всех переменных-членов?

В настоящее время я использую переменные переменные, потому что я не мог найти другой способ, выполнив его. Переменные переменные считаются плохой практикой или я не беспокоюсь ни о чем?

abstract class BaseModel implements \ArrayAccess { 

/** 
* Don't allow these member variables to be written by __set 
* 
* @var array 
*/ 
protected $noSet = array(); 

/** 
* Don't allow these member variables to be retrieved by __get 
* 
* @var array 
*/ 
protected $noGet = array(); 

public function offsetExists($offset) 
{ 
    return property_exists($this, $offset); 
} 
public function offsetGet($offset) 
{ 
    return $this->__get($offset); 
} 
public function offsetSet($offset , $value) 
{ 
    return $this->__set($offset, $value); 
} 
public function offsetUnset($offset) 
{ 
    unset($this->$offset); 
} 

public function __get($member) 
{ 
    if($member == 'noSet' || $member == 'noGet') 
    { 
     throw new \InvalidArgumentException ("Tried to access a forbidden property", 1); 
    } 

    if(! property_exists($this, $member)) 
    { 
     throw new \InvalidArgumentException ("Tried to access a non-existent property", 1); 
    } 

    if(in_array($member, $this->noGet)) 
    { 
     throw new \InvalidArgumentException ("Tried to access a forbidden property", 1); 
    } 

    return $this->$member; 
} 

public function __set($member, $value) 
{ 
    if($member == 'noSet' || $member == 'noGet') 
    { 
     throw new \DomainException ("Tried write to a non-writable property.", 1); 
    } 

    if(! property_exists($this, $member)) 
    { 
     throw new \InvalidArgumentException ("Tried to access a non-existent property", 1); 
    } 

    if(in_array($member, $this->noSet)) 
    { 
     throw new \DomainException ("Tried write to a non-writable property.", 1); 
    } 

    return $this->$member = $value; 
} 

ответ

-1

Переменные переменные действительно являются отправными точками.

+0

PS: Проверьте __call. Мы избавились от так много крутизны в наших моделях :) – Jessica

0

Во-первых, кажется, вы думаете, что ключевое слово protected делает свойство неспособным установить/получить с помощью магических методов. Это не тот случай. Это просто приводит к тому, что вы не можете напрямую обращаться к этим свойствам или изменять их из-за пределов сферы действия класса (т. Е. Вы не можете сделать что-то вроде $object->foo = 'bar')

Во-вторых, вы, кажется, неправильно понимаете магические методы. Фактически это делается для обеспечения соблюдения поведения, когда пользователь пытается напрямую получить доступ/изменить свойство. Так что в моем примере, если пользователь пытается сделать:

$object->foo = 'bar'; 

Это на самом деле вызывает метод __set() и эквивалентно:

$object->__set('foo', 'bar'); 

Так типичная реализация класса с помощью получить/установить магические методы могли бы выглядеть следующим образом:

class some_class { 
    protected $foo; 
    protected $foo2; 
    public $pub; 
    public function __construct() { 
     // maybe do something here 
    } 
    public function __get($prop) { 
     if(!property_exists($this, $prop) { 
      throw new Exception('Tried to get unknown property ' . $prop); 
     } else { 
      return $this->{$prop}; 
     } 
    } 
    public function __set($prop, $value) { 
     if(!property_exists($this, $prop) { 
      throw new Exception('Tried to set unknown property ' . $prop); 
     } else { 
      $this->{$prop} = $value; 
      return true; // or whatever you want to return 
     } 
    } 
} 

Использование будет выглядеть следующим образом:

$object = new some_class(); 
$object->foo = 'bar'; // sets 'bar' 
echo $object->foo; // echo 'bar; 
var_dump($object->foo2); // null 
$object->pub = 'something'; // does not call __set() as this property is available from global scope 
echo $object->pub; // echo 'something' does not call __get() as this property is available from global scope 
$object->no_prop; // throws Exception from __get() as property does not exist 

Похоже, странное использование, чтобы попытаться на самом деле позвонить __get() или __set() изнутри класса.

Ознакомьтесь с PHP документации по объекту перегружать для получения дополнительной информации:

http://www.php.net/manual/en/language.oop5.overloading.php#object.get

+0

'offsetExists', а другие методы' offset * 'являются частью интерфейса [ArrayAccess] (http://www.php.net/arrayaccess). – zzzzBov

+0

@zzzzBov Я раньше не заметил декларацию 'tools '. Удалено комментарий об этом методе. –

Смежные вопросы