| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <!-- |
| Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. |
| --> |
| <html> |
| <head> |
| <title>使用 PHP 创建数据库驱动的应用程序。优化 PHP 代码。重构。包括文件。MySQL 数据库访问函数</title> |
| <meta name="KEYWORDS" content="CRUD, Update, Delete, MySQL, PHP, NetBeans"> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <meta name="DESCRIPTION" content="Creating a Database Driven Application With PHP. Optimizing PHP code. Refactoring. Include files. MySQL Database access functions" > |
| <link rel="stylesheet" type="text/css" href="../../../netbeans.css" media="screen"> |
| </head> |
| <body> |
| <h1>使用 PHP 创建数据库驱动的应用程序 </h1> |
| <h1>第 4 课:使用类和对象优化代码</h1> |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| <h4>教程目录:</h4> |
| <ol start="0"> |
| <li><a href="wish-list-tutorial-main-page.html">使用 PHP 创建数据库驱动的应用程序 - 主页</a></li> |
| <li><p>创建数据库</p> <ol type="a"><li><a href="wish-list-lesson1.html">创建 MySQL 数据库</a></li> |
| <li><a href="wish-list-oracle-lesson1.html">创建 Oracle 数据库表</a></li> |
| </ol></li> |
| <li><a href="wish-list-lesson2.html">设计应用程序。从数据库读取数据</a></li> |
| <li><a href="wish-list-lesson3.html">创建新的应用程序用户</a></li> |
| <li><p><b>=> 优化代码</b></p> |
| <ul> |
| <li><a href="#previousLessonSourceCode">来自上一课的应用程序源代码</a></li> |
| <li><a href="#createDbPhpFile">创建 db.php 文件</a></li> |
| <li><a href="#wishDBClass">创建 WishDB 类</a></li> |
| <li><a href="#instantiate-wishdb">实例化 WishDB 类</a></li> |
| <li><a href="#wishdb-constructor">在 WishDB 类中添加构造函数</a></li> |
| <li><a href="#includedFunctions">WishDB 类中的函数</a> |
| <ul> |
| <li><a href="#getIDByName">函数 get_wisherID_by_name</a></li> |
| <li><a href="#getWishesByID">函数 get_wishes_by_wisher_id</a></li> |
| <li><a href="#createWisher">函数 create_wisher</a></li> |
| </ul> |
| </li> |
| <li><a href="#refactoring">重构应用程序代码</a> |
| <ul> |
| <li><a href="#refactoringWishlistFile">重构 wishlist.php 文件</a></li> |
| <li><a href="#refactoringCreateNewWisher">重构 createNewWisher.php 文件</a></li> |
| </ul> |
| </li> |
| <li><a href="#lessonResultSourceCode">完成当前课程后的应用程序源代码</a></li> |
| </ul> |
| </li> |
| <li><a href="wish-list-lesson5.html">添加安全功能。实现应用程序用户登录</a></li> |
| <li><a href="wish-list-lesson6.html">在数据库中添加新的愿望</a></li> |
| <li><a href="wish-list-lesson7.html">更新和删除数据库中的条目</a></li> |
| <li><a href="wish-list-lesson8.html">使用 CSS 技术改进应用程序的外观</a></li> |
| <li><a href="wish-list-lesson9.html">将应用程序部署到远程 Web 服务器</a></li> |
| </ol> |
| </div> |
| </div> |
| <img alt="此页上的内容适用于 NetBeans IDE 7.2、7.3、7.4 和 8.0" class="stamp" src="../../../images_www/articles/73/netbeans-stamp-80-74-73.png" title="此页上的内容适用于 NetBeans IDE 7.2、7.3、7.4 和 8.0"> |
| <p>在本课中,将优化代码以便于将来进行维护。这会影响 <tt>createNewWisher.php</tt> 和 <tt>wishlist.php</tt> 文件。此外,还会创建一个名为 <tt>db.php</tt> 的新文件。</p> |
| <p>应用程序代码包含几个类似的块,其中提供了一些数据库查询。为了便于将来阅读和维护代码,您可以提取这些块,将这些块作为名为 <tt>WishDB</tt> 的单独类的函数进行实现,然后将 <tt>WishDB</tt> 放在 <tt>db.php</tt> 中。接下来,您可以将 <tt>db.php</tt> 文件包含在任何 PHP 文件中,然后使用 <a href="#includedFunctions">WishDB 中的任何函数</a>而无需复制代码。这种方法确保了对查询或函数进行的任何更改是在一个地方完成的,您不必解析整个应用程序代码。 </p> |
| <p>在使用 WishDB 中的函数时,不可更改任何 WishDB 变量的值。而应将 WishDB 类作为模板来创建 WishDB 对象,然后在该对象中更改变量值。在使用完该对象后,将会销毁该对象。由于从未更改 WishDB 类本身的值,您可以不限次数地重复使用该类。在某些情况下,您可能希望同时存在多个类实例,而在其他情况下,您可能希望只存在“单个”类,即,在任何时候都只有一个实例。本教程中的 WishDB 就是单个类。</p> |
| <p>请注意,创建类对象的术语是“实例化”该类,而有关对象的另一个术语是类“实例”。使用类和对象进行编程的一般术语是面向对象的编程 (OOP)。PHP 5 使用复杂的 OOP 模型。有关详细信息,请参见 <a href="http://us3.php.net/zend-engine-2.php" target="_blank">php.net</a>。</p> |
| <p>在本教程中,您将数据库调用功能从单独的 PHP 文件移到 WishDB 类。MySQL 用户还会将过程样式的 <tt>mysqli</tt> 调用替换为面向对象的调用。这是为了与面向对象的新应用程序设计保持一致。</p> |
| <p>当前文档是“在适用于 PHP 的 NetBeans IDE 中创建 CRUD 应用程序”教程的一部分。 </p> |
| <br style="clear:left"> |
| <h2><a name="previousLessonSourceCode"></a>来自上一课的应用程序源代码</h2> |
| <p>MySQL 用户:单击<a href="https://netbeans.org/files/documents/4/1929/lesson3.zip" target="_blank">此处</a>以下载源代码,该代码反映了在完成上一课之后的项目状态。 </p> |
| <p>Oracle 数据库用户:单击<a href="https://netbeans.org/projects/www/downloads/download/php%252Foracle-lesson3.zip" target="_blank">此处</a>以下载源代码,该代码反映了在完成上一课之后的项目状态。</p> |
| <h2><a name="createDbPhpFile"></a>创建 db.php 文件</h2> |
| <p>在 "Source Files"(源文件)文件夹中创建一个新子文件夹。将该文件夹命名为 Includes。创建一个名为 db.php 的新文件,并将其放在 Includes 中。然后,您可以在该文件夹中添加更多文件,这些文件将包含在其他 PHP 文件中。 </p> |
| <p><b>在新文件夹中创建 db.php:</b></p> |
| <ol> |
| <li>在 "Source Files"(源文件)节点上单击鼠标右键,然后从上下文菜单中选择 "New"(新建)> "Folder"(文件夹)。"New Folder"(新建文件夹)对话框打开。 </li> |
| <li>在 "Folder Name"(文件夹名称)字段中,键入 Includes。然后,单击 "Finish"(完成)。</li> |
| |
| <li>在 "Includes" 节点上单击鼠标右键,然后从上下文菜单中选择 "New"(新建)> "PHP File"(PHP 文件)。"New PHP File"(新建 PHP 文件)对话框打开。</li> |
| <li>在 "File Name"(文件名)字段中,键入 db。然后,单击 "Finish"(完成)。 </li> |
| </ol> |
| <h2><a name="wishDBClass"></a>创建 WishDB 类</h2> |
| <p>要创建 WishDB 类,您需要初始化该类的变量,并实现该类的构造函数。MySQL 用户请注意,WishDB 类<em>扩展</em>了 <tt>mysqli</tt>。这意味着 WishDB <em>继承</em> PHP mysqli 类的函数和其他特性。在类中添加 <tt>mysqli </tt>函数时,您会看到这种继承的重要性。</p> |
| <p>打开文件 db.php 并创建 WishDB 类。在该类中,声明数据库配置变量以存储数据库所有者(用户)的名称和口令、数据库名称和数据库主机。所有这些变量声明都是私有的 ("private"),这意味着无法从 WishDB 类外部访问声明中的初始值(请参见 <a href="http://us3.php.net/manual/en/language.oop5.visibility.php" target="_blank">php.net</a>)。您还可以声明私有的 <em>static</em> <tt>$instance</tt> 变量以存储 WishDB 实例。"static" 关键字表示,即使没有类实例,类中的函数也可以访问变量。</p> |
| <p><strong>对于 MySQL 数据库:</strong></p> |
| <pre class="examplecode">class WishDB extends mysqli { |
| |
| |
| // single instance of self shared among all instances |
| private static $instance = null; |
| |
| |
| // db connection config vars |
| private $user = "phpuser"; |
| private $pass = "phpuserpw"; |
| private $dbName = "wishlist"; |
| private $dbHost = "localhost"; |
| }</pre> |
| <p><strong>对于 Oracle 数据库:</strong></p> |
| <pre class="examplecode"> |
| class WishDB {<br><br> |
| |
| // single instance of self shared among all instances |
| private static $instance = null;<br><br> |
| |
| // db connection config vars |
| private $user = "phpuser"; |
| private $pass = "phpuserpw"; |
| private $dbName = "wishlist"; |
| private $dbHost = "localhost/XE"; |
| private $con = null;<br><br> |
| } </pre> |
| <h2 id="instantiate-wishdb">实例化 WishDB 类</h2> |
| <p>如果其他 PHP 文件要使用 WishDB 类中的函数,这些 PHP 文件需要调用一个函数以创建 WishDB 类的对象(“实例化”)。WishDB 设计为<a href="http://www.phpclasses.org/browse/package/1151.html" target="_blank">单个类</a>,这意味着在任何时候都只有一个类实例。因此,这对防止任何外部 WishDB 实例化是非常有用的,这种实例化可能会创建重复的实例。</p> |
| <p>在 WishDB 类中,键入或粘贴以下代码:</p> |
| <pre class="examplecode"> //This method must be static, and must return an instance of the object if the object |
| //does not already exist. |
| public static function getInstance() { |
| if (!self::$instance instanceof self) { |
| self::$instance = new self; |
| } |
| return self::$instance; |
| } |
| |
| // The clone and wakeup methods prevents external instantiation of copies of the Singleton class, |
| // thus eliminating the possibility of duplicate objects. |
| public function __clone() { |
| trigger_error('Clone is not allowed.', E_USER_ERROR); |
| } |
| public function __wakeup() { |
| trigger_error('Deserializing is not allowed.', E_USER_ERROR); |
| }</pre> |
| <p><tt>getInstance</tt> 函数为 "public" 和 "static"。"Public" 表示可以从类外部任意访问该函数。"Static" 表示即使未实例化类,也可以使用该函数。在调用 <tt>getInstance</tt> 函数以实例化类时,该函数必须是静态的。请注意,该函数访问静态 <tt>$instance</tt> 变量,并将其值设置为类实例。 |
| |
| <p>称为作用域解析运算符的双冒号 (::) 和 <tt>self</tt> 关键字用于访问静态函数。<tt>Self</tt> 从类定义中使用以引用类本身。从类定义外部使用双冒号时,将使用类名而不是 <tt>self</tt>。请参见 <a href="http://us3.php.net/manual/en/language.oop5.paamayim-nekudotayim.php" target="_blank">php.net 上的作用域解析运算符</a>。 |
| <h2 id="wishdb-constructor">在 WishDB 类中添加构造函数</h2> |
| <p>类可以包含一个称为“构造函数”的特殊方法,每次创建该类的实例时,都会自动处理该方法。在本教程中,将在 WishDB 中添加一个构造函数;每次实例化 WishDB 时,它都会连接到数据库。</p> |
| <p>在 WishDB 中添加以下代码:</p> |
| <p><b>对于 MySQL 数据库:</b></p> |
| <pre class="examplecode">// private constructor<br>private function __construct() {<br> parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName);<br> if (mysqli_connect_error()) {<br> exit('Connect Error (' . mysqli_connect_errno() . ') '<br> . mysqli_connect_error());<br> }<br> parent::set_charset('utf-8');<br>}</pre> |
| <p><b>对于 Oracle 数据库:</b></p> |
| <pre class="examplecode">// private constructor |
| private function __construct() { |
| $this->con = oci_connect($this->user, $this->pass, $this->dbHost); |
| if (!$this->con) { |
| $m = oci_error(); |
| echo $m['message'], "\n"; |
| exit; |
| } |
| }</pre> |
| <p>请注意,使用了伪变量 <tt>$this</tt>,而不是使用 <tt>$con</tt>、<tt>$dbHost</tt>、<tt>$user</tt> 或 <tt>$pass</tt> 变量。从对象上下文中调用方法时,将使用伪变量 <tt>$this</tt>。它引用该对象中的变量值。</p> |
| <h2><a id="includedFunctions" name="includedFunctions"></a>WishDB 类中的函数 </h2> |
| <p>在本课中,将实现 WishDB 类的以下函数:</p> |
| <ul> |
| <li><a href="#getIDByName">get_wisher_id_by_name</a> - 根据许愿者名字检索许愿者的 ID </li> |
| <li><a href="#getWishesByID">get_wishes_by_wisher_id</a> - 使用特定 ID 检索许愿者的愿望列表 </li> |
| <li><a href="#createWisher">create_wisher</a> - 将新许愿者记录添加到 wishers 表中 </li> |
| </ul> |
| <div class="indent"><h3><a id="getIDByName" name="getIDByName"></a>函数 get_wisher_id_by_name</h3> |
| 该函数要求将许愿者名字作为输入参数,并返回许愿者的 ID。 <br> |
| <p> |
| 在 WishDB 类中,在 WishDB 函数后面键入或粘贴以下函数:</p> |
| <p><b>对于 MySQL 数据库:</b></p> |
| <pre class="examplecode">public function get_wisher_id_by_name($name) {<br> |
| $name = $this->real_escape_string($name);<br> |
| $wisher = $this->query("SELECT id FROM wishers WHERE name = '"<br> |
| . $name . "'"); |
| if ($wisher->num_rows > 0){<br> $row = $wisher->fetch_row();<br> return $row[0];<br> } else<br> return null; |
| }</pre> |
| <p><b>对于 Oracle 数据库:</b></p> |
| <pre class="examplecode">public function get_wisher_id_by_name($name) { |
| $query = "SELECT id FROM wishers WHERE name = :user_bv"; |
| $stid = oci_parse($this->con, $query); |
| oci_bind_by_name($stid, ':user_bv', $name); |
| oci_execute($stid); |
| //Because user is a unique value I only expect one row |
| $row = oci_fetch_array($stid, OCI_ASSOC);<br> if ($row) <br> return $row["ID"];<br> else<br> return null; |
| }</pre> |
| 该代码块执行 <tt>SELECT ID FROM wishers WHERE name = [variable for name of the wisher]</tt> 查询。查询结果是一个数组,其中包含符合查询条件的记录中的 ID。如果该数组不为空,则自动表示它包含一个元素,这是因为在创建表期间将字段名称指定为 UNIQUE。在本示例中,该函数返回 <tt>$result</tt> 数组的第一个元素(编号为零的元素)。如果数组为空,该函数将返回空值。 |
| <p class="notes"><b>安全注意事项:</b>对于 MySQL 数据库,将转义 <tt>$name</tt> 字符串以防止 SQL 注入攻击。请参见<a href="http://en.wikipedia.org/wiki/SQL_injection" target="_blank">有关 SQL 注入的维基百科</a>和 <a href="http://us3.php.net/mysql_real_escape_string" target="_blank">mysql_real_escape_string 文档</a>。虽然在本教程的上下文中,您不会遇到有害 SQL 注入的风险,但最佳做法是转义存在此类攻击风险的 MySQL 查询中的字符串。Oracle 数据库通过使用绑定变量来避免该问题。</p> |
| <h3><a id="getWishesByID" name="getWishesByID"></a>函数 get_wishes_by_wisher_id</h3> |
| <p>该函数要求将许愿者 ID 作为输入参数,并返回为许愿者注册的愿望。 </p> |
| <p>请输入以下代码块:</p> |
| <p><b>对于 MySQL 数据库:</b></p> |
| <pre class="examplecode">public function get_wishes_by_wisher_id($wisherID) {<br> return $this->query("SELECT id, description, due_date FROM wishes WHERE wisher_id=" . $wisherID);<br>}</pre> |
| <p><b>对于 Oracle 数据库:</b></p> |
| <pre class="examplecode">public function get_wishes_by_wisher_id($wisherID) { |
| $query = "SELECT id, description, due_date FROM wishes WHERE wisher_id = :id_bv"; |
| $stid = oci_parse($this->con, $query); |
| oci_bind_by_name($stid, ":id_bv", $wisherID); |
| oci_execute($stid); |
| return $stid; |
| }</pre> |
| <p>该代码块执行 <tt>"SELECT id, description, due_date FROM wishes WHERE wisherID=" . $wisherID</tt> 查询并返回一个结果集,这是一个符合查询条件的记录数组。(出于数据库性能和安全考虑,Oracle 数据库使用绑定变量。)数据选择是按 wisherID 执行的,这是 <tt>wishes</tt> 表的外键。 </p> |
| <p class="notes"><b>注:</b>在第 7 课之前,您不需要使用 <tt>id</tt> 值。</p> |
| <h3><a id="createWisher" name="createWisher"></a>函数 create_wisher</h3> |
| <p>该函数在 wishers 表中创建一个新记录。该函数要求将新许愿者的名字和口令作为输入参数,并且不返回任何数据。</p> |
| 请输入以下代码块: |
| <p><b>对于 MySQL 数据库:</b></p> |
| <pre class="examplecode">public function create_wisher ($name, $password){ |
| $name = $this->real_escape_string($name);<br> $password = $this->real_escape_string($password);<br> $this->query("INSERT INTO wishers (name, password) VALUES ('" . $name . "', '" . $password . "')"); |
| }</pre> |
| <p><b>对于 Oracle 数据库:</b></p> |
| <pre class="examplecode">public function create_wisher($name, $password) { |
| $query = "INSERT INTO wishers (name, password) VALUES (:user_bv, :pwd_bv)"; |
| $stid = oci_parse($this->con, $query); |
| oci_bind_by_name($stid, ':user_bv', $name); |
| oci_bind_by_name($stid, ':pwd_bv', $password); |
| oci_execute($stid); |
| }</pre> |
| 该代码块执行 <tt>"INSERT wishers (Name, Password) VALUES ([variables representing name and password of new wisher])</tt> 查询。该查询在 "wishers" 表中添加一个新记录,并分别使用 <tt>$name</tt> 和 <tt>$password</tt> 值填充 "name" 和 "password" 字段。 </div> |
| <h2><a name="refactoring"></a>重构应用程序代码</h2> |
| <p>现在,您已创建了一个单独的类以使用数据库,接下来便可将重复的块替换为对该类中的相关函数的调用。这有助于避免将来出现拼写错误和不一致的情况。不影响功能的代码优化称为“重构”。</p> |
| <div class="indent"> |
| <h3><a name="refactoringWishlistFile"></a>重构 wishlist.php 文件 </h3> |
| 请从 wishlist.php 文件入手,因为该文件很短,改进更能说明问题。 |
| <ol> |
| <li>在 <?php ?> 块的顶部,输入以下行以允许使用 <tt>db.php</tt> 文件: |
| <pre class="examplecode">require_once("Includes/db.php");</pre> |
| </li> |
| |
| <li>将连接到数据库并获取许愿者 ID 的代码替换为 <tt>get_wisher_id_by_name</tt> 函数调用。 |
| <p>对于 <b>MySQL 数据库</b>,替换的代码为: |
| <pre class="examplecode"><del>$con = mysqli_connect("localhost", "phpuser", "phpuserpw"); |
| if (!$con) { |
| exit('Connect Error (' . mysqli_connect_errno() . ') ' |
| . mysqli_connect_error()); |
| } |
| //set the default client character set |
| mysqli_set_charset($con, 'utf-8'); |
| |
| mysqli_select_db($con, "wishlist"); |
| $user = mysqli_real_escape_string($con, $_GET['user']); |
| $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='" . $user . "'"); |
| if (mysqli_num_rows($wisher) < 1) { |
| exit("The person " . $_GET['user'] . " is not found. Please check the spelling and try again"); |
| } |
| $row = mysqli_fetch_row($wisher);<br>$wisherID = $row[0]; |
| mysqli_free_result($wisher);</del><br><br> |
| <b>$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_GET["user"]); |
| if (!$wisherID) { |
| exit("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); |
| }</b></pre> |
| <p>对于 <b>Oracle 数据库</b>,替换的代码为:</p> |
| <pre class="examplecode"><del>$con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8"); |
| if (!$con) { |
| $m = oci_error(); |
| echo $m['message'], "\n"; |
| exit; |
| } |
| $query = "SELECT id FROM wishers WHERE name = :user_bv"; |
| $stid = oci_parse($con, $query); |
| $user = $_GET["user"]; |
| |
| oci_bind_by_name($stid, ':user_bv', $user); |
| oci_execute($stid); |
| |
| //Because user is a unique value I only expect one row<br> |
| $row = oci_fetch_array($stid, OCI_ASSOC); |
| if (!$row) { |
| echo("The person " . $user . " is not found. Please check the spelling and try again" );<br> exit;<br> |
| } |
| $wisherID = $row["ID"]; </del> |
| <br> |
| <b>$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_GET["user"]); |
| if (!$wisherID) { |
| exit("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); |
| }</b></pre> |
| <p>新代码先调用 WishDB 中的 <tt>getInstance</tt> 函数。<tt>getInstance</tt> 函数返回一个 WishDB 实例,然后代码在该实例中调用 <tt>get_wisher_id_by_name</tt> 函数。如果在数据库中找不到请求的许愿者,代码将终止该进程,然后显示一条错误消息。</p><p>此处不需要用于打开数据库连接的代码。连接是通过 WishDB 类的构造函数打开的。如果名字和/或口令发生变化,您只需要更新 WishDB 类的相关变量即可。</p> |
| </li> |
| <li>将获取按 ID 标识的许愿者的愿望的代码替换为调用 <tt>get_wishes_by_wisher_id</tt> 函数的代码。 |
| <p>对于 <b>MySQL 数据库</b>,替换的代码为: |
| <pre class="examplecode"><del>$result = mysqli_query($con, "SELECT description, due_date FROM wishes WHERE wisher_id=". $wisherID);</del> |
| |
| <strong>$result = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);</strong></pre> |
| <p>对于 <b>Oracle 数据库</b>,替换的代码为: </p> |
| <pre class="examplecode"><del>$query = "select * from wishes where wisher_id = :id_bv";<br>$stid = oci_parse($con, $query);<br>oci_bind_by_name($stid, ":id_bv", $wisherID);<br>oci_execute($stid);</del> |
| |
| <strong>$stid = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);</strong></pre> |
| </li> |
| <li>删除关闭数据库连接的行。 |
| <pre class="examplecode"> <del>mysqli_close($con);</del> |
| or |
| <del>oci_close($con);</del> </pre> |
| 不需要该代码,因为在销毁 WishDB 对象时自动关闭数据库连接。不过,保留了释放资源的代码。即使您调用了 <tt>close</tt> 函数或销毁了使用数据库连接的实例,也需要释放使用连接的所有资源以确保正确关闭连接。</li> |
| </ol> |
| <h3> </h3> |
| <h3><a name="refactoringCreateNewWisher"></a>重构 createNewWisher.php 文件 </h3> |
| <p>重构不影响 HTML 输入窗体或显示相关错误消息的代码。</p> |
| <ol> |
| <li>在 <?php?> 块的顶部,输入以下代码以允许使用 <tt>db.php</tt> 文件: |
| <pre class="examplecode">require_once("Includes/db.php");</pre> |
| </li> |
| <li>删除数据库连接凭证(<tt>$dbHost</tt> 等)。这些凭证现在包含在 <tt>db.php</tt> 中。</li> |
| <li>将连接到数据库并获取许愿者 ID 的代码替换为 <tt>get_wisher_id_by_name</tt> 函数调用。 |
| <p>对于 <b>MySQL 数据库</b>,替换的代码为:</p> |
| <pre class="examplecode"><del> |
| $con = mysqli_connect("localhost", "phpuser", "phpuserpw"); |
| if (!$con) { |
| exit('Connect Error (' . mysqli_connect_errno() . ') ' |
| . mysqli_connect_error()); |
| } |
| //set the default client character set |
| mysqli_set_charset($con, 'utf-8'); |
| |
| |
| <br>/** Check whether a user whose name matches the "user" field already exists */ |
| mysqli_select_db($con, "wishlist"); |
| $user = mysqli_real_escape_string($con, $_POST['user']); |
| $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='".$user."'"); |
| $wisherIDnum=mysqli_num_rows($wisher); |
| if ($wisherIDnum) { |
| $userNameIsUnique = false; |
| }</del> |
| <br> |
| <strong>$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_POST["user"]);<br>if ($wisherID) {<br> $userNameIsUnique = false;<br>}</strong></pre> |
| <p>对于 <b>Oracle 数据库</b>,替换的代码为: </p> |
| <pre class="examplecode"><del> |
| $con = oci_connect("phpuser", "phpuserpw", "localhost"); |
| if (!$con) { |
| $m = oci_error(); |
| echo $m['message'], "\n"; |
| exit; |
| } |
| $query = "select ID from wishers where name = :user_bv"; |
| $stid = oci_parse($con, $query); |
| $user = $_POST['user']; |
| $wisherID = null; |
| oci_bind_by_name($stid, ':user_bv', $user); |
| oci_execute($stid); |
| |
| //Each user name should be unique. Check if the submitted user already exists. |
| $row = oci_fetch_array($stid, OCI_ASSOC);<br>if ($row) {<br> $wisherID = $row["ID"]; <br>}<br>if ($wisherID != null) {<br> $userNameIsUnique = false;<br>}</del> |
| |
| <strong>$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_POST["user"]);<br>if ($wisherID) {<br> $userNameIsUnique = false;<br>}</strong></pre> |
| |
| 只要处理当前页面,<tt>WishDB</tt> 对象就会存在。在处理完成或中断后,将销毁该对象。不需要用于打开数据库连接的代码,因为该操作是由 WishDB 函数完成的。不需要用于关闭连接的代码,因为在销毁 <tt>WishDB</tt> 对象后,将立即关闭连接。</li> |
| <li>将在数据库中插入新许愿者的代码替换为调用 <tt>create_wisher</tt> 函数的代码。 |
| <p>对于 <b>MySQL 数据库</b>,替换的代码为:</p> |
| |
| <pre class="examplecode"><del>if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { |
| $password = mysqli_real_escape_string($con, $_POST["password"]);<br> mysqli_select_db($con, "wishlist");<br> mysqli_query($con, "INSERT wishers (name, password) VALUES ('" . $user . "', '" . $password . "')");<br> mysqli_free_result($wisher);<br> mysqli_close($con);<br> header('Location: editWishList.php');<br> exit;<br>} |
| </del> |
| <strong>if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) {<br> WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]);<br> header('Location: editWishList.php' );<br> exit;<br>}</strong></pre> |
| <p>对于 <b>Oracle 数据库</b>,替换的代码为: </p> |
| <pre class="examplecode"><del> |
| if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { |
| $query = "INSERT INTO wishers (name, password) VALUES (:user_bv, :pwd_bv)"; |
| $stid = oci_parse($con, $query); |
| $pwd = $_POST['password']; |
| oci_bind_by_name($stid, ':user_bv', $user); |
| oci_bind_by_name($stid, ':pwd_bv', $pwd); |
| oci_execute($stid); |
| oci_close($con); |
| header('Location: editWishList.php'); |
| exit; |
| }</del> |
| |
| |
| <strong>if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) {<br> WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]);<br> header('Location: editWishList.php' );<br> exit;<br>}</strong></pre> |
| </li> |
| </ol> |
| </div> |
| |
| <h2><a name="lessonResultSourceCode"></a>完成当前课程后的应用程序源代码 </h2> |
| <p>MySQL 用户:单击<a href="https://netbeans.org/projects/www/downloads/download/php%252Flesson4.zip" target="_blank">此处</a>以下载源代码,该代码反映了在完成课程后的项目状态。</p> |
| <p>Oracle 数据库用户:单击<a href="https://netbeans.org/projects/www/downloads/download/php%252Foracle-lesson4.zip" target="_blank">此处</a>以下载源代码,该代码反映了在完成课程后的项目状态。</p> |
| <h2><a name="nextSteps"></a>后续步骤</h2> |
| <p> |
| <a href="wish-list-lesson3.html"><< 上一课</a><br> <br> <a href="wish-list-lesson5.html">下一课 >></a><br> <br> <a href="wish-list-tutorial-main-page.html">返回到教程主页</a><br> <br> |
| </p> |
| <h2><a name="usefulLinks"></a>有用链接</h2> |
| <p>了解在 PHP 中使用类的详细信息:</p> |
| <ul> |
| <li><a href="http://us3.php.net/manual/en/language.oop5.php" target="_blank">类和对象</a> </li> |
| </ul> |
| <p>了解重构 PHP 代码的详细信息: </p> |
| <ul> |
| <li><a href="http://www.slideshare.net/spriebsch/seven-steps-to-better-php-code-presentation/" target="_blank">优化 PHP 代码的七个步骤</a></li> |
| <li> <a href="http://www.dokeos.com/wiki/index.php/Refactoring" target="_blank">PHP 重构</a></li> |
| </ul> |
| <br> |
| <div class="feedback-box" ><a href="/about/contact_form.html?to=3&subject=Feedback:%20PHP%20Wish%20List%20CRUD%204:%20Optimizing%20Code">发送有关此教程的反馈意见</a></div> |
| <br style="clear:both;" > |
| <p>要发送意见和建议、获得支持以及随时了解 NetBeans IDE PHP 开发功能的最新开发情况,请<a href="../../../community/lists/top.html">加入 users@php.netbeans.org 邮件列表</a>。</p> |
| <p><a href="../../trails/php.html">返回至 PHP 学习资源</a><br> |
| </p> |
| </body> |
| </html> |