跳转至内容

PHP 编程/特殊方法

来自维基教科书,开放的书籍,开放的世界

构造函数

[编辑 | 编辑源代码]

构造函数是类中的一个特殊方法,在创建对象时调用。构造函数的使用方法如下


这是 PHP5 版本

  <?php
  class test {
    public $name;   
    public function __construct ($name) {
        $this->name = $name;
     }
  }
  $testing = new test('Hello');
  echo $testing->name;  // Prints 'Hello'
  ?>

这是等效的 PHP4.x 版本:(注意没有公共/私有关键字,类名是构造函数)

  <?php
  class test {
    var $name;   
    function test ($name) {
        $this->name = $name;
     }
  }
  $testing = new test('Hello');
  echo $testing->name;  // Prints 'Hello'
  ?>

在 PHP5 中,构造函数必须声明为 public,否则将无法工作。构造函数的名称在 PHP5 中必须始终为 __construct。类名必须在 PHP5 中用作构造函数。

析构函数

[编辑 | 编辑源代码]

析构函数用于删除对象的实例。析构函数在对象的类中声明,包含在销毁时要执行的其他代码。

   <?php
   class myClass {
     function __construct() {
         print "Constructing new myClass...\n";
         $this->name = "My class";
     }
     function __destruct() {
         print "Destroying " . $this->name . "\n";
     }
   }
   $obj = new myClass();
   ?>

注意,析构函数仅存在于 PHP5 中。

为什么构造函数和析构函数很棒

[编辑 | 编辑源代码]

为什么构造函数和析构函数有用?有时,对象表示复杂的实体,它们使用其他资源或具有其他副作用,即使在您的程序中它们看起来像简单的变量。在这些情况下,创建对象时可能需要特殊设置;您可以使用构造函数来为您自动执行此操作。此外,在程序结束时释放这些资源非常重要,这样它们就不会被多个运行或页面浏览占用;析构函数可以自动处理,这样您就不会忘记。

以下是一个使处理 MySQL 数据库稍微简单的示例

 <?php
 class db_link {
  private $link;
  public function __construct ($database_name) {
   $link = mysql_connect ("localhost", "your_user_name", "your_password");
   mysql_select_db ($database_name, $link);
   $this -> link = $link;
   }
  function query ($sql_query) {
   $result = mysql_query ($sql_query, $this -> link);
   return $result;
   }
  function __destruct() {
   mysql_close ($this -> link);
   }
  }
 $db = new db_link ("MyDB");
 $result = $db->query ("Select * from MyTable");
 ?>

类 "db_link" 使用 3 个函数:构造函数,它会在每次创建新的 "db_link" 对象时自动登录数据库;"query" 函数,我可以用它从数据库获取记录;析构函数,它会在 PHP 完成我的对象实例时自动关闭数据库。我可以通过为数据库编写特殊的 "open" 和 "close" 函数来执行与构造函数和析构函数相同的操作,但我必须每次都调用这些函数。这样一来,我所要做的就是创建对象并使用它们;它们可以自动打开和关闭自己。


序列化和反序列化

[编辑 | 编辑源代码]

在某些情况下,需要将实例化的(创建的)对象存储为静态文本,以便在程序运行之间存储,通常存储在文件或数据库字段中。可以使用序列化来存储它,序列化会从对象创建一个字符串,然后可以反序列化为一个工作对象,包括工作方法和属性。

可以使用以下方法序列化对象

 <?php
 class test {
  private $test1;
  public function __construct ($testval) {
   $this->test1=$testval;
   }
  public function get_testval() {
   return $testval;
   }
  }
 $testobject = new test ("Testing serialization...")
 $serialized_testobject = serialize($testobject);
 ?>

$serialized_testobject 是一个字符串,可以存储在文件或数据库列中,假设它没有超过列的大小限制。可以使用以下方法对其进行反序列化

 <?php
 class test {
  private $test1;
  public function __construct ($testval) {
   $this->test1=$testval;
   }
  public function get_testval() {
   return $testval;
   }
  }
 $testobject = unserialize($serialized_testobject);
 echo $testobject->get_testval();
 ?>

注意,test 类需要定义,因为它没有在序列化字符串中定义。以不同的方式定义类可能会在反序列化时导致问题。类必须具有相同的名称。

然而,某些对象在序列化前后需要执行任务,以确保运行之间的一致性。例如,数据库链接在序列化时需要销毁,在反序列化时需要重新创建,否则它们将在稍后失效。对象在用户定义的 __sleep() 方法期间准备好进行序列化,并在反序列化后使用 __wakeup() 准备好工作,如下所示。

 <?php
 class db_link {
  private $link;
  public function __construct ($database_name) {
   $link = mysql_connect ("localhost", "your_user_name", "your_password");
   mysql_select_db ($database_name, $link);
   }
  function query ($sql_query) {
   $result = mysql_query ($sql_query, $link);
   return $result;
   }
  function __destruct() {
   mysql_close ($link);
   }
  function __sleep() {
   mysql_close ($link);
  }
  function __wakeup() {
   $link = mysql_connect ("localhost", "your_user_name", "your_password");
   mysql_select_db ($database_name, $link);
  }
 $db = new db_link ("MyDB")
 $result = $db->query ("Select * from MyTable")
 ?>

这里,链接在序列化时关闭,在反序列化时重新打开,因为链接可能不会在存储在文本文件中几个小时后具有相同的网络状态。在复杂的类中,许多属性和其他不高度依赖时间的 data 将存储在序列化字符串中,而更多易变的事物(如文件句柄和数据库链接)将在稍后关闭和重新打开。存在一个例外:可以快速生成的 large amounts of data 应该在 __sleep() 中被销毁或至少压缩,以便它们不会占用序列化文件中的空间。例如,包含 2000 个条目长的算法生成的条目的数组应该被重新生成。


华夏公益教科书