面向对象的PHP最佳实践

Tim*_*Tim 10 php oop

假设我有一个代表一个人的类,该类中的变量将是$ name.

以前,在我的脚本中,我将创建对象的实例,然后通过使用以下方式设置名称:

$object->name = "x";
Run Code Online (Sandbox Code Playgroud)

但是,有人告诉我这不是最佳做法?我应该有一个函数set_name()或类似的东西:

function set_name($name)
{
    $this->name=$name;
}
Run Code Online (Sandbox Code Playgroud)

它是否正确?

如果在这个例子中我想在数据库中插入一个新的"人"记录,我如何将有关该人的所有信息,即$ name,$ age,$ address,$ phone等传递给该类,以便插入它,我应该这样做:

function set($data)
{
    $this->name= $data['name'];
    $this->age = $data['age'];
    etc
    etc

}
Run Code Online (Sandbox Code Playgroud)

然后发送一个数组?这是最好的做法吗?或者有人可以推荐最佳做法吗?

Man*_*kis 30

你应该有setter/getter方法.他们很痛苦,但你不一定要自己写.只要您提供类成员,IDE(例如Eclipse或Netbeans)就可以自动为您生成这些内容.但是,如果您根本不想处理这个问题并且使用PHP5,则可以使用其魔术方法来解决此问题:

   protected $_data=array(); 
   public function __call($method, $args) {
        switch (substr($method, 0, 3)) {
            case 'get' :
                $key = strtolower(substr($method,3));
                $data = $this->_data[$key];
                return $data;
                break;
            case 'set' :
                $key = strtolower(substr($method,3));
                $this->_data[$key] = isset($args[0]) ? $args[0] : null;
                return $this;
                break;
            default :
                die("Fatal error: Call to undefined function " . $method);
        }
    } 
Run Code Online (Sandbox Code Playgroud)

每次使用以set或get开头的不存在的方法时,此代码都将运行.所以你现在可以像这样设置/获取(并隐式声明)变量:

$object->setName('Bob');
$object->setHairColor('green');

echo $object->getName(); //Outputs Bob
echo $object->getHairColor(); //Outputs Green
Run Code Online (Sandbox Code Playgroud)

无需声明成员或setter/getter函数.如果将来你需要为set/get方法添加功能,你只需声明它,基本上覆盖了魔术方法.此外,由于setter方法返回$ this,你可以像这样链接它们:

 $object->setName('Bob')
        ->setHairColor('green')
        ->setAddress('someplace');
Run Code Online (Sandbox Code Playgroud)

这使代码易于编写和读取.

这种方法的唯一缺点是它使您的类结构更难以辨别.由于您基本上是在运行时声明成员和方法,因此必须在执行期间转储对象以查看它包含的内容,而不是读取类.如果你的类需要声明一个明确定义的接口(因为它是一个库和/或你希望phpdoc生成API文档),我强烈建议声明面向公众的set/get方法以及上面的代码.


Chr*_*heD 23

对对象的属性使用显式getter和setter(就像你给出的示例一样set_name)而不是直接访问它们会给你(以及其他)以下优点:

  • 您可以更改"内部"实现,而无需修改任何外部调用.这种"外部"代码不需要经常更改(因为您提供了一致的访问方式).
  • 您非常明确地提供了从类外部使用/调用的属性.如果其他人开始使用您的课程,这将证明非常有用.

上述原因是为什么这可以被认为是最佳实践,虽然它没有要这样做(并且可能被认为是某些用途的过度杀伤;例如,当你的对象做很少的'处理'但仅仅作为'数据的占位符'时").


Rob*_*loi 6

我完全赞同CristopheD(投票).创建一个新的,当我刚刚加入一个很好的实践.

通常,使用构造函数接受必填字段并设置可选字段的默认值.就像是:

class Person
{
  private $name;
  private $surname;
  private $sex;

  // Male is the default sex, in this case
  function Person($name, $surname, $sex='m'){
    $this->name = $name;
    $this->surname = $surname;
    $this->sex = $sex;
  }

  // Getter for name
  function getName()
  {
    return $this->name;
  }

  // Might be needed after a trip to Casablanca
  function setSex($sex)
  {
     $this->sex = $sex;
  }
}
Run Code Online (Sandbox Code Playgroud)

显然,您可以在构造函数中使用setter方法(请注意性别设置器的重复代码).

  • "去卡萨布兰卡之后可能需要"LOL (5认同)
  • 需要记住两件事:1.php 5+中的构造函数具有以下结构:__ construct(){} 2.在php中,您不能创建两个具有不同签名的构造函数,如Person(String $ name)和Person(),你只能有一个.(尽管如此,有很多方法可以实现这一目标.) (2认同)