PHP类的成员和方法

5

我已经搜索过,但无法找到关于在PHP类内部使用$this的明确答案(如果有的话)。我仍在努力理解使用OOP方法,并希望确保我使用最佳实践。

因此,我的问题是关于何时以及何时应该定义变量以及何时应使用$ this引用它们。

假设我有以下类....

class Foo {

private $pin;
private $stat;

public function get_stat($pin) {
            $this->stat = shell_exec("blah read $pin");
            return $this->stat;
    }
}

所以在上面的函数中,我将变量$pin传递给了类方法。这样做完全没有必要使用$this->pin...然而,下面的代码似乎更像是正确的做法......

class Foo {

private $pin = 0;
private $stat = 0;

public function get_stat($pin) {
            $this->pin = $pin;
            $this->stat = shell_exec("blah read $this->pin");
            return $this->stat;
    }
}

此外,我已将$pin和$stat变量设置为= 0。 我认为这只是一个默认值,或者我可以像第一个示例中那样定义它们为private $pin;和private $stat;。
那么回到我的问题,如何在类方法中使用成员和$this的最佳实践是什么? 每个示例的优点或缺点是什么?

1
我在codereview.stackexchange上得到了一个非常好的答案。请点击这里查看。 - jnthnjns
感谢提供链接,ASOK!现在我明白为什么只能使用 $this 来引用类内的属性了。我之前无法理解如何在类外访问它们的关系。 - nomaxpi
请勿使用未转义的值调用shell!shell_exec("blah read $pin");容易受到代码注入攻击。在这种情况下,始终使用转义函数来进行shell命令:escapeshellarg()。 - Sven
嗨Sven,是的,我承认我没有对输入进行“净化”。这只是一个我试图快速让它工作的简单例子。在我完全理解我想要实现的面向对象编程方面之后,逃逸的其余逻辑将会出现。再次感谢! - nomaxpi
@user2233942зҡ„ж„ҸжҖқжҳҜеңЁзұ»еӨ–йғЁи®ҝй—®еұһжҖ§дёҺзұ»еҶ…йғЁдҪҝз”Ё$this->зӣёдјјпјҢдҫӢеҰӮ $Foo = new Foo() 然еҗҺи°ғз”Ё $Foo->get_stat("Variable Passed") дёҺзұ»еҶ…йғЁдҪҝз”Ё $this->get_stat("Variable Passed")зӣёдјјгҖӮ - jnthnjns
换句话说,类内的 $this 是该类的一个实例,而上面我的示例中的 $Foo 则是来自类外部的同一类的一个实例。如果这样更容易理解的话。 - jnthnjns
3个回答

6
当使用任何类成员时,必须使用 $this。当使用局部变量时,不能使用它。如果不必要,应避免使用类成员,例如第二个示例中的 $this->pin

谢谢Sven。简而言之,我只有在需要使用类成员时才应该使用$this。否则它根本不需要使用? - nomaxpi
@ColeJohnson:这完全取决于编码风格。只要语言支持,这就是一种有效的方法。 - Sven
有效和合理的可能是两回事。虽然我同意你的观点,但 PHP 技术上会评估你传递给它的任何字符串。这并不意味着仅因为语言支持它,就通过 eval 运行一切是明智的选择。因此,对类或局部变量的滥用技术上可能有效,但失控可能会导致他得到高薪工作或住在桥下的区别。 - Kai Qing
假设我有一个变量 $var,它包含单词 word。使用这种编码风格,我会输入 "$vars",这将导致未定义的变量,而我实际上想要的是 $var + "s" - Cole Tobin
当然,但是如果他毫无理由地把每一件小事都分配为类变量,我最终可能得出和如果他通过eval运行所有内容一样的结论:这个人不适合雇佣。但是我太极端了。在这两种情况下,我需要绝对和彻头彻尾的愚蠢才会完全以此为依据做出决定。我只是太过极端了。 - Kai Qing
显示剩余3条评论

1
“最佳实践”取决于您的需求。在您的示例中,似乎 pin 是静态的。您可以最初设置它,甚至不将其传递给方法。
private $pin = 'abc123';

public function get_stat() {
    $this->stat = shell_exec("blah read $this->pin");
    return $this->stat;
}

设置类变量只有在需要使它们可以被类内方法访问时才有意义。在您的示例中,key和stat都可能在许多方法中使用,因此将它们定义为类变量并通过使用$this->key和$this->stat来访问它们是明智和合理的。如果像stat这样的东西仅在特定方法中使用或根据特定数据集更改,则将其作为类的常见属性而不是对象的属性不太合适。

正如Sven所指出的那样,在传递$pin到类时使用$this->pin是不合理的。如果pin不会更改且对实例通用,则将其分配为类变量并使用$this->pin更加合理,在这种情况下,您不需要向方法传递任何内容。例如,API请求中的密钥不太可能更改。如果$key可以是任何东西(例如来自数据库的结果、用户输入或其他任何源),则向方法传递$key是有意义的。

我不知道这是否会对您有所帮助,但以下是使用getter和setter的示例,如果您打算根据通用或抽象传递的任何内容更改引脚或状态的值。 Getter和Setter?

这真的很有帮助,Kai。正如你和Sven指出的那样,$this->pin并不需要,因为它一开始就被传递给了类。我的困惑在于类内外变量之间的关系(似乎没有任何关系)。 - nomaxpi

-1

如果您想坚持OOP的良好实践,那么您应该确实为实例变量设置setter和getter。 例如,这是您代码的修改版本:

class Foo {

    // common practice to begin private variables and methods with an underscore
    private $_pin = 0;
    private $_stat = 0;

    // this is called a setter because we are setting a value
    // note the lack of a return
    public function setStat($stat) {
        // we use $this-> because we are referencing THIS instance of THIS class/object
        // and in doing so we refer to our private $_stat instance variable.
        $this->_stat = $stat;
    }

    // this is called a getter because we are getting a value
    // not how we are NOT setting values here.
    public function getStat() {
        return $this->_stat;
    }

}

总的来说,当你引用this实例(也被称为对象)时,使用$this。拥有类的好处是可以定义多个对象。例如:

class Person {

    public $name, $age, $gender;

    public function setName($name) {
        $this->name = $name;
    }
    public function setAge($age) {
        $this->age = $age;
    }
    public function setGender($gender) {
        $this->gender = $gender;
    }
    public function getName() {
        return $this->name;
    }
    public function getAge() {
        return $this->age;
    }
    public function getGender() {
        return $this->gender;
    }

}

// outside the class
$john = new Person();
$john->setName('John Doe');
$john->setAge(22);
$john->setGender('male');
var_dump($john);

var_dump 将显示:

object(Person)#1 (3) { 
    ["name"]=> string(8) "John Doe" // $this->name
    ["age"]=> int(22)               // $this->age
    ["gender"]=> string(4) "male"   // $this->gender
}

希望这能帮到你!


不好意思,我不同意。你关于“getStat”的getter/setter示例是完全错误的。你的代码是一个无限循环,因为getStat()调用了getStat(),这个想法是错误的。拥有一个带有方法的对象,可以对传递的参数进行操作并返回结果是一件好事情。你的另一个示例是完全不同的示例,因为你展示了一个没有任何功能的值存储的getter/setter。 - Sven
无论我对你的代码的其他部分有什么看法,getStat()中的无限循环仍然存在。 - Sven
Sevn,我终于明白你在说什么了哈哈。有时候就像是在跟墙壁说话一样难懂 -___-。已经被纠正了。感谢你指出。 - djthoms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接