代码之家  ›  专栏  ›  技术社区  ›  Thomas Owens

在PHP中我应该何时使用uConstruct()、uuGet()、uuSet()和uuCall()?

  •  10
  • Thomas Owens  · 技术社区  · 16 年前

    similar question discusses __construct 但我把它留在了我的书名里,是为了寻找找到这个的人。

    显然,“get”和“set”采用的参数是正在获取或设置的变量。但是,您必须知道变量名(例如,知道此人的年龄是$age而不是$myage)。因此,如果您必须知道变量名,特别是使用不熟悉的代码(如库),我看不出这一点。

    我找到几页解释 __get() , __set() __call() 但是我还是不知道为什么或者什么时候它们有用。

    10 回复  |  直到 11 年前
        1
  •  6
  •   user7094    16 年前

    This page 可能会有用。(注意你说的不正确- __set() 将变量名和值都作为参数。 __get() 只取变量的名称)。

    γ-() α-集() 在要提供对变量的一般访问的库函数中非常有用。例如,在ActiveRecord类中,您可能希望人们能够访问数据库字段作为对象属性。例如,在Kohana PHP框架中,您可以使用:

    $user = ORM::factory('user', 1);
    $email = $user->email_address;
    

    这是通过使用 γ-() α-集() .

    使用时可以完成类似的工作 __call() 也就是说,您可以检测何时有人调用getproperty()和setproperty(),并进行相应的处理。

        2
  •  5
  •   Peter Bailey    16 年前

    _ get()、uu set()和u call()是php所称的“magic methods”,这是一个绰号,我觉得这有点傻-我认为“hook”更合适。总之,我想……

    它们的目的是提供当数据成员(属性或方法) 不是 对象上定义的被访问,可用于各种各样的“聪明”思想,如变量隐藏、消息转发等。

    但是,有一个成本-调用这些的调用比调用定义的数据成员慢大约10倍。

        3
  •  3
  •   Ross    13 年前

    重新定义 __get __set 在核心类中特别有用。例如,如果您不希望意外地覆盖配置,但仍然希望从中获取数据:

    class Example
    {
        private $config = array('password' => 'pAsSwOrD');
        public function __get($name)
        {
            return $this->config[$name];
        }
    }
    
        4
  •  2
  •   Michał Niedźwiedzki    16 年前

    魔法方法的另一个有用的应用,特别是 __get __set __toString 是模板。只需编写使用magic方法的简单适配器,就可以使代码独立于模板引擎。如果您想移动到另一个模板引擎,只需更改这些方法。

    class View {
    
        public $templateFile;
        protected $properties = array();
    
        public function __set($property, $value) {
            $this->properties[$property] = $value;
        }
    
        public function __get($property) {
            return @$this->properties[$property];
        }
    
        public function __toString() {
            require_once 'smarty/libs/Smarty.class.php';
            $smarty = new Smarty();
            $smarty->template_dir = 'view';
            $smarty->compile_dir = 'smarty/compile';
            $smarty->config_dir = 'smarty/config';
            $smarty->cache_dir = 'smarty/cache';
            foreach ($this->properties as $property => $value) {
                $smarty->assign($property, $value);
            }
            return $smarty->fetch($this->templateFile);
        }
    
    }
    

    这种方法的隐藏好处是可以将视图对象彼此嵌套:

    $index = new View();
    $index->templateFile = 'index.tpl';
    
    $topNav = new View();
    $topNav->templateFile = 'topNav.tpl';
    
    $index->topNav = $topNav;
    

    而在 index.tpl ,嵌套如下:

    <html>
    <head></head>
    <body>
        {$topNav}
        Welcome to Foobar Corporation.
    </body>
    </html>
    

    一旦您 echo $index;

        5
  •  1
  •   karthikr    12 年前

    我认为这不利于代码的设计。如果你知道并做了一个好的设计,那么你就不需要使用 __set() __get() 在你的代码中。如果您使用Studio(例如Zend Studio)和 α-集() γ-() 你看不到你的类属性。

        6
  •  1
  •   Jay Bhatt    11 年前

    PHP允许我们动态地创建类变量,这会导致问题。您可以使用uuu set和uuu get方法来限制此行为。请参阅下面的示例…

    class Person { 
          public $name;
          public function printProperties(){
           print_r(get_object_vars($this));
          }
    }
    
    $person = new Person();
    $person->name = 'Jay'; //This is valid
    $person->printProperties();
    $person->age = '26';  //This shouldn't work...but it does 
    $person->printProperties();
    

    为了防止出现上述情况,你可以这样做。

    public function __set($name, $value){
        $classVar = get_object_vars($this);
        if(in_array($name, $classVar)){
        $this->$name = $value;
        }
    }
    

    希望这有帮助…

        7
  •  0
  •   Greg    16 年前

    他们是为了做“聪明”的事情。

    例如,您可以使用 __set() __get() 与数据库对话。您的代码将是: $myObject->foo = "bar"; 这可以在后台更新数据库记录。当然,你必须非常小心,否则你的表现可能会受到影响,因此引用“聪明”:)

        8
  •  0
  •   Aron Rotteveel    16 年前

    Overloading 方法在处理包含易于访问的数据的PHP对象时特别有用。 __get() 在访问不存在的属性时调用, __set() 在尝试写入不存在的属性时调用,并且 __call() 在调用不存在的方法时调用。

    例如,假设有一个类管理您的配置:

    class Config
    {
        protected $_data = array();
    
        public function __set($key, $val)
        {
            $this->_data[$key] = $val;
        }
    
        public function __get($key)
        {
            return $this->_data[$key];
        }
    
        ...etc
    
    }
    

    这使得对对象的读写变得容易得多,并使您在读写对象时能够更改使用自定义功能。 例子:

    $config = new Config();
    $config->foo = 'bar';
    
    echo $config->foo; // returns 'bar'
    
        9
  •  0
  •   JamShady    16 年前

    使用它们的一个很好的理由是在注册系统方面(我认为Zend框架将其实现为注册或配置类IIRC),因此您可以执行如下操作

    $conf = new Config();
    $conf->parent->child->grandchild = 'foo';
    

    这些属性中的每一个都是自动生成的配置对象,类似于:

    function __get($key) {
        return new Config($key);
    }
    

    显然,如果$conf->父级已经存在,则不会调用uuuget()方法,因此使用此方法生成新变量是一个很好的技巧。

    请记住,我刚才引用的代码不是功能性的,我只是为了举例而快速地编写了它。

        10
  •  0
  •   bobwienholt    16 年前

    可能不是世界上最干净的设计,但我遇到了这样一种情况:我有很多代码引用了类中的实例变量,即:

    $obj->value = 'blah';
    echo $obj->value;
    

    但是后来,我想在某些情况下设置“value”时做一些特殊的事情,所以我重命名了value变量,并用我需要的更改实现了uu set()和uu get()。

    其余的代码不知道有什么区别。