若相依 发表于 2015-2-4 00:14:13

PHP教程之经由过程缓存数据库了局进步PHP功能

完成一个功能齐全的动态站点缓存|数据|数据库|功能    尽人皆知,缓存数据库查询的了局可以明显延长剧本履行工夫,并最大限制地削减数据库办事器上的负载。假如要处置的数据根基上是静态的,则该手艺将十分无效。这是由于对近程数据库的很多数据恳求终究可以从当地缓存失掉知足,从而不用毗连到数据库、履行查询和获得了局。
  但当您利用的数据库与 Web 办事器位于分歧的盘算机上时,缓存数据库了局集凡是是一个不错的办法。不外,依据您的情形肯定最好的缓存战略倒是一个困难。例如,关于利用最新数据库了局集对照主要的使用法式而言,工夫触发的缓存办法(缓存体系经常使用的办法,它假定每次抵达生效工夫戳记时就从头生成缓存)能够并非一个使人写意的处理计划。这类情形下,您需求采取一种机制,每当使用法式需求缓存的数据库数据产生更改时,该机制将告诉该使用法式,以便该使用法式将缓存的过时数据与数据库坚持分歧。这类情形下利用“数据库更改告诉”(一个新的 Oracle 数据库 10g 第 2 版特征)将十分便利。
  “数据库更改告诉”入门
  “数据库更改告诉”特征的用法十分复杂:创立一个针对告诉履行的告诉处置法式 C 一个 PL/SQL 存储进程或客户端 OCI 回调函数。然后,针对要吸收其更改告诉的数据库对象注册一个查询,以便每当事务更改个中的任何对象并提交时挪用告诉处置法式。凡是情形下,告诉处置法式将被修正的表的称号、所做更改的类型和所更转业的行 ID(可选)发送给客户端监听法式,以便客户端使用法式可以在呼应中履行响应的处置。
  为了懂得“数据库更改告诉”特征的感化体例,请思索以下示例。假定您的 PHP 使用法式会见 OE.ORDERS 表中存储的定单和 OE.ORDER_ITEMS 中存储的定单项。鉴于很少更改已下定单的信息,您能够但愿使用法式同时缓存针对 ORDERS 和 ORDER_ITEMS 表的查询了局集。要防止会见过时数据,您可使用“数据库更改告诉”,它可以让您的使用法式便利地获知以上两个表中所存储数据的更改。
  您必需先将 CHANGE NOTIFICATION 体系权限和 EXECUTE ON DBMS_CHANGENOTIFICATION 权限授与 OE 用户,才干注册对 ORDERS 和 ORDER_ITEMS 表的查询,以便吸收告诉和呼应对这两个表所做的 DML 或 DDL 更改。为此,可以从 SQL 号令行东西(如 SQL*Plus)中履行以下号令。
CONNECT / AS SYSDBA;
GRANT CHANGE NOTIFICATION TO oe;
GRANT EXECUTE ON DBMS_CHANGE_NOTIFICATION TO oe;
  确保将 init.ora 参数 job_queue_processes 设置为非零值,以便吸收 PL/SQL 告诉。或,您也能够利用上面的 ALTER SYSTEM 号令:
ALTER SYSTEM SET "job_queue_processes"=2;  然后,在以 OE/OE 毗连后,您可以创立一个告诉处置法式。但起首,您必需创立将由告诉处置法式利用的数据库对象。例如,您能够需求创立一个或多个数据库表,以便告诉处置法式将注册表的更改纪录到个中。在以下示例中,您将创立 nfresults 表来纪录以下信息:更改产生的日期和工夫、被修正的表的称号和一个动静(申明告诉处置法式是不是胜利地将告诉动静发送给客户端)。
CONNECT oe/oe;
CREATE TABLE nfresults (
operdate DATE,
tblname VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
  在实践情形中,您能够需求创立更多表来纪录告诉事务和所更转业的行 ID 等信息,但就本文而言,nfresults 表完整可以知足需求。
  利用 UTL_HTTP 向客户端发送告诉
  您能够还要创立一个或多个 PL/SQL 存储进程,并从告诉处置法式中挪用这些存储进程,从而完成一个更具可保护性和天真性的处理计划。例如,您能够要创立一个完成将告诉动静发送给客户真个存储进程。“清单 1”是 PL/SQL 进程 sendNotification。该进程利用 UTL_HTTPPL 法式包向客户端使用法式发送更改告诉。
  清单 1. 利用 UTL_HTTP 向客户端发送告诉
CREATE OR REPLACE PROCEDURE sendNotification(url IN VARCHAR2,
tblname IN VARCHAR2, order_id IN VARCHAR2) IS
req   UTL_HTTP.REQ;
respUTL_HTTP.RESP;
err_msg VARCHAR2(100);
tbl VARCHAR(60);
BEGIN
tbl:=SUBSTR(tblname, INSTR(tblname, '.', 1, 1)+1, 60);
BEGIN
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
resp := UTL_HTTP.GET_RESPONSE(req);
INSERT INTO nfresults VALUES(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
END;
COMMIT;
END;
/
  如“清单 1”所示,sendNotification 以 UTL_HTTP.BEGIN_REQUEST 函数收回的 HTTP 恳求的模式向客户端发送告诉动静。此 URL 包括 ORDERS 表中已更转业的 order_id。然后,它利用 UTL_HTTP.GET_RESPONSE 获得客户端收回的呼应信息。实践上,sendNotification 其实不需求处置客户端前往的全部呼应,而是只获得一个在 RESP 纪录的 reason_phrase 字段中存储的冗长动静(描写形态代码)。
  创立告诉处置法式
  如今,您可以创立一个告诉处置法式,它将借助于下面引见的 sendNotification 进程向客户端发送更改告诉。来看一看“清单 2”中的 PL/SQL 进程 orders_nf_callback。
  清单 2. 处置对 OE.ORDERS 表所做更改的告诉的告诉处置法式
CREATE OR REPLACE PROCEDURE orders_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
tblname VARCHAR2(60);
numtables NUMBER;
event_type NUMBER;
row_id VARCHAR2(20);
numrows NUMBER;
ord_id VARCHAR2(12);
url VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
BEGIN
event_type := ntfnds.event_type;
numtables := ntfnds.numtables;
IF (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) THEN
FOR i IN 1..numtables LOOP
tblname := ntfnds.table_desc_array(i).table_name;
IF (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) THEN
numrows := ntfnds.table_desc_array(i).numrows;
ELSE
numrows :=0;
END IF;
IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM orders WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
END LOOP;
END IF;
END LOOP;
END IF;
COMMIT;
END;
/
  如“清单 2”所示,此告诉处置法式将 SYS.CHNF$_DESC 对象用作参数,然后利用它的属性获得该更改的具体信息。在该示例中,此告诉处置法式将只处置数据库为呼应对注册对象停止的 DML 或 DDL 更改(也就是说,仅当告诉类型为 EVENT_OBJCHANGE 时)而宣布的告诉,并疏忽有关其他数据库事务(照实例启动或实例封闭)的告诉。从以上版本入手下手,处置法式可以处置针对 OE.ORDERS 表中每一个受影响的行收回的更改告诉。在本文前面的“将表添加到现有注册”局部中,您将向处置法式中添加几行代码,以便它可以处置针对 OE.ORDER_ITEMS 表中被修正的行收回的告诉。
 为更改告诉创立注册
  创立告诉处置法式后,必需为其创立一个查询注册。关于本示例而言,您必需在注册过程当中对 OE.ORDER 表履行查询并将 orders_nf_callback 指定为告诉处置法式。您还需求在 DBMS_CHANGE_NOTIFICATION 法式包中指定 QOS_ROWIDS 选项,以便在告诉动静中启用 ROWID 级其余粒度。“清单 3”是一个 PL/SQL 块,它为 orders_nf_callback 告诉处置法式创立查询注册。
  清单 3. 为告诉处置法式创立查询注册
DECLARE
REGDS SYS.CHNF$_REG_INFO;
regid NUMBER;
ord_id NUMBER;
qosflags NUMBER;
BEGIN
qosflags := DBMS_CHANGE_NOTIFICATION.QOS_RELIABLE +
DBMS_CHANGE_NOTIFICATION.QOS_ROWIDS;
REGDS := SYS.CHNF$_REG_INFO ('orders_nf_callback', qosflags, 0,0,0);
regid := DBMS_CHANGE_NOTIFICATION.NEW_REG_START (REGDS);
SELECT order_id INTO ord_id FROM orders WHERE ROWNUM<2;
DBMS_CHANGE_NOTIFICATION.REG_END;
END;
/
  本示例针对 ORDERS 表创立了一个注册,并将 orders_nf_callback 用作告诉处置法式。如今,假如您利用 DML 或 DDL 语句修正 ORDERS 表并提交事务,则将主动挪用 orders_nf_callback 函数。例如,您能够针对 ORDERS 表履行以下 UPDATE 语句并提交该事务:
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2422;
COMMIT;
  要确保数据库宣布了告诉来呼应以上事务,您可以反省 nfresults 表:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
tblname, rslt_msg FROM nfresults;
  了局应以下所示:
OPERDATE            TBLNAME   RSLT_MSG
--------------------- ----------- ---------
02-mar-06 04:31:28    OE.ORDERS   Not Found
02-mar-06 04:31:29    OE.ORDERS   Not Found
  从以上了局中可以清晰地看到,orders_nf_callback 已正常任务,但未找到客户端剧本。在该示例中呈现这类情形其实不不测,这是由于您并未创立 URL 中指定的 dropResults.php 剧本。
  将表添加到现有注册
  前一局部引见了若何利用更改告诉办事使数据库在注册对象(在以上示例中为 ORDERS 表)产生更改时收回告诉。但从功能角度而言,客户端使用法式能够更但愿缓存 ORDER_ITEMS 表而非 ORDERS 表自己的查询了局集,这是由于它在每次会见定单时,不能不从 ORDERS 表中只检索一行,但同时必需从 ORDER_ITEMS 表中检索多个行。在实践情形中,定单能够包括数十个乃至数百个定单项。
  因为您已对 ORDERS 表注册了查询,因而不用再创立一个注册来注册对 ORDER_ITEMS 表的查询了。相反,您可使用现有注册。为此,您起首需求检索现有注册的 ID。可以履行以下查询来完成此任务:
SELECT regid, table_name FROM user_change_notification_regs;  了局能够以下所示:
REGID TABLE_NAME
----- --------------
241 OE.ORDERS
  获得注册 ID 后,可使用 DBMS_CHANGE_NOTIFICATION.ENABLE_REG 函数将一个新对象添加到该注册,以下所示:
DECLARE
ord_id NUMBER;
BEGIN
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
SELECT order_id INTO ord_id FROM order_items WHERE ROWNUM < 2;
DBMS_CHANGE_NOTIFICATION.REG_END;
END;
/
  完成了!从如今入手下手,数据库将生成一个告诉来呼应对 ORDERS 和 ORDER_ITEMS 所做的任何更改,并挪用 orders_nf_callback 进程来处置告诉。因而,下一步就是编纂 orders_nf_callback,以便它可以处置因对 ORDER_ITEMS 表履行 DML 操作而生成的告诉。但在从头创立 orders_nf_callback 进程之前,您需求创立以下将在更新过程当中援用的表类型:
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC;  然后,前往清单,在以下代码行以后:
IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM orders WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
END LOOP;
END IF;
  拔出以下代码:
IF (tblname = 'OE.ORDER_ITEMS') THEN
FOR rec IN (SELECT DISTINCT(o.order_id) o_id FROM
TABLE(CAST(ntfnds.table_desc_array(i).row_desc_array AS rdesc_tab)) t,
orders o, order_items d WHERE t.row_id = d.rowid AND d.order_id=o.order_id)
LOOP
sendNotification(url, tblname, rec.o_id);
END LOOP;
END IF;
  从头创立 orders_nf_callback 后,您需求测试它可否正常任务。为此,您可以针对 ORDER_ITEMS 表履行以下 UPDATE 语句并提交该事务:
UPDATE ORDER_ITEMS SET quantity = 160 WHERE order_id=2421 AND line_item_id=1;
UPDATE ORDER_ITEMS SET quantity = 160 WHERE order_id=2421 AND line_item_id=2;
COMMIT;
  然后,反省 nfresults 表,以下所示:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
rslt_msg FROM nfresults WHERE tblname = 'OE.ORDER_ITEMS';  输入能够以下所示:
OPERDATE            RSLT_MSG
------------------- --------------
03-mar-06 12:32:27Not Found
  您能够很奇异为何只向 nfresults 表中拔出了一行 C 究竟您更新了 ORDER_ITEMS 表中的两行。实践上,这两个更新了的行具有不异的 order_id C 即它们属于统一定单。此处,咱们假定客户端使用法式将利用一个语句选择定单的一切定单项,因而它其实不需求切实晓得已更改了某个定单的哪些定单项。相反,客户端需求晓得个中最少修正、删除或拔出了一个定单项的定单 ID。
 构建客户端

  如今,您已针对 ORDERS 和 ORDER_ITEMS 表创立了注册,上面咱们将懂得一下会见这些表中存储的定单及其定单项的客户端使用法式若何利用更改告诉。为此,您可以构建一个 PHP 使用法式,它将缓存针对以上表的查询了局,并接纳响应的操作来呼应有关对这些表所做更改的告诉(从数据库办事器中收到这些告诉)。一个复杂的办法是利用 PEAR::Cache_Lite 法式包,它为您供应了一个牢靠的机制来使缓存数据坚持最新形态。特别是,您可使用 Cache_Lite_Function 类(PEAR::Cache_Lite 法式包的一局部),经由过程该类您可以缓存函数挪用。

  例如,您可以创立一个函数来履行以下义务:创立数据库毗连、针对该数据库履行 select 语句、获得检索了局并终究以数组模式前往了局。然后,您可以经由过程 Cache_Lite_Function 实例的 call 办法缓存由该函数前往的了局数组,以即可以从当地缓存而不是从后端数据库读取这些数组,如许可以明显进步使用法式的功能。然后,在收到缓存数据更改的告诉时,您将利用 Cache_Lite_Function 实例的 drop 办法删除缓存中的过时数据。

  回过火来看看本文的示例,您能够要创立两个函数,用于使用法式与数据库交互:第一个函数将查询 ORDERS 表并前往具有指定 ID 的定单,而另外一个函数将查询 ORDER_ITEMS 表并前往该定单的定单项。“清单 4”显示了包括 getOrderFields 函数(该函数承受定单 ID 并前往一个包括所检索到定单的某些字段的联系关系数组)的 getOrderFields.php 剧本。

  清单 4. 获得指定定单的字段

<?php //File:getOrderFields.php require_once 'connect.php'; function getOrderFields($order_no) { if (!$rsConnection = GetConnection()){ return false; } $strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE, CUSTOMER_ID, ORDER_TOTAL FROM ORDERS WHERE order_id =:order_no"; $rsStatement = oci_parse($rsConnection,$strSQL); oci_bind_by_name($rsStatement, ":order_no", $order_no, 12); if (!oci_execute($rsStatement)) { $err = oci_error(); print $err['message']; trigger_error('Query failed:' . $err['message']); return false; } $results = oci_fetch_assoc($rsStatement); return $results; } ?>
  “清单 5”是 getOrderItems.php 剧本。该剧本包括 getOrderItems 函数,该函数承受定单 ID 并前往一个二维数组,该数组包括暗示定单的定单项的行。

  清单 5. 获得指定定单的定单项

<?php //File:getOrderItems.php require_once 'connect.php'; function getOrderItems($order_no) { if (!$rsConnection = GetConnection()){ return false; } $strSQL = "SELECT * FROM ORDER_ITEMS WHERE order_id =:order_no ORDER BY line_item_id"; $rsStatement = oci_parse($rsConnection,$strSQL); oci_bind_by_name($rsStatement, ":order_no", $order_no, 12); if (!oci_execute($rsStatement)) { $err = oci_error(); trigger_error('Query failed:' . $err['message']); return false; } $nrows = oci_fetch_all($rsStatement, $results); return array ($nrows, $results); } ?>
  注重,以上两个函数都需求 connect.php 剧本,该剧本应包括前往数据库毗连的 GetConnection 函数。清单 6 就是 connect.php 剧本:

  清单 6. 获得数据库毗连

<?php //File:connect.php function GetConnection() { $dbHost = "dbserverhost"; $dbHostPort="1521"; $dbServiceName = "orclR2"; $usr = "oe"; $pswd = "oe"; $dbConnStr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$dbHost.") (PORT=".$dbHostPort."))(CONNECT_DATA=(SERVICE_NAME=".$dbServiceName.")))"; if(!$dbConn = oci_connect($usr,$pswd,$dbConnStr)) { $err = oci_error(); trigger_error('Failed to connect ' .$err['message']); return false; } return $dbConn; } ?>
  如今,您已创立了与数据库通讯所需的一切函数,上面咱们将懂得一下 Cache_Lite_Function 类的任务体例。清单 7 是 testCache.php 剧本,该剧本利用 Cache_Lite_Function 类缓存以上函数的了局。

  清单 7. 利用 PEAR::Cache_Lite 缓存

<?php //File:testCache.php require_once 'getOrderItems.php'; require_once 'getOrderFields.php'; require_once 'Cache/Lite/Function.php'; $options = array( 'cacheDir' => '/tmp/', 'lifeTime' => 86400 ); if (!isset($_GET['order_no'])) { die('The order_no parameter is required'); } $order_no=$_GET['order_no']; $cache = new Cache_Lite_Function($options); if ($orderfields = $cache->call('getOrderFields', $order_no)){ print "<h3>ORDER #$order_no</h3>\n"; print "<table>"; print "<tr><td>DATE:</td><td>".$orderfields['ORDER_DATE']."</td></tr>"; print "<tr><td>CUST_ID:</td><td>".$orderfields['CUSTOMER_ID']."</td></tr>"; print "<tr><td>TOTAL:</td><td>".$orderfields['ORDER_TOTAL']."</td></tr>"; print "</table>"; } else { print "Some problem occurred while getting order fields!\n"; $cache->drop('getOrderFields', $order_no); } if (list($nrows, $orderitems) = $cache->call('getOrderItems', $order_no)){ //print "<h3>LINE ITEMS IN ORDER #$order_no</h3>"; print "<table border=1>"; print "<tr>\n"; while (list($key, $value) = each($orderitems)) { print "<th>$key</th>\n"; } print "</tr>\n"; for ($i = 0; $i < $nrows; $i++) { print "<tr>"; print "<td>".$orderitems['ORDER_ID'][$i]."</td>"; print "<td>".$orderitems['LINE_ITEM_ID'][$i]."</td>"; print "<td>".$orderitems['PRODUCT_ID'][$i]."</td>"; print "<td>".$orderitems['UNIT_PRICE'][$i]."</td>"; print "<td>".$orderitems['QUANTITY'][$i]."</td>"; print "</tr>"; } print "</table>"; } else { print "Some problem occurred while getting order line items"; $cache->drop('getOrderItems', $order_no); } ?>
  “清单 7”中的 testCache.php 剧本应与 order_no URL 参数(代表 OE.ORDER 表中存储的定单 ID)一同被挪用。例如,要检索与 ID 为 2408 的定单相干的信息,需求在阅读器中输出以下所示的 URL:

http://webserverhost/phpcache/testCache.php?order_no=2408  了局,阅读器将生成以下输入:

  ORDER #2408

DATE: 29-JUN-99 06.59.31.333617 AM CUST_ID: 166 TOTAL: 309
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE QUANTITY 2408 1 2751 61 3 2408 2 2761 26 1 2408 3 2783 10 10
 如今,假如您单击阅读器中的 reload 按钮,testCache.php 剧本将不会再次挪用 getOrderFields 和 getOrderItems 函数。相反,它将从当地缓存中读取它们的了局。因而,从如今起的 24 小时(由于 lifeTime 设置为 86400 秒)之内,当地缓存便可知足利用 order_no=2108 的每一个 getOrderFields 或 getOrderItems 挪用的需求。但请注重,Cache_Lite_Function 类未供应 API 来测试具有给定参数的给定函数是不是存在可用缓存。因而,要肯定每次利用不异参数挪用函数时使用法式是实践上读取缓存仍是仍履行该函数能够有点辣手。例如,在以上示例中,要确保缓存机制正常任务,您可以一时更改 connect.php 剧本中指定的毗连信息,以便它没法创立数据库毗连;好比指定一个毛病的数据库办事器主机称号,然后再次利用 order_no=2108 运转 testCache.php 剧本。假如缓存正常任务,阅读器的输入应与先前的一样。

  另外,您还可以反省缓存目次,该目次作为 cacheDir 选项的值(在该示例中为 /tmp)传递给 Cache_Lite_Function 类的机关函数。在该目次中,您将找到两个刚创立的缓存文件,这些文件的称号相似于:cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154。注重,假如您是一名 Windows 用户,则能够要利用 %SystemDrive%\temp 目次保留缓存文件。假如是如许,则必需将 cacheDir 选项设置为 /temp/。

  验证缓存机制正常任务后,可以接着创立一个 PHP 来处置从数据库办事器收到的更改告诉。“清单 8”是 dropResult.php 剧本。数据库办事器将挪用该剧本来呼应 ORDERS 和 ORDER_ITEMS 表的更改。

  清单 8. 处置从数据库办事器收到的更改告诉

<?php //File:dropResults.php require_once 'Cache/Lite/Function.php'; $options = array( 'cacheDir' => '/tmp/' ); $cache = new Cache_Lite_Function($options); if (isset($_GET['order_no'])&& isset($_GET['table'])) { if($_GET['table']=='ORDER_ITEMS'){ $cache->drop('getOrderItems', $_GET['order_no']); } if ($_GET['table']=='ORDERS'){ $cache->drop('getOrderFields', $_GET['order_no']); } } ?>
  创立 dropResult.php 剧本后,请确保在告诉处置法式中指定的 URL(如清单 2 所示)准确。然后,在 SQL*Plus 或相似东西中以 OE/OE 毗连,并履行 UPDATE 语句,这些语句将影响本局部先前经由过程 testCache.php 剧本会见的统一定单(此处是 ID 为 2408 的定单):

UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2408; UPDATE ORDER_ITEMS SET quantity = 3 WHERE order_id=2408 AND line_item_id=1; UPDATE ORDER_ITEMS SET quantity = 1 WHERE order_id=2408 AND line_item_id=2; COMMIT;
  为呼应以上更新,本文后面引见的告诉处置法式将逐一利用以下 URL 运转 dropResults.php 剧本两次:

http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
  从“清单 8”中您可以清晰地看到,dropResult.php 剧本在从数据库办事器收到更改告诉后并未刷新缓存。它只是删除包括过时数据的缓存文件。因而,假如如今反省缓存目次,则将看到在利用 order_no=2408 运转 testCache.php 剧本时创立的缓存文件已消逝。这实践上意味着,testCache.php 鄙人次恳求与 ID 为 2408 的定单相干的数据时将从后端数据库而非当地缓存中获得该数据。

  您会发明,在使用法式恳求的了局集很有能够在使用法式利用它之前更改的情形下该办法将很有效。就本文的示例而言,这意味着与特定定单相干的数据能够在 testCache.php 会见该定单之前屡次更改。如许,使用法式会因在从数据库办事器收到更改告诉后当即刷新它的缓存而做了大批不用要的任务。

  但假如您但愿 dropResult.php 剧本在收到更改告诉后当即刷新缓存,则可以在挪用 drop 办法后挪用 Cache_Lite_Function 实例的 call 办法,并为这两个挪用指定不异的参数。在该情况下,还应确保包括 getOrderFields.php 和 getOrderItems.php 剧本,以便 dropResults.php 可以挪用 getOrderFields 和 getOrderItems 函数来刷新缓存。“清单 9”是修正后的 dropResult.php 剧本。

  清单 9. 在收到更改告诉后当即刷新缓存

<?php //File:dropResults.php require_once 'Cache/Lite/Function.php'; require_once 'getOrderItems.php'; require_once 'getOrderFields.php'; $options = array( 'cacheDir' => '/tmp/', 'lifeTime' => 86400 ); $cache = new Cache_Lite_Function($options); if (isset($_GET['order_no'])&& isset($_GET['table'])) { if($_GET['table']=='ORDER_ITEMS'){ $cache->drop('getOrderItems', $_GET['order_no']); $cache->call('getOrderItems', $_GET['order_no']); } if ($_GET['table']=='ORDERS'){ $cache->drop('getOrderFields', $_GET['order_no']); $cache->call('getOrderFields', $_GET['order_no']); } } ?>
  假如存储在 ORDERS 和 ORDER_ITEMS 表中的数据很少更改而且使用法式频仍会见它,则以上办法能够很有效。

  总结

  假如 PHP 使用法式与 Oracle 数据库 10g 第 2 版交互,则可以使用“数据库更改告诉特征”,经由过程该特征使用法式可以吸收告诉来呼应对与收回的恳求联系关系的对象停止的 DML 更改。利用该特征,您不用在特准时间段更新使用法式中的缓存。相反,仅当注册查询的了局集已更改时才履行该操作
也或许是因为我还没有真正的学到深处吧,说实在的,PHP中的很多高级点的应用,如PHP类、PHP函数基本还是不懂吧!

灵魂腐蚀 发表于 2015-2-4 10:03:42

不禁又想起那些说php是草根语言的人,为什么认得差距这么大呢。

因胸联盟 发表于 2015-2-9 22:03:46

本文当是我的笔记啦,遇到的问题随时填充

飘灵儿 发表于 2015-2-14 17:29:24

首先声明:我是一个菜鸟,是一个初学者。学习了一段php后总是感觉自己没有提高,无奈。经过反思我认为我学习过程中存在很多问题,我改变了学习方法后自我感觉有了明显的进步。

仓酷云 发表于 2015-2-25 03:37:32

php里的数组为空的时候是不能拿来遍历的;(这个有点低级啊,不过我刚被这个边界问题墨迹了好长一会)

小女巫 发表于 2015-3-7 16:21:48

对于懒惰的朋友,我推荐php的集成环境xampp或者是wamp。这两个软件安装方便,使用简单。但是我还是强烈建议自己动手搭建开发环境。

小女巫 发表于 2015-3-7 16:21:49

本人接触php时间不长,算是phper中的小菜鸟一只吧。由于刚开始学的时候没有名师指,碰过不少疙瘩,呗很多小问题卡过很久,白白浪费不少宝贵的时间,在次分享一些子的学习的心得。

飘飘悠悠 发表于 2015-3-13 00:09:44

要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。

爱飞 发表于 2015-3-13 04:10:53

基础有没有对学习php没有太大区别,关键是兴趣。

老尸 发表于 2015-3-19 11:54:56

爱上php,他也会爱上你。

再见西城 发表于 2015-3-27 20:09:32

作为一个合格的coder 编码的规范是必须,命名方面我推崇“驼峰法”,另外就是自己写的代码最好要带注释,不然时间长了,就算是自己的代码估计看起来都费事,更不用说别人拉。

再现理想 发表于 2015-3-28 06:44:23

在学习的过程中不能怕麻烦,不能有懒惰的思想。学习php首先应该搭建一个lamp环境或者是wamp环境。这是学习php开发的根本。虽然网络上有很多集成的环境,安装很方便,使用起来也很稳定、

第二个灵魂 发表于 2015-4-4 09:59:13

对于懒惰的朋友,我推荐php的集成环境xampp或者是wamp。这两个软件安装方便,使用简单。但是我还是强烈建议自己动手搭建开发环境。

兰色精灵 发表于 2015-4-17 05:03:17

装在C盘下面可以利用windows的ghost功能可以还原回来(顺便当做是重转啦),当然啦我的编译目录要放在别的盘下,不然自己的劳动成果就悲剧啦。

柔情似水 发表于 2015-4-26 15:10:25

使用 jquery 等js框架的时候,要随时注意浏览器的更新情况,不然很容易发生框架不能使用。

简单生活 发表于 2015-4-29 12:56:20

遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。

蒙在股里 发表于 2015-5-1 05:10:29

因为blog这样的可以让你接触更多要学的知识,可以接触用到类,模板,js ,ajax

金色的骷髅 发表于 2015-6-16 21:01:18

首先声明:我是一个菜鸟,是一个初学者。学习了一段php后总是感觉自己没有提高,无奈。经过反思我认为我学习过程中存在很多问题,我改变了学习方法后自我感觉有了明显的进步。

海妖 发表于 2015-6-20 20:54:00

遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。

若天明 发表于 2015-7-11 21:21:12

如果你可以写完像留言板这样的程序,那么你可以去一些别人的代码了,
页: [1] 2
查看完整版本: PHP教程之经由过程缓存数据库了局进步PHP功能