加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_郴州站长网 (http://www.0735zz.com/)- 云通信、区块链、物联设备、云计算、站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

运用PHP的OOP特性实现数据保护

发布时间:2022-03-08 09:45:38 所属栏目:PHP教程 来源:互联网
导读:在PHP 4中,声明变量通常使用var,而在PHP 5中,可使用面向对象编程(OOP)的特性来自定义数据的可见性--即可访问性,可见性在此与变量作用域非常类似,但提供了更好的控制机制,有以下三种类型的可见性修饰符: Public(默认)--变量可在全局范围内访问或
  在PHP 4中,声明变量通常使用var,而在PHP 5中,可使用面向对象编程(OOP)的特性来自定义数据的可见性--即可访问性,可见性在此与变量作用域非常类似,但提供了更好的控制机制,有以下三种类型的可见性修饰符:
 
  Public(默认)--变量可在全局范围内访问或修改。
 
  Protected--变量只能在类本身及直接派生(使用extends语句)类内访问或修改。
 
  Private--变量只能在类内部访问或修改。
 
  与接口实现类似,在程序中违反这些规则将会导致严重的错误;且与接口类似的是,它们的存在纯粹是为了方便程序员。但这并不意味着可以忽略它们,指定某个类成员变量的可见性,可保护对象内的数据免受外界影响。
 
  假设有一个MySQLDB类,一个$link变量在其中声明为private,这意味着这个变量只能从对象内部使用$this变量访问,这防止了类外其他对象或函数的意外覆盖,在此,我们将使用可见性特性帮助我们创建一个query对象。
 
  你可以把query当作一个单独的实体,它可以执行,并且返回结果。一些数据库系统也具有存储过程,存储过程与函数很相似,它们存储查询语句,并在调用时接受相应的参数,但MySQL在5.1版本之前并没有提供类似功能,某些其他类型的数据库管理系统也没有。
 
  在本文中,将把上述两个特性结合进示例的query对象中,示例将模拟一个基本的存储过程,并在内部保存结果指针。目前,重点是从对象中执行query,在此可以调用MySQLDB对象的query()函数。
 
  
  execute()--函数execute()将执行query。如果它被prepare()函数过早地初始化为一个存储过程,任何传递进来的参数都会被作为存储过程的执行参数,否则,第一个参数只会被作为查询文本。函数execute()将返回执行查询后的结果。
 
  compile()--函数compile()与函数execute()类似,实际上,query并没有执行,而是替换查询字符串中所有占位符,接受存储过程的参数,并返回query的编译版本。
 
  受保护的成员
 
  正如上面所提到的,可见性的概念可用于隐藏对象的内部工作,保护内部工作所需的数据完整性。前面已经解释,query返回的结果指针将会保存为protected属性,在此使用保护成员是因为从query对象派生出来的特定数据库query对象可能会重载某些核心功能。
 
  深掘代码
 
  理论说够了,现在开始编写代码,首先,创建一个例1所示的模板:
 
  例1:数据库query类的一个模板
 
  以下为引用的内容:
  class DBQuery
  {
   /**
   *保存一个实现了DB接口对象的引用。
   */
   protected $db;
 
   /**
   *如果是一个存储过程,设为true。
   */
   protected $stored_procedure = false;
 
   /**
   *保存一个删除了所有字符串的query。
   */
   private $query;
 
   /**
   *用于在SQL中匹配引号。
   */
   private static $QUOTE_MATCH = "/(".*(?db = $db;
  }
 
  public function prepare($query)
  {
   $this->stored_procedure = true;
  }
 
  public function compile($args)
  {}
 
  public function execute($query)
  {}
  }
 
  函数prepare
 
  为使用例1中的模板,你要做的第一件事是构建好prepare()函数,为确保无带引号的字符被偶然解析为占位符,函数应该移除query内所有字符串,并把它们临时存储在一个数组内。而字符串本身也会被占位符取代,其通常被识别为不应该在SQL语句中出现的的字符串序列。在query的编译期间,过程占位符会首先被替换,接着把字符串放回query中,这是通过preg_replace()函数,和另一个用作preg_replace()函数的helper回调函数完成的。
 
  例2:prepare()函数
 
  以下为引用的内容:
  /**
  * 把query准备为一个存储过程。
  * @param string $query Prepared query text
  * @return void
  */
  public function prepare($query)
  {
   $this->stored_procedure = true;
   $this->quote_store = array(); //清除引号
   $this->query = preg_replace(self::$QUOTE_MATCH, '$this->sql_quote_replace("1"?"1":'2')', $query);
  }
 
  private function sql_quote_replace($match)
  {
   $number = count($this->query_strings);
   $this->query_strings[] = $match;
   return "$||$$number";
  }
 
  在此留意对静态QUOTE_MATCH属性private的使用,还有quote_store属性和sql_quote_replace()函数。相比protected,在此定义为private更能确保任何重载query类prepare()方法的子类使用其自身的机制来剔除引号。
 
  函数compile
 
 
  下一步是构建compile()与execute()函数。
 
 
  函数compile()如例3中所示,功能如下:
 
 
  ·接受的参数数目可变(即可变参数),其将匹配query中的占位符。
 
 
  ·检查占位符是否为正确的数据类型,并把它替换为参数中的值。
 
 
  ·把query作为字符串返回,但不执行它。
 
 
  ·如果query对象没有使用prepare()函数初始化为一个存储过程,将抛出一个异常。
 
 
  例3:compile()函数
 
  以下为引用的内容:
  /**
  * 返回编译的query,但并不执行它。
  * @param mixed $args,... Query Parameters
  * @return string Compiled Query
  */
  public function compile($params)
  {
   if (! $this->stored_procedure) {
    throw new Exception("存储过程未被初始化!");
   }
 
   /* 替代参数 */
   $params = func_get_args(); // 取得函数参数
   $query = preg_replace("/(?query);
 
   return $this->add_strings($query); //把字符串放回query中
  }
 
  /**
  * 重新插入被prepare()函数移除的字符串。
  */
  private function add_strings($string)
  {
   $numbers = array_keys($this->query_strings);
   $count = count($numbers);
   $searches = array();
   for($x = 0; $x < $count; $x ) {
    $searches[$x] = "$||${$numbers[$x]}";
   }
 
   return str_replace($searches, $this->query_strings, $string);
  }
 
  /**
  * 每次执行,存储过程中都有一个占位符被替换。
  */
  protected function compile_callback($params, $index, $type)
  {
   --$index;
 
   /* 抛出一个异常 */
   if (! isset($params[$index])) {
    throw new Exception("存储过程未收到所需的参数数目!");
   }
 
   /* 可以在此添加别的类型,如日期和时间。 */
   switch ($type) {
    case 'S':
     return '"' . $this->db->escape_string($params[$index]) . '"';
     break;
    case 'I':
     return (int) $params[$index];
     break;
    case 'N':
     return (float) $params[$index];
    default:
     throw new Exception("存储过程中指定的数据类型 '$type' 无法识别。");
   }
  }
 
  函数compile()中使用了两个额外的函数,其中compile_callback()函数是作为在preg_replace()函数调用中的回调函数,每一次在query中查找到占位符,并把它替换为传给compile函数的值时,都会执行它。
 
  函数execute
 
  最后,还需要构建函数execute(),函数execute()编译query并且使用DB对象执行它,而DB对象在此是用于初始化DBQuery对象的。请注意在例4中,是怎样运用函数call_user_func_array()来得到编译后的query的,而这样做的原因是,函数execute()要直到运行时,才能确定传递给它的参数数目。

(编辑:开发网_郴州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读