.htaccess Files for the Rest of Us

.htaccess files are used to configure Apache, as well a range of other web servers. Despite the .htaccess file type extension, they are simply text files that can be edited using any text-editor. In this article, we’ll review what they are, and how you can use them in your projects.

 

Please note that .htaccess files don’t work on Windows-based systems, although they can be edited and uploaded to a compatible web server, and on Linux-based systems they are hidden by default.

In order to work with htaccess files locally, to see how they work and generally play around with them, we can use XAMPP (or MAMP) on the Mac – a package that installs and configures Apache, PHP and MySQL. To edit these .htaccess files on Mac, we should use a text editor that allows for the opening of hidden files, such as TextWrangler.

A .htaccess file follows the same format as Apache’s main configuration file: httpd.conf. Many of the settings that can be configured using the main configuration file can also be configured with them, and vice versa.

A setting configured in an .htaccess file will override the same setting in the main configuration file for the directory which contains the file, as well as all of its subdirectories.

They are sometimes referred to as dynamic configuration files because they are read by the server on every request to the directory they are contained within. This means that any changes to an .htaccess file will take effect immediately, without requiring a reboot of the server, unlike changes made to the global configuration file. It also means that you pay a slight performance hit for using them, but they can be useful when you don’t have access to the server’s main configuration file.

So now we all know what .htaccess files are, how they are edited and worked with, and some of their pros and cons, let’s look at how they can be used and some of the cool stuff they can do.


Redirects and URL Rewriting

A popular use of .htaccess files is to perform redirects or rewrite URLs. This can help with SEO following a domain name change, or file-structure reorganisation, or can make long unsightly URL more friendly and memorable.

Redirections

A redirection can be as simple as the following:

1
Redirect 301 ^old\.html$ http://localhost/new.html

This sets the HTTP status code to 301 (moved permanently) and redirects all requests to old.html transparently to new.html. We use a regular expression to match the URL to redirect, which gives us a fine degree of control to ensure only the correct URL is matched for redirection, but adds complexity to the configuration and administration of it. The full URL of the resource being redirected to is required.

Rewrites

A rewrite rule can be as simple as this:

1
2
RewriteEngine on
RewriteRule ^old\.html$ new.html

In this example, we just provide a simple file redirect from one file to another, which will also be performed transparently, without changing what is displayed in the address bar. The first directive, RewriteEngine on, simply ensures that the rewrite engine is enabled.

In order to update what is displayed in the address bar of the visitor’s browser, we can use the R flag at the end of the RewriteRule e.g.

1
RewriteRule ^old\.html$ http://hostname/new.html [r=301]

The r flag causes an external redirection which is why the full URL (an example URL here) to the new page is given. We can also specify the status code when using the flag. This causes the address bar to be updated in the visitor’s browser.

One of the possible uses for URL rewriting I gave at the start of this section was to make unsightly URLs (containing query-string data) friendlier to visitors and search engines. Let’s see this in action now:

1
RewriteRule ^products/([^/]+)/([^/]+)/([^/]+) product.php?cat=$1&brand=$2&prod=$3

This rule will allow visitors to use a URL like products/turntables/technics/sl1210, and have it transformed into product.php?cat=turntables&<WBR>brand=technics&prod=sl1210. The parentheses in between the forward slashes in the above regular expression are capturing groups – we can use each of these as $1, $2 and $3 respectively. The [^/]+ character class within the parentheses means match any character except a forward-slash 1 or more times.

In practice, URL rewriting can be (and usually is) much more complex and achieve far greater things than this. URL rewriting is better explained using entire tutorials so we won’t look at them in any further detail here.


Serving Custom Error Pages

It’s just not cool to show the default 404 page anymore. Many sites take the opportunity offered by a file not found error to inject a little humour into their site, but at the very least, people expect the 404 page of a site to at least match the style and theme of any other page of the site.

Very closely related to URL rewriting, serving a custom error page instead of the standard 404 page is easy with an .htaccess file:

1
ErrorDocument 404 "/404.html"

That’s all we need; whenever a 404 error occurs, the specified page is displayed. We can configure pages to be displayed for many other server errors too.


Restricting Access to Specific Resources

Using .htaccess files, we can enable password protection of any file or directory, to all users, or based on things like domain or IP address. This is after all one of their core uses. To prevent access to an entire directory, we would simple create a new .htaccess file, containing the following code:

1
2
3
4
AuthName "Username and password required"
AuthUserFile /path/to/.htpasswd
Require valid-user
AuthType Basic

This file should then be saved into the directory we wish to protect. The AuthName directive specifies the message to display in the username/password dialog box, the AuthUserFile should be the path to the .htpasswd file. The Require directive specifies that only authenticated users may access the protected file while the AuthType is set to Basic.

To protect a specific file, we can wrap the above code in a <files> directive, which specifies the protected file:

1
2
3
4
5
6
<Files "protectedfile.html">
   AuthName "Username and password required"
   AuthUserFile /path/to/.htpasswd
   Require valid-user
    AuthType Basic
</Files>

We also require an .htpasswd file for these types of authentication, which contains a colon-separated list of usernames and encrypted passwords required to access the protected resource(s). This file should be saved in a directory that is not accessible to the web. There are a range of services that can be used to generate these files automatically as the password should be stored in encrypted form.


Block Access to Certain Entities

Another use of .htaccess files is to quickly and easily block all requests from an IP address or user-agent. To block a specific IP address, simply add the following directives to your .htaccess file:

 
1
2
3
order allow,deny
deny from 192.168.0.1
allow from all

The order directive tells Apache in which order to evaluate the allow/deny directives. In this case, allow is evaluated first, then deny. The allow from all directive is evaluated first (even though it appears after the deny directive) and all IPs are allowed, then if the client’s IP matches the one specified in the deny directive, access is forbidden. This lets everyone in except the specified IP. Note that we can also deny access to entire IP blocks by supplying a shorter IP, e.g. 192.168.

To deny requests based on user-agent, we could do this:

1
2
RewriteCond %{HTTP_USER_AGENT} ^OrangeSpider
RewriteRule ^(.*)$ http://%{REMOTE_ADDR}/$ [r=301,l]

In this example, any client with a HTTP_USER_AGENT string starting with OrangeSpider (a bad bot) is redirected back to the address that it originated from. The regular expression matches any single character (.) zero or more times (*) and redirects to the %{REMOTE_ADDR} environment variable. The l flag we used here instructs Apache to treat this match as the last rule so will not process any others before performing the rewrite.


Force an IE Rendering Mode

Alongside controlling how the server responds to certain requests, we can also do things to the visitor’s browser, such as forcing IE to render pages using a specific rendering engine. For example, we can use the mod_headers module, if it is present, to set the X-UA-Compatible header:

1
Header set X-UA-Compatible "IE=Edge"

Adding this line to an .htaccess file will instruct IE to use the highest rendering mode available. As demonstrated by HTML5 Boilerplate, we can also avoid setting this header on files that don’t require it by using a <FilesMatch directive like so:

1
2
3
<FilesMatch "\.(js|css|gif|png|jpe?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|xpi|safariextz|vcf)$" >
      Header unset X-UA-Compatible
</FilesMatch>


Implement Caching

Caching is easy to set up and can make your site load faster.

Caching is easy to set up and can make your site load faster. ‘Nuff said! By setting a far-future expires date on elements of sites that don’t change very often, we can prevent the browser from requesting unchanged resources on every request.

If you’re running your site through Google PageSpeed or Yahoo’s YSlow and you get the message about setting far-future expiry headers, this is how you fix it:

1
2
3
4
5
6
7
8
9
10
ExpiresActive on
ExpiresActive on
ExpiresByType image/gif                 "access plus 1 month"
ExpiresByType image/png                 "access plus 1 month"
ExpiresByType image/jpg                 "access plus 1 month"
ExpiresByType image/jpeg                "access plus 1 month"
ExpiresByType video/ogg                 "access plus 1 month"
ExpiresByType audio/ogg                 "access plus 1 month"
ExpiresByType video/mp4                 "access plus 1 month"
ExpiresByType video/webm                "access plus 1 month"

You can add different ExpiresByType directives for any content that is listed in the performance tool you’re using, or anything else that you want to control caching on. The first directive, ExpiresActive on, simply ensures the generation of Expires headers is switched on. These directives depend on Apache having the mod_expires module loaded.


Enabling Compression

Another warning we may get in a performance checker refers to enabling compression, and this is also something we can fix simply by updating our .htaccess file:

1
2
3
4
5
6
FilterDeclare   COMPRESS
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/javascript
FilterChain     COMPRESS
FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no

This compression scheme works on newer versions of Apache (2.1+) using the mod_filter module. It uses the DEFLATE compression algorithm to compress content based on its response content-type, in this case we specify text/html, text/css and text/javascript (which will likely be the types of files flagged in PageSpeed/Yslow anyhow).

In the above example we start out by declaring the filter we wish to use, in this case COMPRESS, using the FilterDeclare directive. We then list the content types we wish to use this filter. The FilterChain directive then instructs the server to build a filter chain based on the FilterProvider directives we have listed. The FilterProtocol directive allows us to specify options that are applied to the filter chain whenever it is run, the options we need to use are change=yes (the content may be changed by the filter (in this case, compressed)) and byteranges=no (the filter must only be applied to complete files).

On older versions of Apache, the mod_deflate module is used to configure DEFLATE compression. We have less control of how the content is filtered in this case, but the directives are simpler:

1
2
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/javascript

In this case we just set the compression algorithm using the SetOutputFilter directive, and then specify the content-types we’d like to compress using the AddOutputFilterByType directive.

Usually your web server will use one of these modules depending on which version of Apache is in use. Generally, you will know this beforehand, but if you are creating a generic .htaccess file that you can use on a variety of sites, or which you may share with other people and therefore you don’t know which modules may be in use, you may wish to use both of the above blocks of code wrapped in <IfModule module_name> directives so that the correct module is used and the server doesn’t throw a 500 error if we try to configure a module that isn’t included. You should be aware that it’s also relatively common for hosts that run a large number of sites from a single box to disable compression as there is a small CPU performance hit for compressing on the server.


Summary

We looked at some of the most common uses for .htaccess files, and reviewed how we can achieve certain tasks that, as website builders/maintainers, are of particular interest to us. As is the case with any introductory tutorial of this nature, the subjects we’ve covered are presented as introductions to a particular topic. There are many other options and configurations than we have been able to look at, so I’d strongly recommend further reading on any subject that is of particular interest.

Posted by sqlwang in web - Comments (0)
30 一月

webdav简介–开发,原理

概述

      随着对  Internet   标准和网络互操作性的日益关注,作为  HTTP   1.1 的扩展,WebDAVWeb   分布式创作和版本控制)已经成为重要的 Web 通讯协议(有关详细信息,请参阅 IETF RFC 2616)。 WebDAV 规范(有关详细信息,请参阅 IETF RFC 2518)在 1999 年 2 月由 Internet 工程任务组 (IETF) 发布,这中间有 Microsoft 的巨大贡献,以及许多第三方供应商(如  NetscapeXeroxIBM    Novell )的支持。

      由于 WebDAV 与可扩展标记语言 (XML ) 固有的集成,因此它不仅非常依赖 XML,而且已经成为通过 Web 传送 XML 数据的绝佳方法。 但是,在完全了解这些技术所带来的好处之前,一定要先了解什么是 WebDAV,以及它在客户端/服务器体系结构中的用途。

WebDAV的优势

      由于 Web 已经成为 Internet 的基础,因此 HTTP 1.1(超文本传送协议)被证实是用来传输数据的非常灵活的通用协议。 但是,HTTP 存在一些明显的缺点,从而限制了它作为综合的 Internet 通讯协议而被采用: 它非常适合用于查看的静态文档,但不能提供以足够复杂(以便向客户端提供丰富的创作功能)的方式来处理文档的方法。

      例如,当两个作者在未进行交流的情况下同时对一个文档进行更改时,就会出现“更新丢失”问题。 只有由最后一个作者完成、并将修改后的文档重新上载到服务器的修改才会保留下来,另一个作者进行的更改将丢失。

      IETF WebDAV 工作组的目标是,设计一个协议,它提供基于标准的论坛中任何分布式创作工具需要的功能。 当前的 WebDAV 规范 (IETF RFC 2518) 解决协作式创作工具的三个主要问题:

 

 

改写保护。 HTTP 1.1 无法确保客户端可以保护资源,并且可以在其他客户端同时编辑它们的情况下进行更改。 使用 WebDAV,可以通过多种方式来锁定资源,以便让其他客户端知道您对所讨论的资源感兴趣,或者防止其他客户端访问该资源。

资源管理。 HTTP 只能直接访问单个资源。 WebDAV 提供一种更有效地组织数据的方法。 WebDAV 引入了可包含资源  集合 (类似于文件系统文件夹)概念。 通过 WebDAV 进行的资源管理包括如下功能:创建、移动、复制和删除集合,以及集合中的资源或文件。

文档属性。 不同类型的数据具有唯一的属性,这有助于描述数据。 例如,在电子邮件中,这些属性可能是发件人的姓名和接收邮件的时间。 在协作文档中,这些属性可能是文档原始作者的姓名和最后一个编辑者的姓名。 因为人们使用的文档类型各不相同,所以可能的属性类型列表也变得无限大。 XML 是 WebDAV 所需的一种可扩展通讯工具。

WebDAV 请求的格式

 

    HTTP   1.1(请参阅 IETF RFC 2068)提供一组可供客户端与服务器通讯的方法,并指定响应(从服务器返回发出请求的客户端)的格式。 WebDAV 完全采用此规范中的所有方法,扩展其中的一些方法,并引入了其他可提供所描述功能的方法。 WebDAV 中使用的方法包括:

 

 

OptionsHead    Trace 。 主要由应用程序用来发现和跟踪服务器支持和网络行为。

Get 。 检索文档。

Put    Post 。 将文档提交到服务器。

Delete 。 销毁资源或集合。

Mkcol 。 创建集合。

PropFind    PropPatch 。 针对资源和集合检索和设置属性。

Copy    Move 。 管理命名空间上下文中的集合和资源。

Lock    Unlock 。 改写保护。

 

WebDAV 请求的一般结构遵循 HTTP 的格式并且由以下三个组件构成:

 

 

方法 。 声明由客户端执行的方法(上面描述的方法)。

标头 。 描述有关如何完成此任务的指令。

主体 (可选)。 定义用在该指令或其他指令中的数据,用以描述如何完成此方法。

 

在主体组件中,XML   成为整个 WebDAV 结构中的关键元素。

Posted by sqlwang in web - Comments (0)
27 九月

oracle存储过程语法

oracle存储过程语法
1.基本结构
CREATE OR REPLACE PROCEDURE 存储过程名字
(
    参数1 IN NUMBER,
    参数2 IN NUMBER
) IS
变量1 INTEGER :=0;
变量2 DATE;
BEGIN

END 存储过程名字

2.SELECT INTO STATEMENT
  将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
  记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)
  例子:
  BEGIN
  SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
      xxxx;
  END;
  …

3.IF 判断
  IF V_TEST=1 THEN
    BEGIN
       do something
    END;
  END IF;

4.while 循环
  WHILE V_TEST=1 LOOP
  BEGIN
XXXX
  END;
  END LOOP;

5.变量赋值
  V_TEST := 123;

6.用for in 使用cursor
  …
  IS
  CURSOR cur IS SELECT * FROM xxx;
  BEGIN
FOR cur_result in cur LOOP
  BEGIN
   V_SUM :=cur_result.列名1+cur_result.列名2
  END;
END LOOP;
  END;

7.带参数的cursor
  CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
  OPEN C_USER(变量值);
  LOOP
FETCH C_USER INTO V_NAME;
EXIT FETCH C_USER%NOTFOUND;
    do something
  END LOOP;
  CLOSE C_USER;

Posted by sqlwang in 数据库 - Comments (0)
6 八月

PHP导入导出Excel方法(转)

看到这篇文章的时候,很是惊讶原作者的耐心,虽然我们在平时用的也 有一些,但没有作者列出来的全,写excel的时候,我用过pear的库,也用过pack压包的头,同样那些利用smarty等作的简单替换xml的也用 过,csv的就更不用谈了。呵呵。(COM方式不讲了,这种可读的太多了,我也写过利用wps等进行word等的生成之类的文章 )
但是在读的时候,只用过一种,具体是什么忘了,要回去翻代码了。因为采用的是拿来主义,记不住。
原文地址:http://xinsync.xju.edu.cn/index.php/archives/3858
原文内容:

最近因项目需要,需要开发一个模块,把系统中的一些数据导出成Excel,修改后再导回系统。就趁机对这个研究了一番,下面进行一些总结。
基本上导出的文件分为两种:
1:类Excel格式,这个其实不是传统意义上的Excel文件,只是因为Excel的兼容能力强,能够正确打开而已。修改这种文件后再保存,通常会提示你是否要转换成Excel文件。
优点:简单。
缺点:难以生成格式,如果用来导入需要自己分别编写相应的程序。
2:Excel格式,与类Excel相对应,这种方法生成的文件更接近于真正的Excel格式。

如果导出中文时出现乱码,可以尝试将字符串转换成gb2312,例如下面就把$yourStr从utf-8转换成了gb2312:
$yourStr = mb_convert_encoding(”gb2312″, “UTF-8″, $yourStr);

下面详细列举几种方法。
一、PHP导出Excel

1:第一推荐无比风骚的PHPExcel,官方网站: http://www.codeplex.com/PHPExcel
导入导出都成,可以导出office2007格式,同时兼容2003。
下载下来的包中有文档和例子,大家可以自行研究。
抄段例子出来:

PHP代码
<?php  
/** 
* PHPExcel 

* Copyright (C) 2006 - 2007 PHPExcel 

* This library is free software; you can redistribute it and/or 
* modify it under the terms of the GNU Lesser General Public 
* License as published by the Free Software Foundation; either 
* version 2.1 of the License, or (at your option) any later version. 

* This library is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
* Lesser General Public License for more details. 

* You should have received a copy of the GNU Lesser General Public 
* License along with this library; if not, write to the Free Software 
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 

* @category   PHPExcel 
* @package    PHPExcel 
* @copyright  Copyright (c) 2006 - 2007 PHPExcel ( http://www.codeplex.com/PHPExcel
* @license    http://www.gnu.org/licenses/lgpl.txt    LGPL 
* @version    1.5.0, 2007-10-23 
*/  
  
/** Error reporting */  
error_reporting(E_ALL);  
  
/** Include path **/  
set_include_path(get_include_path() . PATH_SEPARATOR . ‘../Classes/’);  
  
/** PHPExcel */  
include ‘PHPExcel.php’;  
  
/** PHPExcel_Writer_Excel2007 */  
include ‘PHPExcel/Writer/Excel2007.php’;  
  
// Create new PHPExcel object  
echo date(’H:i:s’) . ” Create new PHPExcel object\n”;  
$objPHPExcel = new PHPExcel();  
  
// Set properties  
echo date(’H:i:s’) . ” Set properties\n”;  
$objPHPExcel->getProperties()->setCreator(”Maarten Balliauw”);  
$objPHPExcel->getProperties()->setLastModifiedBy(”Maarten Balliauw”);  
$objPHPExcel->getProperties()->setTitle(”Office 2007 XLSX Test Document”);  
$objPHPExcel->getProperties()->setSubject(”Office 2007 XLSX Test Document”);  
$objPHPExcel->getProperties()->setDescrīption(”Test document for Office 2007 XLSX, generated using PHP classes.”);  
$objPHPExcel->getProperties()->setKeywords(”office 2007 openxml php”);  
$objPHPExcel->getProperties()->setCategory(”Test result file”);  
  
// Add some data  
echo date(’H:i:s’) . ” Add some data\n”;  
$objPHPExcel->setActiveSheetIndex(0);  
$objPHPExcel->getActiveSheet()->setCellValue(’A1′, ‘Hello’);  
$objPHPExcel->getActiveSheet()->setCellValue(’B2′, ‘world!’);  
$objPHPExcel->getActiveSheet()->setCellValue(’C1′, ‘Hello’);  
$objPHPExcel->getActiveSheet()->setCellValue(’D2′, ‘world!’);  
  
// Rename sheet  
echo date(’H:i:s’) . ” Rename sheet\n”;  
$objPHPExcel->getActiveSheet()->setTitle(’Simple’);  
  
// Set active sheet index to the first sheet, so Excel opens this as the first sheet  
$objPHPExcel->setActiveSheetIndex(0);  
  
// Save Excel 2007 file  
echo date(’H:i:s’) . ” Write to Excel2007 format\n”;  
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);  
$objWriter->save(str_replace(’.php’, ‘.xlsx’, __FILE__));  
  
// Echo done  
echo date(’H:i:s’) . ” Done writing file.\r\n”;  

 

2、使用pear的Spreadsheet_Excel_Writer类
下载地址: http://pear.php.net/package/Spreadsheet_Excel_Writer
此类依赖于OLE,下载地址:http://pear.php.net/package/OLE
需要注意的是导出的Excel文件格式比较老,修改后保存会提示是否转换成更新的格式。
不过可以设定格式,很强大。

PHP代码
<?php  
require_once ‘Spreadsheet/Excel/Writer.php’;  
  
// Creating a workbook  
$workbook = new Spreadsheet_Excel_Writer();  
  
// sending HTTP headers  
$workbook->send(’test.xls’);  
  
// Creating a worksheet  
$worksheet =& $workbook->addWorksheet(’My first worksheet’);  
  
// The actual data  
$worksheet->write(0, 0, ‘Name’);  
$worksheet->write(0, 1, ‘Age’);  
$worksheet->write(1, 0, ‘John Smith’);  
$worksheet->write(1, 1, 30);  
$worksheet->write(2, 0, ‘Johann Schmidt’);  
$worksheet->write(2, 1, 31);  
$worksheet->write(3, 0, ‘Juan Herrera’);  
$worksheet->write(3, 1, 32);  
  
// Let’s send the file  
$workbook->close();  
?>  

3:利用smarty,生成符合Excel规范的XML或HTML文件
支持格式,非常完美的导出方案。不过导出来的的本质上还是XML文件,如果用来导入就需要另外处理了。
详细内容请见rardge大侠的帖子:http://bbs.chinaunix.net/viewthread.php?tid=745757

需要注意的是如果导出的表格行数不确定时,最好在模板中把”ss:ExpandedColumnCount=”5″ ss:ExpandedRowCount=”21″”之类的东西删掉。

4、利用pack函数打印出模拟Excel格式的断句符号,这种更接近于Excel标准格式,用office2003修改后保存,还不会弹出提示,推荐用这种方法。
缺点是无格式。

PHP代码
<?php  
// Send Header  
header(”Pragma: public”);  
header(”Expires: 0″);  
header(”Cache-Control: must-revalidate, post-check=0, pre-check=0″);  
header(”Content-Type: application/force-download”);  
header(”Content-Type: application/octet-stream”);  
header(”Content-Type: application/download”);;  
header(”Content-Disposition: attachment;filename=test.xls “);  
header(”Content-Transfer-Encoding: binary “);  
// XLS Data Cell  
  
xlsBOF();  
xlsWriteLabel(1,0,”My excel line one”);  
xlsWriteLabel(2,0,”My excel line two : “);  
xlsWriteLabel(2,1,”Hello everybody”);  
  
xlsEOF();  
  
function xlsBOF() {  
echo pack(”ssssss”, 0×809, 0×8, 0×0, 0×10, 0×0, 0×0);  
return;  
}  
function xlsEOF() {  
echo pack(”ss”, 0×0A, 0×00);  
return;  
}  
function xlsWriteNumber($Row, $Col, $Value) {  
echo pack(”sssss”, 0×203, 14, $Row, $Col, 0×0);  
echo pack(”d”, $Value);  
return;  
}  
function xlsWriteLabel($Row, $Col, $Value ) {  
$L = strlen($Value);  
echo pack(”ssssss”, 0×204, 8 + $L, $Row, $Col, 0×0, $L);  
echo $Value;  
return;  
}  
?>  
不过笔者在64位linux系统中使用时失败了,断句符号全部变成了乱码。  
  
5、使用制表符、换行符的方法  
制表符”\t”用户分割同一行中的列,换行符”\t\n”可以开启下一行。  
<?php  
header(”Content-Type: application/vnd.ms-execl”);  
header(”Content-Disposition: attachment; filename=myExcel.xls”);  
header(”Pragma: no-cache”);  
header(”Expires: 0″);  
/*first line*/  
echo “hello”.”\t”;  
echo “world”.”\t”;  
echo “\t\n”;  
  
/*start of second line*/  
echo “this is second line”.”\t”;  
echo “Hi,pretty girl”.”\t”;  
echo “\t\n”;  
?>  

6、使用com
如果你的PHP可以开启com模块,就可以用它来导出Excel文件

PHP代码
<?PHP  
$filename = “c:/spreadhseet/test.xls”;  
$sheet1 = 1;  
$sheet2 = “sheet2″;  
$excel_app = new COM(”Excel.application”) or Die (”Did not connect”);  
print “Application name: {$excel_app->Application->value}\n” ;  
print “Loaded version: {$excel_app->Application->version}\n”;  
$Workbook = $excel_app->Workbooks->Open(”$filename”) or Die(”Did not open $filename $Workbook”);  
$Worksheet = $Workbook->Worksheets($sheet1);  
$Worksheet->activate;  
$excel_cell = $Worksheet->Range(”C4″);  
$excel_cell->activate;  
$excel_result = $excel_cell->value;  
print “$excel_result\n”;  
$Worksheet = $Workbook->Worksheets($sheet2);  
$Worksheet->activate;  
$excel_cell = $Worksheet->Range(”C4″);  
$excel_cell->activate;  
$excel_result = $excel_cell->value;  
print “$excel_result\n”;  
#To close all instances of excel:  
$Workbook->Close;  
unset($Worksheet);  
unset($Workbook);  
$excel_app->Workbooks->Close();  
$excel_app->Quit();  
unset($excel_app);  
?>  

一个更好的例子: http://blog.chinaunix.net/u/16928/showart_387171.html

一、PHP导入Excel

1:还是用PHPExcel,官方网站: http://www.codeplex.com/PHPExcel

2:使用PHP-ExcelReader,下载地址: http://sourceforge.net/projects/phpexcelreader
举例:

PHP代码
<?php  
require_once ‘Excel/reader.php’;  
  
// ExcelFile($filename, $encoding);  
$data = new Spreadsheet_Excel_Reader();  
  
// Set output Encoding.  
$data->setOutputEncoding(’utf8′);  
  
$data->read(’ jxlrwtest.xls’);  
  
error_reporting(E_ALL ^ E_NOTICE);  
  
for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) {  
for ($j = 1; $j <= $data->sheets[0]['numCols']; $j++) {  
echo “\”".$data->sheets[0]['cells'][$i][$j].”\”,”;  
}  
echo “\n”;  
}  
  
?>  

———-

Posted by sqlwang in PHP, web - Comments (0)
20 七月

extjs Form验证、表单验证、表单错误提示位置

Ext.QuickTips.init(); //为组件提供提示信息功能,form的主要提示信息就是客户端验证的错误信息。  
Ext.form.Field.prototype.msgTarget=’side’; //提示的方式,枚举值为  
    qtip-当鼠标移动到控件上面时显示提示  
    title-在浏览器的标题显示,但是测试结果是和qtip一样的  
    under-在控件的底下显示错误提示  
    side-在控件右边显示一个错误图标,鼠标指向图标时显示错误提示. 默认值.  
    id-[element id]错误提示显示在指定id的HTML元件中  
1.一个最简单的例子:空验证  
    //空验证的两个参数  
    1.allowBlank:false//false则不能为空,默认为tr  
    2.blankText:string//当为空时的错误提示信息  
    js代码为:  
    var form1 = new Ext.form.FormPanel({  
        width       : 350,  
        renderTo    : "form1",  
        title       : "FormPanel",  
        defaults    : {xtype:"textfield",inputType:"password"},  
        items       : [{  
                id          : "blanktest",  
                fieldLabel  : "不能为空",  
                allowBlank  : false,//不允许为空  
                blankText   : "不能为空"//错误提示信息,默认为This field is required!  
        }]  
    });  
2.用vtype格式进行简单的验证。  
在此举邮件验证的例子,重写上面代码的items配置:  
    items:[{  
        fieldLabel  : "不能为空",  
        vtype       : "email",//email格式验证  
        vtypeText   : "不是有效的邮箱地址",//错误提示信息,默认值我就不说了  
        id          : "blanktest",  
        anchor      : "90%" 
    }  
你可以修改上面的vtype为以下的几种extjs的vtype默认支持的验证:  
//form验证中vtype的默认支持类型  
1.alpha     //只能输入字母,无法输入其他(如数字,特殊符号等)  
2.alphanum  //只能输入字母和数字,无法输入其他  
3.email     //email验证,要求的格式是"langsin@gmail.com"  
4.url       //url格式验证,要求的格式是[url]http://www.langsin.com[/url]  
 
3.高级自定义密码验证  
前面的验证都是extjs已经提供的,我们也可以自定义验证函数。  
//先用Ext.apply方法添加自定义的password验证函数(也可以取其他的名字)  
Ext.apply(Ext.form.VTypes,{  
    password:function(val,field){               //val指这里的文本框值,field指这个文本框组件,大家要明白这个意思  
        if(field.confirmTo){                    //confirmTo是我们自定义的配置参数,一般用来保存另外的组件的id值  
            var pwd=Ext.get(field.confirmTo);   //取得confirmTo的那个id的值  
            return (val==pwd.getVal());  
        }  
        return tr;  
    }  
});  
//配置items参数  
items:[  
    {  
        fieldLabel  : "密码",  
        id          : "pass1",  
    },{  
        fieldLabel  : "确认密码",  
        id          : "pass2",  
        vtype       : "password",//自定义的验证类型  
        vtypeText   : "两次密码不一致!",  
        confirmTo   : "pass1",//要比较的另外一个的组件的id  
    }  
]  
4.使用正则表达式验证  
new Ext.form.TextField({  
    fieldLabel  : "姓名",  
    name        : "author_nam",  
    regex       : /[\一-\龥]/,    //正则表达式在/…../之间. [\一-\龥] : 只能输入中文.  
    regexText   : "只能输入中文!",  
    allowBlank  : false                 //此验证依然有效.不许为空. 
 
#####################  
Extjs 常用 vtype 列表  
Ext.form.VTypes["hostnameVal1"]     = /^[a-zA-Z][-.a-zA-Z0-9]{0,254}$/;  
Ext.form.VTypes["hostnameVal2"]     = /^[a-zA-Z]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9]){0,1}([.][a-zA-Z]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9]){0,1}){0,}$/;  
Ext.form.VTypes["ipVal"]            = /^([1-9][0-9]{0,1}|1[013-9][0-9]|12[0-689]|2[01][0-9]|22[0-3])([.]([1-9]{0,1}[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){2}[.]([1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-4])$/;  
Ext.form.VTypes["netmaskVal"]       = /^(128|192|224|24[08]|25[245].0.0.0)|(255.(0|128|192|224|24[08]|25[245]).0.0)|(255.255.(0|128|192|224|24[08]|25[245]).0)|(255.255.255.(0|128|192|224|24[08]|252))$/;  
Ext.form.VTypes["portVal"]          = /^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;  
Ext.form.VTypes["multicastVal"]     = /^((22[5-9]|23[0-9])([.](0|[1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3})|(224[.]([1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])([.](0|[1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])){2})|(224[.]0[.]([1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])([.](0|[1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])))$/;  
Ext.form.VTypes["usernameVal"]      = /^[a-zA-Z][-_.a-zA-Z0-9]{0,30}$/;  
Ext.form.VTypes["passwordVal1"]     = /^.{6,31}$/;  
Ext.form.VTypes["passwordVal2"]     = /[^a-zA-Z].*[^a-zA-Z]/;  
Ext.form.VTypes["hostname"]         = function(v){  
    if(!Ext.form.VTypes["hostnameVal1"].test(v)){  
        Ext.form.VTypes["hostnameText"]="Must begin with a letter and not exceed 255 characters" 
        return false;  
    }  
    Ext.form.VTypes["hostnameText"]="L[.L][.L][.L][...] where L begins with a letter, ends with a letter or number, and does not exceed 63 characters";  
    return Ext.form.VTypes["hostnameVal2"].test(v);  
}  
Ext.form.VTypes["hostnameText"]     = "Invalid Hostname" 
Ext.form.VTypes["hostnameMask"]     = /[-.a-zA-Z0-9]/;  
Ext.form.VTypes["ip"]               = function(v){  
    return Ext.form.VTypes["ipVal"].test(v);  
}  
Ext.form.VTypes["ipText"]           = "1.0.0.1 - 223.255.255.254 excl ing 127.x.x.x" 
Ext.form.VTypes["ipMask"]           = /[.0-9]/;  
Ext.form.VTypes["netmask"]          = function(v){  
    return Ext.form.VTypes["netmaskVal"].test(v);  
}  
Ext.form.VTypes["netmaskText"]      = "128.0.0.0 - 255.255.255.252" 
Ext.form.VTypes["netmaskMask"]      = /[.0-9]/;  
Ext.form.VTypes["port"]             = function(v){  
    return Ext.form.VTypes["portVal"].test(v);  
}  
Ext.form.VTypes["portText"]         = "0 - 65535" 
Ext.form.VTypes["portMask"]         = /[0-9]/;  
Ext.form.VTypes["multicast"]        = function(v){  
    return Ext.form.VTypes["multicastVal"].test(v);  
}  
Ext.form.VTypes["multicastText"]    = "224.0.1.0 - 239.255.255.255" 
Ext.form.VTypes["multicastMask"]    = /[.0-9]/;  
Ext.form.VTypes["username"]         = function(v){  
    return Ext.form.VTypes["usernameVal"].test(v);  
}  
Ext.form.VTypes["usernameText"]     = "Username must begin with a letter and cannot exceed 255 characters" 
Ext.form.VTypes["usernameMask"]     = /[-_.a-zA-Z0-9]/;  
Ext.form.VTypes["password"]=function(v){  
    if(!Ext.form.VTypes["passwordVal1"].test(v)){  
        Ext.form.VTypes["passwordText"]="Password length must be 6 to 31 characters long";  
        return false;  
    }  
    Ext.form.VTypes["passwordText"]="Password must incl e atleast 2 numbers or symbols";  
    return Ext.form.VTypes["passwordVal2"].test(v);  
}  
Ext.form.VTypes["passwordText"]     = "Invalid Password" 
Ext.form.VTypes["passwordMask"]     = /./;

Posted by sqlwang in ext js, javascript - Comments (0)
22 六月

什么是LDAP?LDAP目录的优势(转)

什么是LDAP?
LDAP的英文全称是Lightweight Directory Access Protocol,一般都简称为LDAP。它是基于X.500标准的,
但是简单多了并且可以根据需要定制。与X.500不同,LDAP支持TCP/IP,这对访问Internet是必须的。LDAP
的核心规范在RFC中都有定义,所有与LDAP相关的RFC都可以在LDAPman RFC网页中找到。现在LDAP技术不仅
发展得很快而且也是激动人心的。在企业范围内实现LDAP可以让运行在几乎所有计算机平台上的所有的应
用程序从LDAP目录中获取信息。LDAP目录中可以存储各种类型的数据:电子邮件地址、邮件路由信息、人力
资源数据、公用密匙、联系人列表,等等。通过把LDAP目录作为系统集成中的一个重要环节,可以简化员工
在企业内部查询信息的步骤,甚至连主要的数据源都可以放在任何地方。

 

LDAP目录的优势

如果需要开发一种提供公共信息查询的系统一般的设计方法可能是采用基于WEB的数据库设计方式,即前端
使用浏览器而后端使用WEB服务器加上关系数据库。后端在Windows的典型实现可能是Windows NT + IIS + Acess
数据库或者是SQL服务器,IIS和数据库之间通过ASP技术使用ODBC进行连接,达到通过填写表单查询数据的功能;

后端在Linux系统的典型实现可能是Linux+ Apache + postgresql,Apache和数据库之间通过PHP3提供的函数进
行连接。使用上述方法的缺点是后端关系数据库的引入导致系统整体的性能降低和系统的管理比较繁琐,因为需
要不断的进行数据类型的验证和事务的完整性的确认;并且前端用户对数据的控制不够灵活,用户权限的设置一
般只能是设置在表一级而不是设置在记录一级。

目录服务的推出主要是解决上述数据库中存在的问题。目录与关系数据库相似,是指具有描述性的基于属性的记
录集合,但它的数据类型主要是字符型,为了检索的需要添加了BIN(二进制数据)、CIS(忽略大小写)、CES
(大小写敏感)、TEL(电话型)等语法(Syntax),而不是关系数据库提供的整数、浮点数、日期、货币等类型,
同样也不提供象关系数据库中普遍包含的大量的函数,它主要面向数据的查询服务(查询和修改操作比一般是大于
10:1),不提供事务的回滚(rollback)机制,它的数据修改使用简单的锁定机制实现All-or-Nothing,它的目标
是快速响应和大容量查询并且提供多目录服务器的信息复制功能。

现在该说说LDAP目录到底有些什么优势了。现在LDAP的流行是很多因数共同作用的结果。可能LDAP最大的优势是:
可以在任何计算机平台上,用很容易获得的而且数目不断增加的LDAP的客户端程序访问LDAP目录。而且也很容易
定制应用程序为它加上LDAP的支持。

LDAP协议是跨平台的和标准的协议,因此应用程序就不用为LDAP目录放在什么样的服务器上操心了。实际上,LDAP
得到了业界的广泛认可,因为它是Internet的标准。产商都很愿意在产品中加入对LDAP的支持,因为他们根本不用
考虑另一端(客户端或服务端)是怎么样的。LDAP服务器可以是任何一个开发源代码或商用的LDAP目录服务器(或
者还可能是具有LDAP界面的关系型数据库),因为可以用同样的协议、客户端连接软件包和查询命令与LDAP服务器
进行交互。与LDAP不同的是,如果软件产商想在软件产品中集成对DBMS的支持,那么通常都要对每一个数据库服务
器单独定制。不象很多商用的关系型数据库,你不必为LDAP的每一个客户端连接或许可协议付费 大多数的LDAP服务
器安装起来很简单,也容易维护和优化。

LDAP服务器可以用“推”或“拉”的方法复制部分或全部数据,例如:可以把数据“推”到远程的办公室,以增加
数据的安全性。复制技术是内置在LDAP服务器中的而且很容易配置。如果要在DBMS中使用相同的复制功能,数据库
产商就会要你支付额外的费用,而且也很难管理。

LDAP允许你根据需要使用ACI(一般都称为ACL或者访问控制列表)控制对数据读和写的权限。例如,设备管理员可
以有权改变员工的工作地点和办公室号码,但是不允许改变记录中其它的域。ACI可以根据谁访问数据、访问什么数
据、数据存在什么地方以及其它对数据进行访问控制。因为这些都是由LDAP目录服务器完成的,所以不用担心在客
户端的应用程序上是否要进行安全检查。

LDAP(Lightweight Directory Acess Protocol)是目录服务在TCP/IP上的实现(RFC 1777 V2版和RFC 2251

V3版)。它是对X500的目录协议的移植,但是简化了实现方法,所以称为轻量级的目录服务。在LDAP中目录是按照
树型结构组织,目录由条目(Entry)组成,条目相当于关系数据库中表的记录;条目是具有区别名DN(Distinguished

Name)的属性(Attribute)集合,DN相当于关系数据库表中的关键字(Primary

Key);属性由类型(Type)和多个值(Values)组成,相当于关系数据库中的域(Field)由域名和数据类型组成,
只是为了方便检索的需要,LDAP中的Type可以有多个Value,而不是关系数据库中为降低数据的冗余性要求实现的各
个域必须是不相关的。LDAP中条目的组织一般按照地理位置和组织关系进行组织,非常的直观。LDAP把数据存放在
文件中,为提高效率可以使用基于索引的文件数据库,而不是关系数据库。LDAP协议集还规定了DN的命名方法、存
取控制方法、搜索格式、复制方法、URL格式、开发接口等

LDAP对于这样存储这样的信息最为有用,也就是数据需要从不同的地点读取,但是不需要经常更新。

例如,这些信息存储在LDAP目录中是十分有效的:

l 公司员工的电话号码簿和组织结构图

l 客户的联系信息

l 计算机管理需要的信息,包括NIS映射、email假名,等等

l 软件包的配置信息

l 公用证书和安全密匙

什么时候该用LDAP存储数据

大多数的LDAP服务器都为读密集型的操作进行专门的优化。因此,当从LDAP服务器中读取数据的时候会比从专门为
OLTP优化的关系型数据库中读取数据快一个数量级。也是因为专门为读的性能进行优化,大多数的LDAP目录服务器
并不适合存储需要需要经常改变的数据。例如,用LDAP服务器来存储电话号码是一个很好的选择,但是它不能作为
电子商务站点的数据库服务器。

如果下面每一个问题的答案都是“是”,那么把数据存在LDAP中就是一个好主意。

l 需要在任何平台上都能读取数据吗?

l 每一个单独的记录项是不是每一天都只有很少的改变?

l 可以把数据存在平面数据库(flat database)而不是关系型数据库中吗?换句话来说,也就是不管什么范式不
范式的,把所有东西都存在一个记录中(差不多只要满足第一范式)。

最后一个问题可能会唬住一些人,其实用平面数据库去存储一些关系型的数据也是很一般的。例如,一条公司员工
的记录就可以包含经理的登录名。用LDAP来存储这类信息是很方便的。一个简单的判断方法:如果可以把保数据存
在一张张的卡片里,就可以很容易地把它存在LDAP目录里。

安全和访问控制

LDAP提供很复杂的不同层次的访问控制或者ACI。因这些访问可以在服务器端控制,这比用客户端的软件保证数据的
安全可安全多了。

用LDAP的ACI,可以完成:

l 给予用户改变他们自己的电话号码和家庭地址的权限,但是限制他们对其它数据(如,职务名称,经理的登录名,
等等)只有“只读”权限。

l 给予“HR-admins"组中的所有人权限以改变下面这些用户的信息:经理、工作名称、员工号、部门名称和部门号。
但是对其它域没有写权限。

l 禁止任何人查询LDAP服务器上的用户口令,但是可以允许用户改变他或她自己的口令。

l 给予经理访问他们上级的家庭电话的只读权限,但是禁止其他人有这个权限。

l 给予“host-admins"组中的任何人创建、删除和编辑所有保存在LDAP服务器中的与计算机主机有关的信息

l 通过Web,允许“foobar-sales"组中的成员有选择地给予或禁止他们自己读取一部分客户联系数据的读权限。这
将允许他们把客户联系信息下载到本地的笔记本电脑或个人数字助理(PDA)上。(如果销售人员的软件都支持LDAP,
这将非常有用)

l 通过Web,允许组的所有者删除或添加他们拥有的组的成员。例如:可以允许销售经理给予或禁止销售人员改变Web
页的权限。也可以允许邮件假名(mail aliase)的所有者不经过IT技术人员就直接从邮件假名中删除或添加用户。
“公用”的邮件列表应该允许用户从邮件假名中添加或删除自己(但是只能是自己)。也可以对IP地址或主机名加以
限制。例如,某些域只允许用户IP地址以192.168.200.*开头的有读的权限,或者用户反向查找DNS得到的主机名必须
为*.foobar.com。

LDAP目录树的结构

LDAP目录以树状的层次结构来存储数据。如果你对自顶向下的DNS树或UNIX文件的目录树比较熟悉,也就很容易掌握
LDAP目录树这个概念了。就象DNS的主机名那样,LDAP目录记录的标识名(Distinguished Name,简称DN)是用来读取
单个记录,以及回溯到树的顶部。后面会做详细地介绍。

为什么要用层次结构来组织数据呢?原因是多方面的。下面是可能遇到的一些情况:

l 如果你想把所有的美国客户的联系信息都“推”到位于到西雅图办公室(负责营销)的LDAP服务器上,但是你不想
把公司的资产管理信息“推”到那里。

l 你可能想根据目录树的结构给予不同的员工组不同的权限。在下面的例子里,资产管理组对“asset-mgmt"部分有完
全的访问权限,但是不能访问其它地方。

l 把LDAP存储和复制功能结合起来,可以定制目录树的结构以降低对WAN带宽的要求。位于西雅图的营销办公室需要每
分钟更新的美国销售状况的信息,但是欧洲的销售情况就只要每小时更新一次就行了。

刨根问底:基准DN

LDAP目录树的最顶部就是根,也就是所谓的“基准DN"。基准DN通常使用下面列出的三种格式之一。假定我在名为FooBar
的电子商务公司工作,这家公司在Internet上的名字是foobar.com。

o="FooBar, Inc.", c=US

(以X.500格式表示的基准DN)

在这个例子中,o=FooBar, Inc. 表示组织名,在这里就是公司名的同义词。c=US 表示公司的总部在美国。以前,一般
都用这种方式来表示基准DN。但是事物总是在不断变化的,现在所有的公司都已经(或计划)上Internet上。随着
Internet的全球化,在基准DN中使用国家代码很容易让人产生混淆。现在,X.500格式发展成下面列出的两种格式。

o=foobar.com

(用公司的Internet地址表示的基准DN)

这种格式很直观,用公司的域名作为基准DN。这也是现在最常用的格式。

dc=foobar, dc=com

(用DNS域名的不同部分组成的基准DN)

就象上面那一种格式,这种格式也是以DNS域名为基础的,但是上面那种格式不改变域名(也就更易读),而这种格式
把域名:foobar.com分成两部分 dc=foobar, dc=com。在理论上,这种格式可能会更灵活一点,但是对于最终用户来说
也更难记忆一点。考虑一下foobar.com这个例子。当foobar.com和gizmo.com合并之后,可以简单的把“dc=com"当作基
准DN。把新的记录放到已经存在的dc=gizmo, dc=com目录下,这样就简化了很多工作(当然,如果foobar.com和wocket.edu
合并,这个方法就不能用了)。如果LDAP服务器是新安装的,我建议你使用这种格式。再请注意一下,如果你打算使用活动
目录(Actrive Directory),Microsoft已经限制你必须使用这种格式。

更上一层楼:在目录树中怎么组织数据

在UNIX文件系统中,最顶层是根目录(root)。在根目录的下面有很多的文件和目录。象上面介绍的那样,LDAP目录也是
用同样的方法组织起来的。

在根目录下,要把数据从逻辑上区分开。因为历史上(X.500)的原因,大多数LDAP目录用OU从逻辑上把数据分开来。OU
表示“Organization Unit",在X.500协议中是用来表示公司内部的机构:销售部、财务部,等等。现在LDAP还保留ou=这
样的命名规则,但是扩展了分类的范围,可以分类为:ou=people, ou=groups, ou=devices,等等。更低一级的OU有时用
来做更细的归类。例如:LDAP目录树(不包括单独的记录)可能会是这样的:

dc=foobar, dc=com

ou=customers

ou=asia

ou=europe

ou=usa

ou=employees

ou=rooms

ou=groups

ou=assets-mgmt

ou=nisgroups

ou=recipes

单独的LDAP记录

DN是LDAP记录项的名字

在LDAP目录中的所有记录项都有一个唯一的“Distinguished Name",也就是DN。每一个LDAP记录项的DN是由两个部分
组成的:相对DN(RDN)和记录在LDAP目录中的位置。

RDN是DN中与目录树的结构无关的部分。在LDAP目录中存储的记录项都要有一个名字,这个名字通常存在cn(Common Name)
这个属性里。因为几乎所有的东西都有一个名字,在LDAP中存储的对象都用它们的cn值作为RDN的基础。如果我把最喜欢的
吃燕麦粥食谱存为一个记录,我就会用cn=Oatmeal Deluxe作为记录项的RDN。

l 我的LDAP目录的基准DN是dc=foobar,dc=com

l 我把自己的食谱作为LDAP的记录项存在ou=recipes

l 我的LDAP记录项的RDN设为cn=Oatmeal Deluxe

上面这些构成了燕麦粥食谱的LDAP记录的完整DN。记住,DN的读法和DNS主机名类似。下面就是完整的DN:

cn=Oatmeal Deluxe,ou=recipes,dc=foobar,dc=com

举一个实际的例子来说明DN

现在为公司的员工设置一个DN。可以用基于cn或uid(User ID),作为典型的用户帐号。例如,FooBar的员工Fran Smith
(登录名:fsmith)的DN可以为下面两种格式:

uid=fsmith,ou=employees,dc=foobar,dc=com

(基于登录名)

LDAP(以及X.500)用uid表示“User ID",不要把它和UNIX的uid号混淆了。大多数公司都会给每一个员工唯一的登录名,
因此用这个办法可以很好地保存员工的信息。你不用担心以后还会有一个叫Fran Smith的加入公司,如果Fran改变了她的
名字(结婚?离婚?或宗教原因?),也用不着改变LDAP记录项的DN。

cn=Fran Smith,ou=employees,dc=foobar,dc=com

(基于姓名)

可以看到这种格式使用了Common Name(CN)。可以把Common Name当成一个人的全名。这种格式有一个很明显的缺点就是:
如果名字改变了,LDAP的记录就要从一个DN转移到另一个DN。但是,我们应该尽可能地避免改变一个记录项的DN。

定制目录的对象类型

你可以用LDAP存储各种类型的数据对象,只要这些对象可以用属性来表示,下面这些是可以在LDAP中存储的一些信息:

l 员工信息:员工的姓名、登录名、口令、员工号、他的经理的登录名,邮件服务器,等等。

l 物品跟踪信息:计算机名、IP地址、标签、型号、所在位置,等等。

l 客户联系列表:客户的公司名、主要联系人的电话、传真和电子邮件,等等。

l 会议厅信息:会议厅的名字、位置、可以坐多少人、电话号码、是否有投影机。

l 食谱信息:菜的名字、配料、烹调方法以及准备方法。

因为LDAP目录可以定制成存储任何文本或二进制数据,到底存什么要由你自己决定。LDAP目录用对象类型
(object classes)的概念来定义运行哪一类的对象使用什么属性。在几乎所有的LDAP服务器中,你都要根据
自己的需要扩展基本的LDAP目录
的功能,创建新的对象类型或者扩展现存的对象类型。

LDAP目录以一系列“属性对”的形式来存储记录项,每一个记录项包括属性类型和属性值(这与关系型数据库
用行和列来存取数据有根本的不同)。下面是我存在LDAP目录中的一部分食谱记录:

dn: cn=Oatmeal Deluxe, ou=recipes, dc=foobar, dc=com

cn: Instant Oatmeal Deluxe

recipeCuisine: breakfast

recipeIngredient: 1 packet instant oatmeal

recipeIngredient: 1 cup water

recipeIngredient: 1 pinch salt

recipeIngredient: 1 tsp brown sugar

recipeIngredient: 1/4 apple, any type

请注意上面每一种配料都作为属性recipeIngredient值。LDAP目录被设计成象上面那样为一个属性保存多个值的,
而不是在每一个属性的后面用逗号把一系列值分开。

因为用这样的方式存储数据,所以数据库就有很大的灵活性,不必为加入一些新的数据就重新创建表和索引。更
重要的是,LDAP目录不必花费内存或硬盘空间处理“空”域,也就是说,实际上不使用可选择的域也不会花费你
任何资源。

作为例子的一个单独的数据项

让我们看看下面这个例子。我们用Foobar, Inc.的员工Fran Smith的LDAP记录。这个记录项的格式是LDIF,用来
导入和导出LDAP目录的记录项。

dn: uid=fsmith, ou=employees, dc=foobar, dc=com

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

objectclass: foobarPerson

uid: fsmith

givenname: Fran

sn: Smith

cn: Fran Smith

cn: Frances Smith

telephonenumber: 510-555-1234

roomnumber: 122G

o: Foobar, Inc.

mailRoutingAddress: fsmith@foobar.com

mailhost: mail.foobar.com

userpassword: 3×1231v76T89N

uidnumber: 1234

gidnumber: 1200

homedirectory: /home/fsmith

loginshell: /usr/local/bin/bash

属性的值在保存的时候是保留大小写的,但是在默认情况下搜索的时候是不区分大小写的。某些特殊的属性
(例如,password)在搜索的时候需要区分大小写。

让我们一点一点地分析上面的记录项。

dn: uid=fsmith, ou=employees, dc=foobar, dc=com

这是Fran的LDAP记录项的完整DN,包括在目录树中的完整路径。LDAP(和X.500)使用uid(User ID),不要
把它和UNIX的uid号混淆了。

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

objectclass: foobarPerson

可以为任何一个对象根据需要分配多个对象类型。person对象类型要求cn(common name)和sn(surname)
这两个域不能为空。persion对象类型允许有其它的可选域,包括givenname、telephonenumber,等等。
organizational Person给person加入更多的可选域,inetOrgPerson又加入更多的可选域(包括电子邮件信息)。
最后,foobarPerson是为Foobar定制的对象类型,加入了很多定制的属性。

uid: fsmith

givenname: Fran

sn: Smith

cn: Fran Smith

cn: Frances Smith

telephonenumber: 510-555-1234

roomnumber: 122G

o: Foobar, Inc.

以前说过了,uid表示User ID。当看到uid的时候,就在脑袋里想一想“login"。

请注意CN有多个值。就象上面介绍的,LDAP允许某些属性有多个值。为什么允许有多个值呢?假定你在用
公司的LDAP服务器查找Fran的电话号码。你可能只知道她的名字叫Fran,但是对人力资源处的人来说她的
正式名字叫做Frances。因为保存了她的两个名字,所以用任何一个名字检索都可以找到Fran的电话号码、
电子邮件和办公房间号,等等。

mailRoutingAddress: fsmith@foobar.com

mailhost: mail.foobar.com

就象现在大多数的公司都上网了,Foobar用Sendmail发送邮件和处理外部邮件路由信息。Foobar把所有用户
的邮件信息都存在LDAP中。最新版本的Sendmail支持这项功能。

Userpassword: 3×1231v76T89N

uidnumber: 1234

gidnumber: 1200

gecos: Frances Smith

homedirectory: /home/fsmith

loginshell: /usr/local/bin/bash

注意,Foobar的系统管理员把所有用户的口令映射信息也都存在LDAP中。FoobarPerson类型的对象具有这
种能力。再注意一下,用户口令是用UNIX的口令加密格式存储的。UNIX的uid在这里为uidnumber。提醒你一下,
关于如何在LDAP中保存NIS信息,有完整的一份RFC。在以后的文章中我会谈一谈NIS的集成。

LDAP复制

LDAP服务器可以使用基于“推”或者“拉”的技术,用简单或基于安全证书的安全验证,复制一部分或者所
有的数据。

例如,Foobar有一个“公用的”LDAP服务器,地址为ldap.foobar.com,端口为389。Netscape Communicator
的电子邮件查询功能、UNIX的“ph"命令要用到这个服务器,用户也可以在任何地方查询这个服务器上的员工
和客户联系信息。公司的主LDAP服务器运行在相同的计算机上,不过端口号是1389。

你可能即不想让员工查询资产管理或食谱的信息,又不想让信息技术人员看到整个公司的LDAP目录。为了解决
这个问题,Foobar有选择地把子目录树从主LDAP服务器复制到“公用”LDAP服务器上,不复制需要隐藏的信息。
为了保持数据始终是最新的,主目录服务器被设置成即时“推”同步。这些种方法主要是为了方便,而不是安全,
因为如果有权限的用户想查询所有的数据,可以用另一个LDAP端口。

假定Foobar通过从奥克兰到欧洲的低带宽数据的连接用LDAP管理客户联系信息。可以建立从ldap.foobar.com:1389
到munich-ldap.foobar.com:389的数据复制,象下面这样:

periodic pull: ou=asia,ou=customers,o=sendmail.com

periodic pull: ou=us,ou=customers,o=sendmail.com

immediate push: ou=europe,ou=customers,o=sendmail.com

“拉”连接每15分钟同步一次,在上面假定的情况下足够了。“推”连接保证任何欧洲的联系信息发生了变化就
立即被“推”到Munich。
用上面的复制模式,用户为了访问数据需要连接到哪一台服务器呢?在Munich的用户可以简单地连接到本地服务
器。如果他们改变了数据,本地的LDAP服务器就会把这些变化传到主LDAP服务器。然后,主LDAP服务器把这些变化
“推”回本地的“公用”LDAP服务器保持数据的同步。这对本地的用户有很大的好处,因为所有的查询(大多数是读)都在本地的服务器上进行,速度非常快。当需要改变信息的时候,最终用户不需要重新配置客户端的软件,因为LDAP目录服务器为他们完成了所有的数据交换工作。

Posted by sqlwang in web - Comments (0)
16 六月

php配置文件php.ini的中文注释版

; 指明的路径;编译时指定的路径。
; 在windows下,编译时的路径是Windows安装目录。
; 在命令行模式下,php.ini的查找路径可以用 -c 参数替代。

; 该文件的语法非常简单。空白字符和用分号´;´开始的行被简单地忽略(就象你可能
; 猜到的一样)。 章节标题(例如 : [Foo])也被简单地忽略,即使将来它们可能
; 有某种的意义。
;
; 指示被指定使用如下语法:
; 指示标识符 = 值
; directive = value
; 指示标识符 是 *大小写敏感的* - foo=bar 不同于 FOO = bar。
;
; 值可以是一个字符串,一个数字,一个 PHP 常量 (如: E_ALL or M_PI), INI 常量中的
; 一个 (On, Off, True, False, Yes, No and None) ,或是一个表达式
; (如: E_ALL & ~E_NOTICE), 或是用引号括起来的字符串("foo").
;
; INI 文件的表达式被限制于位运算符和括号。
; | bitwise OR
; & bitwise AND
; ~ bitwise NOT
; ! boolean NOT
;
; 布尔标志可用 1, On, True or Yes 这些值置于开的状态。
; 它们可用 0, Off, False or No 这些值置于关的状态。
;
; 一个空字符串可以用在等号后不写任何东西表示,或者用 None 关键字:
;
; foo = ; 将foo置为空字符串
; foo = none ; 将foo置为空字符串
; foo = "none" ; 将foo置为字符串´none´
;
; 如果你值设置中使用常量,而这些常量属于动态调入的扩展库(不是 PHP 的扩展,就是
; Zend 的扩展),你仅可以调入这些扩展的行*之后*使用这些常量。
;
; 所有在 php.ini-dist 文件里设定的值与内建的默认值相同(这是说,如果 php.ini
; 没被使用或者你删掉了这些行,默认值与之相同)。

;;;;;;;;;;;;;;;;;;;;
; 语言选项 ;
;;;;;;;;;;;;;;;;;;;;

engine = On
; 使 PHP scripting language engine(PHP 脚本语言引擎)在 Apache下有效。
short_open_tag = On
; 允许 <? 标识(这种简单表示)。否则 仅有 <?php and <script> tags 将被识别。
asp_tags = Off
; 允许ASP-style <% %> tags
precision = 14
; 浮点类型数显示时的有效位数

y2k_compliance = Off
; 是否打开 2000年适应 (可能在非Y2K适应的浏览器中导致问题)

output_buffering = Off
; 输出缓存允许你甚至在输出正文内容之后发送 header(标头,包括cookies)行
; 其代价是输出层减慢一点点速度。你可以使用输出缓存在运行时打开输出缓存,
; 或者在这里将指示设为 On 而使得所有文件的输出缓存打开。

implicit_flush = Off
; 强制flush(刷新)让PHP 告诉输出层在每个输出块之后自动刷新自身数据。
; 这等效于在每个 print() 或 echo() 调用和每个 HTML 块后调用flush()函数。
; 打开这项设置会导致严重的运行时冲突,建议仅在debug过程中打开。

allow_call_time_pass_reference = On
; 是否让强迫函数调用时按引用传递参数。这一方法遭到抗议,
; 并可能在将来版本的PHP/Zend里不再支持。
; 受到鼓励的指定哪些参数按引用传递的方法是在函数声明里。
; 你被鼓励尝试关闭这一选项并确认你的脚本仍能正常工作,以保证在将来版本的语言里
; 它们仍能工作。(你将在每次使用该特点时得到一个警告,而参数将按值而不是按引用
; 传递)。

; Safe Mode 安全模式
safe_mode = Off
safe_mode_exec_dir =
safe_mode_allowed_env_vars = PHP_
; ?Setting certain environment variables
; ?may be a potential security breach.
; 该指示包含用逗号分隔的前缀列表。安全模式中,用户仅可以替换
; 以在此列出的前缀开头的环境变量的值。
; 默认地,用户将仅能 设定以PHP_开头的环境变量,(如: PHP_FOO=BAR)。
; 注意: 如果这一指示为空,PHP 将让用户更改任意环境变量!

safe_mode_protected_env_vars = LD_LIBRARY_PATH
; 这条指示包含一个用逗号分隔的环境变量列表,那是最终用户将不能用putenv () 更改的。
; 这些变量甚至在safe_mode_allowed_env_vars 设置为允许的情况下得到保护。

disable_functions =
; 这条指示让你可以为了安全的原因让特定函数失效。
; 它接受一个用逗号分隔的函数名列表。
; 这条指示 *不受* 安全模式是否打开的影响。

; 语法高亮模式的色彩。
; 只要能被<font color=???>接受的东西就能工作。

highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000

; Misc 杂项
expose_php = Off
; 决定 PHP 是否标示它装在服务器上的事实(例如:加在它 —PHP—给Web服务
; 发送的信号上)。
; (我个人的意见,在出现什么power-by的header的时候,把这关掉。)
; 它不会有安全上的威胁, 但它使检查你的服务器上是否安装了PHP成为了可能。

;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

max_execution_time = 30 ; 每个脚本的最大执行时间, 按秒计
memory_limit = 8388608 ; 一个脚本最大可使用的内存总量 (这里是8MB)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
; 出错控制和登记 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 错误报告是按位的。或者将数字加起来得到想要的错误报告等级。
; E_ALL - 所有的错误和警告
; E_ERROR - 致命性运行时错
; E_WARNING - 运行时警告(非致命性错)
; E_PARSE - 编译时解析错误
; E_NOTICE - 运行时提醒(这些经常是是你的代码的bug引起的,
;也可能是有意的行为造成的。(如:基于未初始化的变量自动初始化为一个
;空字符串的事实而使用一个未初始化的变量)

; E_CORE_ERROR - 发生于PHP启动时初始化过程中的致命错误
; E_CORE_WARNING - 发生于PHP启动时初始化过程中的警告(非致命性错)
; E_COMPILE_ERROR - 编译时致命性错
; E_COMPILE_WARNING - 编译时警告(非致命性错)
; E_USER_ERROR - 用户产生的出错消息
; E_USER_WARNING - 用户产生的警告消息
; E_USER_NOTICE - 用户产生的提醒消息
; 例子:
; error_reporting = E_ALL & ~E_NOTICE ; 显示所有的错误,除了提醒
; error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; 仅显示错误
error_reporting = E_ALL & ~E_NOTICE ; 显示所有的错误,除了提醒
display_errors = On ; 显示出错误信息(作为输出的一部分)
; 在最终发布的web站点上,强烈建议你关掉这个特性,并使用
; 错误日志代替(参看下面)。
; 在最终发布的web站点继续让 display_errors 有效可能
; 暴露一些有关安全的信息,例如你的web服务上的文件路径、
; 你的数据库规划或别的信息。

log_errors = Off ; 在日志文件里记录错误(服务器指定的日志,stderr标准错误输出,或error_log(下面的))
; 正如上面说明的那样,强烈建议你在最终发布的web站点以日志记录错误
; 取代直接错误输出。

track_errors = Off ; 保存最近一个 错误/警告 消息于变量 $php_errormsg (boolean)
;error_prepend_string = "<font color=ff0000>" ; 于错误信息前输出的字符串
;error_append_string = "</font>" ; 于错误信息后输出的字符串
;error_log = filename ; 记录错误日志于指定文件
;error_log = syslog ; 记录错误日志于系统日志 syslog (NT 下的事件日志, Windows 95下无效)
warn_plus_overloading = Off ; 当将‘ ’用于字符串时警告

;;;;;;;;;;;;;;;;;
; Data Handling ;
;;;;;;;;;;;;;;;;;
variables_order = "EGPCS" ; 这条指示描述了PHP 记录
; GET, POST, Cookie, Environment and Built-in 这些变量的顺序。
; (以 G, P, C, E & S 代表,通常以 EGPCS 或 GPC 的方式引用)。
; 按从左到右记录,新值取代旧值。

register_globals = On ; 是否将这些 EGPCS 变量注册为全局变量。
; 若你不想让用户数据不在全局范围内混乱的话,你可能想关闭它。
; 这和 track_vars 连起来用更有意义 — 这样你可以通过
; $HTTP_*_VARS[] 数组访问所有的GPC变量。

register_argc_argv = On ; 这条指示告诉 PHP 是否声明 argv和argc 变量
; (注:这里argv为数组,argc为变量数)
; (其中包含用GET方法传来的数据)。
; 若你不想用这些变量,你应当关掉它以提高性能。

track_vars = On ; 使$HTTP_*_VARS[]数组有效,这里*在使用时用
; ENV, POST, GET, COOKIE or SERVER替换

gpc_order = "GPC" ; 这条指示被人反对。用 variables_order 代替。

; Magic quotes
magic_quotes_gpc = On ; 在输入的GET/POST/Cookie数据里使用魔术引用
; (原文就这样,呵呵,所谓magic quotes 应该是指用转义符加在引用性的控制字符上,如 ´….)
magic_quotes_runtime= Off ; 对运行时产生的数据使用魔术引用,
; 例如:用SQL查询得到的数据,用exec()函数得到的数据,等等
magic_quotes_sybase = Off ; 采用 Sybase形式的魔术引用(用 ´´ 脱出 ´ 而不用 ´)

; 自动在 PHP 文档之前和之后添加文件
auto_prepend_file =
auto_append_file =

; 象4.04b4一样,PHP 默认地总是在 “Content-type:” 头标输出一个字符的编码方式。
; 让输出字符集失效,只要设置为空。
; PHP 的内建默认值是 text/html
default_mimetype = "text/html"
;default_charset = "iso-8859-1"

;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;
include_path = ; include 路径设置,UNIX: "/path1:/path2" Windows: "path1;path2"
doc_root = ; php 页面的根路径,仅在非空时有效
user_dir = ; 告知 php 在使用 /~username 打开脚本时到哪个目录下去找,仅在非空时有效
;upload_tmp_dir = ; 存放用HTTP协议上载的文件的临时目录(在没指定时使用系统默认的)
upload_max_filesize = 2097152 ; 文件上载默认地限制为2 Meg
extension_dir = c:php ; 存放可加载的扩充库(模块)的目录
enable_dl = On ; 是否使dl()有效。
; 在多线程的服务器上 dl()函数*不能*很好地工作,
; 例如IIS or Zeus,并在其上默认为禁止

;;;;;;;;;;;;;;;;;;;;;;
; 动态扩展 ;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
; 若你希望一个扩展库自动加载,用下面的语法:
; extension=modulename.extension
; 例如,在windows上,
; extension=msql.dll
; or 在UNIX下,
; extension=msql.so
; 注意,这只应当是模块的名字,不需要目录信息放在里面。
; 用上面的 extension_dir 指示指定扩展库的位置。

;Windows 扩展
;extension=php_nsmail.dll
extension=php_calendar.dll
;extension=php_dbase.dll
;extension=php_filepro.dll
extension=php_gd.dll
;extension=php_dbm.dll
;extension=php_mssql.dll
;extension=php_zlib.dll
;extension=php_filepro.dll
;extension=php_imap4r2.dll
;extension=php_ldap.dll
;extension=php_crypt.dll
;extension=php_msql2.dll
;extension=php_odbc.dll
; 注意, MySQL的支持现在是内建的,因此,不需要用它的dll

;;;;;;;;;;;;;;;;;;;
; 模块设定 ;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;

[Syslog]
define_syslog_variables = Off ; 是否定义各种的系统日志变量
; 如:$LOG_PID, $LOG_CRON, 等等。
; 关掉它是个提高效率的好主意。
; 运行时,你可以调用函数define_syslog_variables(),来定义这些变量

[mail function]
SMTP = localhost ;仅用于win32系统
sendmail_from = me@localhost.com ;仅用于win32系统
;sendmail_path = ;仅用于unix, 也可支持参数(默认的是´sendmail -t -i´)

[Debugger]
debugger.host = localhost
debugger.port = 7869
debugger.enabled = False

[Logging]
; 这些配置指示用于示例的日志记录机制。
; 看 examples/README.logging 以得到更多的解释
;logging.method = db
;logging.directory = /path/to/log/directory

[SQL]
sql.safe_mode = Off

[ODBC]
;uodbc.default_db = Not yet implemented
;uodbc.default_user = Not yet implemented
;uodbc.default_pw = Not yet implemented
uodbc.allow_persistent = On ; 允许或禁止 持久连接
uodbc.check_persistent = On ; 在重用前检查连接是否还可用
uodbc.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
uodbc.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
uodbc.defaultlrl = 4096 ; 控制 LONG 类型的字段。返回变量的字节数,0 代表通过(?)0 means passthru
uodbc.defaultbinmode = 1 ; 控制 二进制数据。0 代表?????Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char
; 见有关 odbc_binmode 和 odbc_longreadlen 的文档以得到 uodbc.defaultlrl 和 uodbc.defaultbinmode 的解释。

[MySQL]
mysql.allow_persistent = On ; 允许或禁止 持久连接
mysql.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
mysql.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
mysql.default_port = ; mysql_connect() 使用的默认端口,如不设置,mysql_connect()
; 将使用变量 $MYSQL_TCP_PORT,或在/etc/services 下的mysql-tcp 条目(unix),
; 或在编译是定义的 MYSQL_PORT(按这样的顺序)
; Win32环境,将仅检查MYSQL_PORT。
mysql.default_socket = ; 用于本地 MySql 连接的默认的套接字名。为空,使用 MYSQL 内建值

mysql.default_host = ; mysql_connect() 默认使用的主机(安全模式下无效)
mysql.default_user = ; mysql_connect() 默认使用的用户名(安全模式下无效)
mysql.default_password = ; mysql_connect() 默认使用的密码(安全模式下无效)
; 注意,在这个文件下保存密码通常是一个*坏*主意
; *任何*可以使用PHP访问的用户可以运行
; ´echo cfg_get_var("mysql.default_password")´来显示那个密码!
; 而且当然地,任何有读该文件权力的用户也能看到那个密码。

[mSQL]
msql.allow_persistent = On ; 允许或禁止 持久连接
msql.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
msql.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制

[PostgresSQL]
pgsql.allow_persistent = On ; 允许或禁止 持久连接
pgsql.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
pgsql.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制

[Sybase]
sybase.allow_persistent = On ; 允许或禁止 持久连接
sybase.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
sybase.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
;sybase.interface_file = "/usr/sybase/interfaces"
sybase.min_error_severity = 10 ; 显示的错误的最低严重性
sybase.min_message_severity = 10 ; 显示的消息的最低重要性
sybase.compatability_mode = Off ; 与旧版的PHP 3.0 兼容的模式。若打开,这将导致 PHP 自动地
; 把根据结果的 Sybase 类型赋予它们,
; 而不是把它们全当成字符串。
; 这个兼容模式不会永远留着,
; 因此,将你的代码进行需要的修改,
; 并将该项关闭。

[Sybase-CT]
sybct.allow_persistent = On ; 允许或禁止 持久连接
sybct.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
sybct.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
sybct.min_server_severity = 10 ; minimum server message severity to display
sybct.min_client_severity = 10 ; minimum client message severity to display

[bcmath]
bcmath.scale = 0 ; 用于所有bcmath函数的10十进制数数字的个数number of decimal digits for all bcmath functions

[browscap]
;browscap = extra/browscap.ini
browscap = C:WINSYSTEMinetsrvrowscap.ini
[Informix]
ifx.default_host = ; ifx_connect() 默认使用的主机(安全模式下无效)
ifx.default_user = ; ifx_connect() 默认使用的用户名(安全模式下无效)
ifx.default_password = ; ifx_connect() 默认使用的密码(安全模式下无效)
ifx.allow_persistent = On ; 允许或禁止 持久连接
ifx.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
ifx.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
ifx.textasvarchar = 0 ; 若打开,select 状态符返回一个 ‘text blob’字段的内容,而不是它的id
ifx.byteasvarchar = 0 ; 若打开,select 状态符返回一个 ‘byte blob’字段的内容,而不是它的id
ifx.charasvarchar = 0 ; 追踪从固定长度的字符列里剥离的空格。
; 可能对 Informix SE 用户有效。
ifx.blobinfile = 0 ; 若打开,text和byte blobs 的内容被导出到一个文件
; 而不是保存到内存。
ifx.nullformat = 0 ; NULL(空)被作为空字段返回,除非,这里被设为1。
; 这种情况下(为1),NULL作为字串NULL返回。

[Session]
session.save_handler = files ; 用于保存/取回数据的控制方式
session.save_path = C:win emp ; 在 save_handler 设为文件时传给控制器的参数,
; 这是数据文件将保存的路径。
session.use_cookies = 1 ; 是否使用cookies
session.name = PHPSESSID
; 用在cookie里的session的名字
session.auto_start = 0 ; 在请求启动时初始化session
session.cookie_lifetime = 0 ; 为按秒记的cookie的保存时间,
; 或为0时,直到浏览器被重启
session.cookie_path = / ; cookie的有效路径
session.cookie_domain = ; cookie的有效域
session.serialize_handler = php ; 用于连接数据的控制器
; php是 PHP 的标准控制器。
session.gc_probability = 1 ; 按百分比的´garbage collection(碎片整理)´进程
; 在每次 session 初始化的时候开始的可能性。
session.gc_maxlifetime = 1440 ; 在这里数字所指的秒数后,保存的数据将被视为
; ´碎片(garbage)´并由gc 进程清理掉。
session.referer_check = ; 检查 HTTP引用以使额外包含于URLs中的ids无效
session.entropy_length = 0 ; 从文件中读取多少字节
session.entropy_file = ; 指定这里建立 session id
; session.entropy_length = 16
; session.entropy_file = /dev/urandom
session.cache_limiter = nocache ; 设为{nocache,private,public},以决定 HTTP 的
; 缓存问题
session.cache_expire = 180 ; 文档在 n 分钟后过时

[MSSQL]
;extension=php_mssql.dll
mssql.allow_persistent = On ; 允许或禁止 持久连接
mssql.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
mssql.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
mssql.min_error_severity = 10 ; 显示的错误的最低严重性
mssql.min_message_severity = 10 ; 显示的消息的最低重要性
mssql.compatability_mode = Off ; 与旧版的PHP 3.0 兼容的模式。

[Assertion]
; ?????
;assert.active = On ; ?assert(expr); active by default
;assert.warning = On ; issue a PHP warning for each failed assertion.
;assert.bail = Off ; don´t bail out by default.
;assert.callback = 0 ; user-function to be called if an assertion fails.
;assert.quiet_eval = 0 ; eval the expression with current error_reporting(). set to true if you want error_reporting(0) around the eval().

[Ingres II]
ii.allow_persistent = On ; 允许或禁止 持久连接
ii.max_persistent = -1 ; 持久连接的最大数。-1 代表无限制
ii.max_links = -1 ; 连接的最大数目(持久和非持久)。-1 代表无限制
ii.default_database = ; 默认 database (format : [node_id::]dbname[/srv_class]
ii.default_user = ; 默认 user
ii.default_password = ; 默认 password

[Verisign Payflow Pro]
pfpro.defaulthost = "test.signio.com" ; 默认的 Signio 服务器
pfpro.defaultport = 443 ; 连接的默认端口
pfpro.defaulttimeout = 30 ; 按秒计的默认超时时间

; pfpro.proxyaddress = ; 默认的代理的 IP 地址(如果需要)
; pfpro.proxyport = ; 默认的代理的端口
; pfpro.proxylogon = ; 默认的代理的登录(logon 用户名)
; pfpro.proxypassword = ; 默认的代理的密码

; Local Variables:
; tab-width: 4
; End:

Posted by sqlwang in PHP, web - Tags: - Comments (0)
13 六月

PHP XML 解析函数库

XML (eXtensible Markup Language) 是一种资料文件转换的标准。详情请参考 http://www.w3.org/XML。

  要使用本函数库,需先到 http://www.jclark.com/xml 取回 XML 的函数库,并且编译或安装。用 RedHat Linux 的用户可以到 http://www.guardian.no/~ssb/phpxml.html 取得 RPM 的格式档。之后要在编译 PHP 前加入 –with-xml 的配置选项。tommy@nashville.net 指出 (12-Jan-1999) 若有问题,尚需在 /usr/local/include 放入 xmltok.h 及 xmlparse.h 二个 C 语言的标头档,或是设好环境变量。

  目前的版本支持三种字符集:US-ASCII、ISO-8859-1 与 UTF-8。至于 UTF-16 字符集 PHP 尚未支持。

  XML 有许多错误代码,如下

  XML_ERROR_NONE
XML_ERROR_NO_MEMORY
XML_ERROR_SYNTAX
XML_ERROR_NO_ELEMENTS
XML_ERROR_INVALID_TOKEN
XML_ERROR_UNCLOSED_TOKEN
XML_ERROR_PARTIAL_CHAR
XML_ERROR_TAG_MISMATCH
XML_ERROR_DUPLICATE_ATTRIBUTE
XML_ERROR_JUNK_AFTER_DOC_ELEMENT
XML_ERROR_PARAM_ENTITY_REF
XML_ERROR_UNDEFINED_ENTITY
XML_ERROR_RECURSIVE_ENTITY_REF
XML_ERROR_ASYNC_ENTITY
XML_ERROR_BAD_CHAR_REF
XML_ERROR_BINARY_ENTITY_REF
XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
XML_ERROR_MISPLACED_XML_PI
XML_ERROR_UNKNOWN_ENCODING
XML_ERROR_INCORRECT_ENCODING
XML_ERROR_UNCLOSED_CDATA_SECTION
XML_ERROR_EXTERNAL_ENTITY_HANDLING

  和中文有关的信息可在中央研究院的 Chinese XML Now 网站看到。而和 XML 有关的术语则使用曾士熊先生所译的 SGML 名词英汉翻译表。

  xml_parser_create: 初始 XML 解析器。
xml_set_object: 使 XML 解析器用类。
xml_set_element_handler: 配置元素的标头。
xml_set_character_data_handler: 建立字符资料标头。
xml_set_processing_instruction_handler: 建立处理指令标头。
xml_set_default_handler: 建立默认标头。
xml_set_unparsed_entity_decl_handler: 配置未解析实体宣告的标头。
xml_set_notation_decl_handler: 配置记法宣告的标头。
xml_set_external_entity_ref_handler: 配置外部实体参引的标头。
xml_parse: 解析 XML 文件。
xml_get_error_code: 取得 XML 错误码。
xml_error_string: 取得 XML 错误字符串。
xml_get_current_line_number: 取得目前解析的行号。
xml_get_current_column_number: 获知目前解析的第几字段。
xml_get_current_byte_index: 取得目前解析为第几个位组。
xml_parser_free: 释放解析占用的内存。
xml_parser_set_option: 配置解析使用的选项。
xml_parser_get_option: 取得解析使用的选项。
utf8_decode: 将 UTF-8 码转成 ISO-8859-1 码。
utf8_encode: 将 ISO-8859-1 码转成 UTF-8 码。

  xml_parser_create 初始 XML 解析器。
语法: int xml_parser_create(string [encoding]);
返回值: 整数
函数种类: 资料处理
内容说明: 本函数用来初始化一个新的 XML 解析器。参数 encoding 可省略,为 XML 使用的字符集,默认值为 ISO-8859-1,其它尚有 US-ASCII、UTF-8 二种。成功则返回 parser 代码供其它函数使用,失败则返回 false 值。

  xml_set_object 使 XML 解析器用类。
语法: void xml_set_object(int parser, object &object);
返回值: 无
函数种类: 资料处理
内容说明: 本函数让解析器能使用类的方式,值得注意的是这个函数在 PHP 4.0 以上的版本才可使用。参数 parser 为 xml_parser_create() 所返回的解析代码。参数 &object 是类本身的指针。

  使用范例
<?php
class xml {
var $parser;
function xml() {
$this->parser = xml_parser_create();
xml_set_object($this->parser,&$this);
xml_set_element_handler($this->parser,"tag_open","tag_close");
xml_set_character_data_handler($this->parser,"cdata");
}

      function parse($data) {
xml_parse($this->parser,$data);
}

      function tag_open($parser,$tag,$attributes) {
var_dump($parser,$tag,$attributes);
}

      function cdata($parser,$cdata) {
var_dump($parser,$cdata);
}

      function tag_close($parser,$tag) {
var_dump($parser,$tag);
}

    } // end of class xml

    $xml_parser = new xml();
$xml_parser->parse("<A ID="hallo">PHP</A>");
?>

  
xml_set_element_handler 配置元素的标头。
语法: boolean xml_set_element_handler(int parser, string startElementHandler, string endElementHandler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置元素的标头供 xml_parse() 函数使用。参数 parser 为解析代码。参数 startElementHandler 及 endElementHandler 分别为元素开始与结束的标头,其中的 startElementHandler 必须包括解析代码、名称、与属性,而 endElementHandler 参数包括了解析代码及名称二个参数。若无错误则返回 true 值。

  使用范例,下列用来显示 XML 元素结构 (Element Structure)

<?php
$file = "data.xml";
$depth = array();

    function startElement($parser, $name, $attrs){
global $depth;
for ($i = 0; $i < $depth[$parser]; $i++) {
print " ";
}
print "$namen";
$depth[$parser]++;
}

    function endElement($parser, $name, $attrs){
global $depth;
$depth[$parser]–;
}

    $xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
?>

  xml_set_character_data_handler 建立字符资料标头。
语法: boolean xml_set_character_data_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置字符资料的标头。参数 parser 为解析代码。参数 handler 包括解析代码及资料字符串等二个元素。若无错误则返回 true 值。

  xml_set_processing_instruction_handler 建立处理指令标头。
语法: boolean xml_set_processing_instruction_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置处理指令 (Processing Instruction, 简称 PI) 的标头,处理指令类似下列行的格式 <?target data?> 参数 parser 为解析代码。参数 handler 包括解析代码、处理指令目标及资料字符串等三个元素。若无错误则返回 true 值。

  xml_set_default_handler 建立默认标头。
语法: boolean xml_set_default_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置默认的标头。参数 parser 为解析代码。参数 handler 包括解析代码及资料字符串等二个元素。若无错误则返回 true 值。

  xml_set_unparsed_entity_decl_handler 配置未解析实体宣告的标头。
语法: boolean xml_set_unparsed_entity_decl_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置尚未经过解析的实体宣告标头。参数 parser 为解析代码。参数 handler 包括解析代码、实体名称、基底、系统识别符、公用识别符、与记法名称等六个元素。看起来应是类似如下的字符串
<!ENTITY name {publicId | systemId} NDATA notationName>
更多的细节可以参考 XML 1.0 的规格书,有关实体宣告的部份。若无错误则返回 true 值。

  xml_set_notation_decl_handler 配置记法宣告的标头。
语法: boolean xml_set_notation_decl_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置记法宣告 (notation declaration) 的标头。参数 parser 为解析代码。参数 handler 包括解析代码、记法名称、基底、系统识别符、与公用识别符等五个元素。看起来应是类似如下的字符串 <!NOTATION name {systemId | publicId}>
更多的细节可以参考 XML 1.0 的规格书,有关 Notation 的部份。若无错误则返回 true 值。

  xml_set_external_entity_ref_handler 配置外部实体参引的标头。
语法: boolean xml_set_external_entity_ref_handler(int parser, string handler);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数配置外部实体参引 (external entity reference) 的标头。参数 parser 为解析代码。参数 handler 包括解析代码、打开实体名称、基底、系统识别符、与公用识别符等五个元素。若标头有错,可用 xml_get_error_code() 会返回 XML_ERROR_EXTERNAL_ENTITY_HANDLING。若无错误则返回 true 值。

  xml_parse 解析 XML 文件。
语法: boolean xml_parse(int parser, string data, int [isFinal]);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数用来解析 XML 格式的文件资料。参数 parser 为解析代码。参数 data 为解析的资料区块 (chunk)。参数 isFinal 可省略,若设为 true 则系统会自动送出最后的资料部分 (piece) 给 data 参数。若无错误则返回 true 值。

  xml_get_error_code 取得 XML 错误码。
语法: int xml_get_error_code(int parser);
返回值: 整数
函数种类: 资料处理
内容说明: 本函数可取得 XML 在处理时的错误代码。参数 parser 为解析代码。若 parser 有错则返回 false 值,否则就返回错误代码 (如 XML_ERROR_BINARY_ENTITY_REF …. 等等)。

  xml_error_string 取得 XML 错误字符串。
语法: string xml_error_string(int code);
返回值: 字符串
函数种类: 资料处理
内容说明: 本函数可取得 XML 在处理时的错误代码。参数 code 为解析错误代码。若无错误返回值为代码的文字描述字符串。

  xml_get_current_line_number 取得目前解析的行号。
语法: int xml_get_current_line_number(int parser);
返回值: 整数
函数种类: 资料处理
内容说明: 本函数用来取得目前 XML 解析所正在处理的行号。参数 parser 为解析代码。若 parser 有错则返回 false 值,若无错误则返回行号数字。

  xml_get_current_column_number 获知目前解析的第几字段。
语法: int xml_get_current_column_number(int parser);
返回值: 整数
函数种类: 资料处理
内容说明: 本函数用来取得目前 XML 解析所正在处理行的第几个字段。参数 parser 为解析代码。若 parser 有错则返回 false 值,若无错误则返回字段序数。

  xml_get_current_byte_index 取得目前解析为第几个位组。
语法: int xml_get_current_column_number(int parser);
返回值: 整数
函数种类: 资料处理
内容说明: 本函数用来取得目前 XML 解析所正在的位组 (byte) 为第几个位组。参数 parser 为解析代码。若 parser 有错则返回 false 值,若无错误则返回位序号。

  xml_parser_free 释放解析占用的内存。
语法: boolean xml_parser_free(int parser);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数用来释放目前 XML 解析所使用的内存。参数 parser 为解析代码。若没有错误则返回 true 值,否则返回 false 值。

  xml_parser_set_option
配置解析使用的选项。
语法: boolean xml_parser_set_option(int parser, int option, mixed value);
返回值: 布尔值
函数种类: 资料处理
内容说明: 本函数用来配置 XML 解析所选用的选项。参数 parser 为解析代码。参数 option 即为欲配置的选项常量名称,见下表 (如: XML_OPTION_CASE_FOLDING)。参数 value 则为欲配置的值。若没有错误则返回 true 值,否则返回 false 值。选项常量名称类型说明:

  XML_OPTION_CASE_FOLDING 整数 配置是否允许 case-folding,默认值为允许
XML_OPTION_TARGET_ENCODING 字符串 配置目地的编码类型,有 ISO-8859-1、US-ASCII 及 UTF-8 等
参考: xml_parser_get_option()

  xml_parser_get_option 取得解析使用的选项。
语法: mixed xml_parser_get_option(int parser, int option);
返回值: 混合类型资料
函数种类: 资料处理
内容说明: 本函数用来取得 XML 解析所选用的选项。参数 parser 为解析代码。参数 option 即为欲取得的选项常量名称,有 XML_OPTION_CASE_FOLDING 及 XML_OPTION_TARGET_ENCODING 二种。
参考: xml_parser_set_option()

  utf8_decode 将 UTF-8 码转成 ISO-8859-1 码。
语法: string utf8_decode(string data);
返回值: 字符串
函数种类: 资料处理
内容说明: 本函数用来将 UTF-8 内码转成 ISO-8859-1 内码。参数 data 为待转换的字符串。
参考 utf8_encode()

  utf8_encode 将 ISO-8859-1 码转成 UTF-8 码。
语法: string utf8_decode(string data);
返回值: 字符串
函数种类: 资料处理
内容说明: 本函数用来将 ISO-8859-1 内码转成 UTF-8 内码。参数 data 为待转换的字符串。
参考: utf8_decode()

Posted by sqlwang in PHP, web - Comments (0)
2 六月

谈PHP生成静态页面(转)

在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存相关信息的 话,整体的管理上比较繁琐,比方修改编辑.比方阅读权限限制等,但是,对应一些我们经常频频使用的文件,比方说,开发的新闻发布系统,我们不希望很多用户 都读取数据库才显示结果,这样一方面消耗了服务器的资源,另一方面占去了浏览者大量可贵的响应时间,所有,有了"静态页面话"的做法,当前很多网站都采用 这种技术,一般都是由管理后台控制,或者生成html直接显示,或者xhtml用css控制显示,或者生成xml用xslt显示,这些技术都不是难的,在 这里我就浅显的说说生成html的方法.

二、预备知识 

模板技术:

[PHP] 模板引擎Smarty深入浅出介绍  –2005-12-31
[PHP] 笑谈配置,使用Smarty技术        –2006-01-04

缓存技术:   

有些信息比方经常不变的,但是还是能变的信息放在缓存中以加快显示速度,这是很有价值的,所谓的缓存,通俗的理解就是一些保存在服务器端的共用信 息.它是于服务器同生死的,我们在保存缓存的时候可以指定下次更新的时间的判断,比方要在5分钟更新一次,可以记录上次更新的时间,和当前时间比较,如果 大于 5 分钟 ,读取数据库,更新换成,否则直接读取缓存数据,当然,缓存需要客户端用户激活的,只需一次.

ob_start()函数:打开输出缓冲区.
    函数格式 void ob_start(void)
    说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。

Flush:刷新缓冲区的内容,输出。
    函数格式:flush()
    说明:这个函数经常使用,效率很高。

ob_get_contents :返回内部缓冲区的内容。
    函数格式:string ob_get_contents(void)
    说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE.

ob_get_length:返回内部缓冲区的长度。
    函数格式:int ob_get_length(void)
    说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活,则返回 FALSE.

ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
    函数格式:void ob_end_clean(void)
    说明:这个函数不会输出内部缓冲区的内容而是把它删除

ob_end_flush:发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区
    函数格式:void ob_end_flush(void)
    说明:这个函数发送输出缓冲区的内容(如果有的话)

ob_implicit_flush:打开或关闭绝对刷新
    函数格式:void ob_implicit_flush ([int flag])
    说明:默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直接发送到浏览器,不再需要调用 flush()    

文件写入:   

int fwrite ( resource handle, string string [, int length] )
fwrite() 把 string 的内容写入 文件指针 handle 处。 如果指定了 length,当写入了 length 个字节或者写完了 string 以后,写入就会停止,视乎先碰到哪种情况。
fwrite() 返回写入的字符数,出现错误时则返回 FALSE 。
相关参考官方网站: 文件参考

三、解决方案

思路:开启 ob_start缓冲,当已经调出数据的时候获取 ob_get_contents,然后生成静态页,ob_end_clean清除缓冲.ok,就这么来,来看一个例子(php+mysql的结合):

创建数据库:

CREATE TABLE `bihtml` (
  `id` int(11) NOT NULL auto_increment,
  `szdtitle` varchar(16) NOT NULL,
  `szdcontent` text NOT NULL,
  PRIMARY KEY  (`id`) 
) TYPE=MyISAM;

获取当前的ID,并导入模板:

 

 

 

ob_start();
$id=_POST['id']
if(!isset($id)&&is_integer($id))
{
 @$db=new mysqli(’localhost’,'root’,'admin’,'bihtml’);
 $result=$db->fetch_one_array("select  * from szd_bi where id=’$id’");
   if(!empty($result))
   { 
   $tmp->assign(array(
    "Szdtitle",htmlspecialchars($result['titles']),
    "Szdcontent",$result['titles']));
   }
 $tpl->display(’default_1.tpl’);
 $this_my_f= ob_get_contents(); //此处关键
 ob_end_clean();
 $filename = "$id.html";
 if(tohtmlfile_cjjer($filename,$this_my_f))
 echo "生成成功 $filename";
 else
 echo "生成识别";
 }
}

//把生成文件的过程写出函数
function tohtmlfile_cjjer($file_cjjer_name,$file_cjjer_content)
{
 if (is_file ($file_cjjer_name)){
  @unlink ($file_cjjer_name);
 }
$cjjer_handle = fopen ($file_cjjer_name,"w");
 if (!is_writable ($file_cjjer_name)){
  return false;
 }
 if (!fwrite ($cjjer_handle,$file_cjjer_content)){
  return false;
 }
fclose ($cjjer_handle); //关闭指针
return $file_cjjer_name;
}

四、说明事项

1: 一般建议管理员添加数据的时候就生成静态页面,可以考虑记录生成的文件名次和路径.

2: php主要是    ob_starts()和 ob_get_contents,生成静态页面的时候很有用,当然也可以考虑调出数据库直接替换模板里面的变量也是可以的.

3:

主要的模板使用smarty,phplib都是可以的,smarty使用比较简易.

Posted by sqlwang in PHP, web - Tags: - Comments (0)
11 四月

php的memcache配置大全(转)

linux下的Memcache安装:

1. 下载 memcache的linux版本,注意 memcached 用 libevent 来作事件驱动,所以要先安装有 libevent。
2. 安装 pecl::memcache。

用 pecl 命令行工具安装:
pecl install memcache

或直接从源码安装:
phpize
./configure
make
make install

Windows下的Memcache安装:

1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached
2. 在终端(也即cmd命令界面)下输入 ‘c:\memcached\memcached.exe -d install’ 安装
3. 再输入: ‘c:\memcached\memcached.exe -d start’ 启动。NOTE: 以后memcached将作为windows的一个服务每次开机时自动启动。这样服务器端已经安装完毕了。
4.下载php_memcache.dll,请自己查找对应的php版本的文件
5. 在C:\winnt\php.ini 加入一行 ‘extension=php_memcache.dll’
6.重新启动Apache,然后查看一下phpinfo,如果有memcache,那么就说明安装成功!

memcached的基本设置:

-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25-n 最小分配空间,key+value+flags默认是48
-h 显示帮助

php.ini中的配置:

[Memcache]

; 一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,
; 它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。

; 是否在遇到错误时透明地向其他服务器进行故障转移。
memcache.allow_failover = On

; 接受和发送数据时最多尝试多少个服务器,只在打开memcache.allow_failover时有效。memcache.max_failover_attempts = 20

; 数据将按照此值设定的块大小进行转移。此值越小所需的额外网络传输越多。
; 如果发现无法解释的速度降低,可以尝试将此值增加到32768。
memcache.chunk_size = 8192

; 连接到memcached服务器时使用的默认TCP端口。
memcache.default_port = 11211

; 控制将key映射到server的策略。默认值"standard"表示使用先前版本的老hash策略。
; 设为"consistent"可以允许在连接池中添加/删除服务器时不必重新计算key与server之间的映射关系。
;memcache.hash_strategy = "standard"; 控制将key映射到server的散列函数。默认值"crc32"使用CRC32算法,而"fnv"则表示使用FNV-1a算法。
; FNV-1a比CRC32速度稍低,但是散列效果更好。
;memcache.hash_function = "crc32"

;memcache也可以作为session的存储模块,具体参看:memcache PHP 的 session.save_handler.

memcache的测试代码:

  1. $memcache = new Memcache;  
  2. $memcache->connect(‘localhost’, 11211) or die ("Could not connect");  
  3.   
  4. $version = $memcache->getVersion();  
  5. echo "Server’s version: ".$version."<br>\n";  
  6.   
  7. $tmp_object = new stdClass;  
  8. $tmp_object->str_attr = ‘test’;  
  9. $tmp_object->int_attr = 123;  
  10.   
  11. $memcache->set(‘key’$tmp_object, false, 10) or die ("Failed to save data at the server");  
  12. echo "Store data in the cache (data will expire in 10 seconds)<br>\n";  
  13.   
  14. $get_result = $memcache->get(‘key’);  
  15. echo "Data from the cache:<br>\n";  
  16.   
  17. var_dump($get_result);  
Posted by sqlwang in 数据库 - Comments (0)
21 三月