isset()和__isset()之间有什么区别?

时间:2014-01-20 06:31:14

标签: php

我需要了解魔法函数__isset()和普通函数isset()。实际上php语言构造isset()和php魔术方法__isset()之间的真正区别是什么?当我谷歌时,他们告诉我__isset()是一个神奇的功能。常见的php函数和php中的魔术函数有什么区别?

7 个答案:

答案 0 :(得分:43)

isset()

它是一种语言结构,用于检查变量或类属性的初始化:

$a = 10;

isset($a);     // true
isset($a, $b); // false

class Test
{
    public $prop = 10;
}

$obj = new Test;
isset($obj->prop); // true

__isset()

isset()empty()检查不存在或无法访问的类属性时,调用它是一种神奇的方法:

class Test
{
    public function __isset($name) {
        echo "Non-existent property '$name'";
    }
}

$obj = new Test;
isset($obj->prop); // prints "Non-existent property 'prop'" and return false

差:

           isset()                               __isset()
Language construct                    | Magic method
                                      |
Always return bool                    | Result depends on custom logic*
                                      |
Must be invoked in code               | Called automatically by event
                                      |
Unlimited number of parameters        | Has only one parameter
                                      |
Can be used in any scope              | Must be defined as method**
                                      |
Is a reserved keyword                 | Not a reserved keyword
                                      |
Can't be redefined (Parse error)      | Can be redefined in extended class***

__isset()结果无论如何都会automatically castedbool

实际上你可以定义自定义函数__isset(),但它与魔术方法无关。

请参阅this example


Magic Methods

与通用函数不同,只能在类作用域中定义,并且可以在特定事件上自动调用,例如:不可访问的方法调用,类序列化,在不可访问的属性上使用unset()等等。另请参阅此官方文档:Overloading

答案 1 :(得分:5)

__ isset是神奇的方法。魔术方法是内部调用的方法。

考虑以下代码

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo)
    {
        $this->foo = $foo;
    }

    public function __toString()
    {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;
?>

这里_ toString是一种神奇的方法,但你不会调用它。 当行echo $ class;被执行。 PHP知道现在我应该将$ class对象视为字符串,并将任何对象视为字符串调用 _toString方法,如果在该类中实现的话。

所有神奇的方法都以间接的方式称之为。

另一个例子如下

<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

同样,在上面的代码中,var_dump(is_callable($ obj));间接调用__invoke魔法。

答案 2 :(得分:5)

首先让我告诉你isset()函数的作用。 isset()函数检查值是否已设置或是否为空。 _ isset()函数是PHP中的一种神奇方法。开头的任何带有“_ ”的函数都是PHP中的魔术方法。现在,通过在不可访问的属性上调用isset()或empty()来调用__isset(),我指的是那些尚未在类中定义并在运行时显式定义的属性。 这是一段代码,可以让你更好地理解它:

<?php
class PropertyTest
{
    /**  Location for overloaded data.  */
    private $data = array();

    /**  Overloading not used on declared properties.  */
    public $declared = 1;

    /**  Overloading only used on this when accessed outside the class.  */
    private $hidden = 2;

    public function __set($name, $value)
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name)
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    /**  As of PHP 5.1.0  */
    public function __isset($name)
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    /**  As of PHP 5.1.0  */
    public function __unset($name)
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  Not a magic method, just here for example.  */
    public function getHidden()
    {
        return $this->hidden;
    }
}


echo "<pre>\n";

$obj = new PropertyTest;

$obj->a = 1;
echo $obj->a . "\n\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";

echo $obj->declared . "\n\n";

echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>

答案 3 :(得分:4)

简单来说, __ isset()帮助isset()处理类中的受保护/私有变量。

示例:

class test
{
    public $x = array();
}

在上述课程中,isset($test->x['key'])为公共

,您可以$x执行此操作

但是这里

class test
{
    protected $x = array();

    function __isset($key)
    {
        return isset($this->x[$key]);
    }
}

$x受到保护,您无法访问它,因此我们创建了__isset()来帮助我们使用 isset($x['key'])

你可以说__isset()只是isset()

的桥梁

答案 4 :(得分:1)

当某些事情发生时,会自动调用(触发)魔术函数。必须通过php代码专门调用普通函数。

在你的情况下:当你有一个试图得到不可访问属性的isset()时,会自动调用__isset()。

示例:

root@folgore:/tmp/php# cat a.php 
<?php
class a {
    private $att1;
    public $att2;

    function __isset($field) {
        echo "__isset invoked for $field\n";
    }
}

$obj=new a();

// __isset will be triggered:
isset($obj->att1);

// __isset will not be triggered:
isset($obj->att2);

root@folgore:/tmp/php# php a.php 
__isset invoked for att1

答案 5 :(得分:1)

  

常见的php函数和php中的魔术函数有什么区别?

通过预期的输入和结果声明和访问公共PHP函数,但应该调用它们。相比之下,魔术函数是在PHP中定义的,但是当在类中定义时,它们将被自动调用。例如,isset()PHP function

  

确定变量是否已设置且不是NULL

但是__isset()是一个类的Property overloading

  

PHP中的重载提供了动态创建&#34;的方法。属性和方法。这些动态实体通过魔术方法处理,可以在类中为各种动作类型建立。   在与尚未声明或在当前作用域中不可见的属性或方法交互时,将调用重载方法。

如果在类中声明,它将在场景后面神奇地调用。让我们试验PHP类属性重载。

<?php
    class PropertyTest
        {
            /**  Location for overloaded data.  */
            private $data = array();

            /**  Overloading not used on declared properties.  */
            public $declared = 1;

            /**  Overloading only used on this when accessed outside the class.  */
            private $hidden = 2;

            public function __set($name, $value)
            {
                echo "Setting '$name' to '$value'\n";
                $this->data[$name] = $value;
            }

            public function __get($name)
            {
                echo "Getting '$name'\n";
                if (array_key_exists($name, $this->data)) {
                    return $this->data[$name];
                }

                $trace = debug_backtrace();
                trigger_error(
                    'Undefined property via __get(): ' . $name .
                    ' in ' . $trace[0]['file'] .
                    ' on line ' . $trace[0]['line'],
                    E_USER_NOTICE);
                return null;
            }

            /*  As of PHP 5.1.0  */
             public function __isset($name) 
             { 
                 echo "Is '$name' set?\n"; 
                 return isset($this->data[$name]); 
             } 

            /**  As of PHP 5.1.0 */  
            public function __unset($name)
            {
                echo "Unsetting '$name'\n";
                unset($this->data[$name]);
            }

            /**  Not a magic method, just here for example.  */
            public function getHidden()
            {
                return $this->hidden;
            }
        }


        echo "<pre>\n";

        $obj = new PropertyTest;

        //__set() is called when 'a' property is not visible outside of class
        $obj->a = 1;
        //__get() is called when 'a' property is not visible outside of class
        echo "a: ".$obj->a . "\n\n";
        //__isset() is called when 'a' property is not visible outside of class
        var_dump(isset($obj->a));
        unset($obj->a);
        //__isset() is called when 'a' property is not visible outside of class
        var_dump(isset($obj->a));
        echo "\n";
        //__isset() is not called as 'declared' property is visible outside of class
        var_dump(isset($obj->declared));
        //__get() is not called as 'declared' property is visible outside of class            
        echo "declared: ". $obj->declared . "\n\n";
        //__set() is not called as 'declared' property is visible outside of class
        $obj->declared = 3;
        //__get() is not called as 'declared' property is visible outside of class 
        echo "declared: ". $obj->declared . "\n\n";

        //__isset() is called as 'hidden' property is not visible outside of class 
        var_dump(isset($obj->hidden));

        echo "Let's experiment with the private property named 'hidden':\n";
        echo "Privates are visible inside the class, so __get() not used...\n";
        echo $obj->getHidden() . "\n";
        echo "Privates not visible outside of class, so __get() is used...\n";
        var_dump($obj->hidden);

 ?>

上面的代码将输出

    Setting 'a' to '1'
    Getting 'a'
    a: 1

    Is 'a' set?
    bool(true)
    Unsetting 'a'
    Is 'a' set?
    bool(false)

    bool(true)
    declared: 1

    declared: 3

    Is 'hidden' set?
    bool(false)
    Let's experiment with the private property named 'hidden':
    Privates are visible inside the class, so __get() not used...
    2
    Privates not visible outside of class, so __get() is used...
    Getting 'hidden'
    NULL

它说隐藏了&#39;未设置属性并显示bool(false),但回显值&#39; 2&#39;后来因为隐藏了#39;属性在课堂外不可见,它会调用__isset()魔术函数,但它也没有设置在&#39;数据&#39;所以它返回bool(false)。在getHidden()函数中虽然它返回了对象私有属性&#39; hidden&#39;对象内部函数可见。在最后var_dump($obj->hidden)中,它调用__get()方法并返回NULL。因为在__get()方法中,它会查找data['hidden']的{​​{1}}。

注意:此处的示例来自PHP Manuel: Overloading并进行了一些修改。

希望这有帮助!

答案 6 :(得分:-1)

isset()用于变量,__isset()用于类的属性。