<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>magicjungle</title>
	<atom:link href="http://www.magic-jungle.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.magic-jungle.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 29 Aug 2010 07:25:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>什么是单一入口应用程序</title>
		<link>http://www.magic-jungle.com/?p=142</link>
		<comments>http://www.magic-jungle.com/?p=142#comments</comments>
		<pubDate>Sun, 29 Aug 2010 07:25:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ROR]]></category>
		<category><![CDATA[单一入口]]></category>
		<category><![CDATA[框架]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=142</guid>
		<description><![CDATA[单一入口应用程序概述 什么是单一入口应用程序？
在解释什么是单一入口应用程序之前，我们先来看看传统的 web 应用程序。
news.php 显示新闻列表
news_edit.php 显示新闻编辑页面
这两个页面不但分别实现了两个功能，还成为了应用程序的两个入口。
 那什么是入口啊？
打个比方，大家上 WC，都是男生进一个门，女生进一个门。这两个门就是 WC 的两个入口。
呵呵，上面的例子应该很好理解吧。那稍微变换一下，单一入口的概念就很容易理解了。
现在我们是进一个公共 WC，不管男女都是从最外面的入口进入，交了钱以后才分别进两个门。那最外面的入口就是这个 WC 的单一入口。
所以单一入口的应用程序实际上就是说用一个文件处理所有的 HTTP 请求。例如不管是新闻列表功能还是新闻编辑功能，都是从浏览器访问 index.php 文件。这个 index.php 文件就是这个应用程序的单一入口。
index.php 如何知道用户是要使用哪一个功能呢？
很简单，我们访问 index.php 时跟上一个特定的参数就行了。例如 index.php?action=news 就是显示新闻列表，而 index.php?action=news_edit 就是新闻编辑。
而在 index.php 里面，仅用两行代码就可以实现这种效果。
上面的代码中，第一行是从 url 中取出 action 参数。如果没有提供 action 参数，就设置一个默认的 &#8216;index&#8217; 作为参数。
第二行代码就是根据 $action 参数调用不同的代码文件，从而实现单一入口对应不同功能的效果。
单一入口应用程序的入口文件很复杂？
有些朋友可能以为单一入口程序的 index.php 会像面条一样复杂，其实是误解。
例如我现在的应用程序入口文件只有下面几行：
足够简单了吧？
当然了，在 index.php 里面写上一长串 switch case 绝对是拙劣的实现方式。但这纯粹是开发者自己的设计和实现问题，而不是单一入口应用程序这种设计思想的问题。
补充说明： 这里提到 switch case 并不是说用了 switch 就代表“落后”、“土气”等。只是说在 index.php 这个入口程序里面写上一堆 switch case [...]]]></description>
			<content:encoded><![CDATA[<p>单一入口应用程序概述 什么是单一入口应用程序？<br />
在解释什么是单一入口应用程序之前，我们先来看看传统的 web 应用程序。<br />
news.php 显示新闻列表<br />
news_edit.php 显示新闻编辑页面<br />
这两个页面不但分别实现了两个功能，还成为了应用程序的两个入口。<br />
<strong> 那什么是入口啊？</strong><br />
打个比方，大家上 WC，都是男生进一个门，女生进一个门。这两个门就是 WC 的两个入口。<br />
呵呵，上面的例子应该很好理解吧。那稍微变换一下，单一入口的概念就很容易理解了。<br />
现在我们是进一个公共 WC，不管男女都是从最外面的入口进入，交了钱以后才分别进两个门。那最外面的入口就是这个 WC 的单一入口。<br />
所以单一入口的应用程序实际上就是说用一个文件处理所有的 HTTP 请求。例如不管是新闻列表功能还是新闻编辑功能，都是从浏览器访问 index.php 文件。这个 index.php 文件就是这个应用程序的单一入口。<span id="more-142"></span></p>
<p>index.php 如何知道用户是要使用哪一个功能呢？<br />
很简单，我们访问 index.php 时跟上一个特定的参数就行了。例如 index.php?action=news 就是显示新闻列表，而 index.php?action=news_edit 就是新闻编辑。<br />
而在 index.php 里面，仅用两行代码就可以实现这种效果。</p>
<p>上面的代码中，第一行是从 url 中取出 action 参数。如果没有提供 action 参数，就设置一个默认的 &#8216;index&#8217; 作为参数。<br />
第二行代码就是根据 $action 参数调用不同的代码文件，从而实现单一入口对应不同功能的效果。</p>
<p>单一入口应用程序的入口文件很复杂？<br />
有些朋友可能以为单一入口程序的 index.php 会像面条一样复杂，其实是误解。<br />
例如我现在的应用程序入口文件只有下面几行：</p>
<p>足够简单了吧？<br />
当然了，在 index.php 里面写上一长串 switch case 绝对是拙劣的实现方式。但这纯粹是开发者自己的设计和实现问题，而不是单一入口应用程序这种设计思想的问题。<br />
补充说明： 这里提到 switch case 并不是说用了 switch 就代表“落后”、“土气”等。只是说在 index.php 这个入口程序里面写上一堆 switch case 不利于程序的修改和维护，所以是一种不好的用法。</p>
<p>单一入口应用程序的设计思想<br />
当web服务器（apache或者iis）收到一个http请求时，会解析该请求，确定要访问哪一个文件。例如http://www.xxx.com/news.php的解析结果就是要求web服务器解析 news.php 文件，并返回结果给浏览器。现在看看单一入口应用程序的 index.php 文件，就会发现 index.php 实际上根据 url 参数进行了第二次解析。<br />
完成这个解析的程序一般称为 Dispatcher（中文的准确翻译我也不知道），大概意思就是将不同的请求转发到不同的处理程序进行处理。<br />
在单一入口应用程序中，index.php 和 web服务器一起构成了一个 Dispatcher，根据 http 请求和 url 参数来确定请求的处理程序。<br />
了解了 Dispatcher 的概念后，我们可以发现前面提到的两行代码实际上就是一个最简单的 Dispatcher 实现：</p>
<p>诚然，对于一个安全、健壮的应用程序，Dispatcher 肯定不是上面那么简单。在调用实际代码前，还会加上各种判断、安全性检查等。例如判断 url 指定的功能是否可以访问以及 url 中包含了无效的参数。<br />
看到这里，朋友们肯定会说：单一入口程序就多了就这样一个 dispatcher ，和我直接做成 news.php、news_edit.php 等单个文件相比有什么好处啊？</p>
<p>单一入口应用程序的优势<br />
单一入口应用程序的所有http请求都是通过 index.php 接收并转发到功能代码去的，所以我们在 index.php 里面就能完成许多实际工作。<br />
这里我只拿安全性检查为例详细说明一下：<br />
由于所有的 http 请求都由 index.php 接收，所以可以进行集中的安全性检查。如果不是单一入口，那么开发者就必须记得在每一个文件的开始加上安全性检查代码（当然，安全性检查代码可以写到另一个文件中，只需要include进来就可以了）。<br />
但我想大家都是懒人，也许记性也不好，难免有忘记的时候。因此要记得在每一个文件前面都加上必要的include可不是件容易做到的事情。<br />
与安全性检查类似。在入口里，我们还可以对url参数和post进行必要的检查和特殊字符过滤、记录日志、访问统计等等各种可以集中处理的任务。<br />
“咦，搞这么多功能，不是会把 index.php 搞得很复杂吗？”<br />
“不会的。只需要把各种功能写到单独的文件，然后在index.php里面include进来就可以了！”<br />
可以看出，由于这些工作都被集中到了 index.php 来完成，可以减轻我们维护其他功能代码的难度。例如在10个文件中保持头部的几个include都一致可不是件让人愉快的事情。</p>
<p>单一入口应用程序的缺点<br />
任何事情都有两面性，单一入口应用程序也不例外。由于所有 http 请求都是针对 index.php，所以应用程序的 url 看起来确实不那么美观。特别是对搜索引擎来说很不友好。<br />
要解决这个问题，可以采用 url 重写、PATHINFO 等方式。但我个人更推荐在前台页面不使用单一入口方式，而是保持多个文件入口。或者两者混用。例如新闻列表采用单独的 news.php 显示，而用户注册、发表信息等则采用单一入口。因为对于网站拥有者来说，新闻列表、新闻显示页面才是需要搜索引擎关注的高价值目标，而用户注册页面等交互性功能则根本没有收录的价值。<br />
有朋友提到单一入口的应用程序会有很长一串参数，那么我们分析一下下面这个 url：</p>
<p>index.php?url=news&amp;news_id=123&amp;page=2&amp;sort=title<br />
如果改为直接访问 news.php，也只不过省掉了 url=news 这一个参数而已。</p>
<p>所以认为单一入口的应用程序 url 太复杂是没有道理的。<br />
如何组织单一入口应用程序的功能代码？</p>
<p>单一入口应用程序最大的挑战来自于如何合理组织各个功能的处理代码。但只要遵循一定的步骤，也可以轻松的解决掉这个难题。</p>
<p>首先，对于应用程序的功能要做出一个合理的分解。例如后台的新闻栏目可能包含“添加新闻”、“编辑新闻”、“删除新闻”等多个功能。这时我们就可以将这一组逻辑上关联的功能组合到一个功能模块中，称为“新闻管理”模块。<br />
按照上面的方法整理完应用程序的功能，我们就会得到多个功能模块，而每个模块又是由多个功能组成。（实际上，即便不是单一入口应用程序，功能的整理也是必须的步骤。）</p>
<p>整理完功能后，我们就需要确定如何存放各个功能的代码。这里我推荐两种方式：</p>
<p>1、每个功能模块一个子目录，目录里的每一个文件就是一个功能的实现代码。<br />
这种方式的好处是每个功能的代码都互相隔离，非常便于多人协作。缺点是每个功能之间共享代码和数据不那么方便。例如新闻管理模块中的所有功能都需要一个“取出新闻栏目记录”的功能，那么采用这种多个独立文件的组织方式，“取出新闻栏目记录”就只能写在另一个文件中，然后由需要该功能的文件include进去。</p>
<p>2、每个模块一个文件，模块中的每个功能写成一个函数或者一个类方法。<br />
好处不用多说了，非常便于共享代码和数据。缺点就是如果几个人同时改，容易发生冲突。不过借助版本控制软件和差异比较合并工具，冲突还是很容易解决的。<br />
好了，我们的功能代码都确定存放方式了。那么如何调用呢？<br />
index.php 如何调用功能代码？</p>
<p>调用首先就是要设计一个规则，然后让 index.php 根据这个规则来搜索和调用功能代码。就我自己来说，我总是使用 $_GET['url'] 来指定要调用的功能模块，而 $_GET['action'] 来指定该模块的特定功能。因此我的应用程序会使用如下的 url 地址：<br />
index.php?url=news&amp;action=edit</p>
<p>觉得两个参数太多了？那可以使用 index.php?func=news.edit 这样的 url。只需要将 news.edit 拆开为 news 和 edit 就行了。</p>
<p>“嘿嘿，那我故意搞一个 index.php?url=news&amp;action=xxx，看你的应用程序还能运行？”<br />
很显然，这样的 url 只会使得 index.php 无法找到需要的功能代码，最后报告错误。但是这和你在浏览器中访问 newsxxx.php 这个并不存在的文件有什么本质区别呢？</p>
<p>相反，我还可以让 index.php 在发现找不到需要的功能代码时显示一个漂亮的出错页面，并提供一个返回网站首页的连接。</p>
<p>在实际开发中，我倾向于将一些基本服务从应用程序中抽取出来，形成一个应用程序框架。这个框架通常会包含一个 Dispatcher、基本的数据库访问服务、模版引擎、常用的辅助功能等。由于有了一个框架，所以我可以更加让 Dispatcher 更加灵活。例如可以对某些功能模块应用权限检查，而另一些则不检查。<br />
进一步了解单一入口应用程序</p>
<p>要深刻理解一个事物，自己尝试一下是最好的办法。</p>
<p>你可以选择自己实现一个 Dispatcher 以及相应的各种规则，或者选择一个现有的应用程序框架。但更好的方式还是首先尝试一下现有的框架，然后再自己尝试实现一个类似的。这样可以在最短的时间内获得最多的收获。</p>
<p>目前绝大多数 php 应用程序框架都是单一入口的，并采用了 MVC 模式（很遗憾，由于 MVC 实在太复杂，并且和单一入口应用程序也没有必然联系，所以我就不赘述了。感兴趣的朋友可以 google 一下相关资料）。</p>
<p>我个人推荐下面的框架：<br />
CakePHP</p>
<p>http://www.cakephp.org/</p>
<p>一个 Ruby on Rails 的 PHP 仿制品。具有出色的功能，但显然太过于复杂，而且缺乏中文资料是个很大的问题。<br />
symfony</p>
<p>http://www.symfony-project.com/</p>
<p>一个超复杂的框架，集成了 n 多东西。项目网站上提供的视频演示看上去很不错。<br />
其他<br />
还有 Mojavi、Phing 等许多 PHP 框架，如果你精力充沛，可以去探索一下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=142</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何转义插入到数据里的特殊符号，例如：“ &#8216; ”,“&#8221;”</title>
		<link>http://www.magic-jungle.com/?p=137</link>
		<comments>http://www.magic-jungle.com/?p=137#comments</comments>
		<pubDate>Fri, 27 Aug 2010 13:40:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[addslashes]]></category>
		<category><![CDATA[mysql_escape_string]]></category>
		<category><![CDATA[特殊字符]]></category>
		<category><![CDATA[转义]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=137</guid>
		<description><![CDATA[php mysql转义特殊字符的函数
一个是：addslashes
一个是：mysql_escape_string
mysql_escape_string与addslashes的区别在于
mysql_escape_string总是将“’”转换成“\’ ”
而addslashes
在magic_quotes_sybase=on时将“ ’ ”转换成“ ” ”
在magic_quotes_sybase=off时将“ ’ ”转换成“\’ ”
php，就提供了一些函数，使你的查询语句符合你的要求，比如mysql_escape_string
引用一个字符串，并返回一个结果，该结果可作为一个适当转义过的数据值在一个 SQL 语句中使用。字符串被单引号包围着返回，并且在该字符串中每个单引号(“’”)、反斜线符号(“\”)、ASCII NUL 和 Control-Z 出现的地方，在该字符之前均被加上了一个反斜线。如果参数是 NULL，那么结果值是一个没有单引号包围的单词 “NULL”。 QUOTE 函数在 MySQL 4.0.3 中被加入。
在往数据库里写数据的时候, 有时要写入的字符串中包含了一些特殊的字符,如 ‘,”,/,%等,不知道mysql本身有没有这种转义的函数,不是那些api.
php mysql转义特殊字符的函数一个是：addslashes
一个是：mysql_escape_string
mysql_escape_string与addslashes的区别在于    mysql_escape_string总是将“’”转换成“\’”       而addslashes    在magic_quotes_sybase=on时将“’”转换成“””    在magic_quotes_sybase=off时将“’”转换成“\’”php，就提供了一些函数，使你的查询语句符合你的要求，比如mysql_escape_string引用一个字符串，并返回一个结果，该结果可作为一个适当转义过的数据值在一个 SQL 语句中使用。字符串被单引号包围着返回，并且在该字符串中每个单引号(“’”)、反斜线符号(“\”)、ASCII NUL 和 Control-Z 出现的地方，在该字符之前均被加上了一个反斜线。如果参数是 NULL，那么结果值是一个没有单引号包围的单词 “NULL”。 QUOTE 函数在 MySQL 4.0.3 中被加入。在往数据库里写数据的时候, 有时要写入的字符串中包含了一些特殊的字符,如 ‘,”,/,%等,不知道mysql本身有没有这种转义的函数,不是那些api.
]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">php mysql转义特殊字符的函数</div>
<div id="_mcePaste">一个是：addslashes</div>
<div id="_mcePaste">一个是：mysql_escape_string</div>
<div id="_mcePaste">mysql_escape_string与addslashes的区别在于<span id="more-137"></span></div>
<p><font style="font-size:16px;">mysql_escape_string总是将“’”转换成“\’ ”</font></p>
<div id="_mcePaste">而addslashes</div>
<p><font style="font-size:16px;">在magic_quotes_sybase=on时将“ ’ ”转换成“ ” ”</font><br />
<font style="font-size:16px;">在magic_quotes_sybase=off时将“ ’ ”转换成“\’ ”</font></p>
<div id="_mcePaste">php，就提供了一些函数，使你的查询语句符合你的要求，比如mysql_escape_string</div>
<div id="_mcePaste">引用一个字符串，并返回一个结果，该结果可作为一个适当转义过的数据值在一个 SQL 语句中使用。字符串被单引号包围着返回，并且在该字符串中每个单引号(“’”)、反斜线符号(“\”)、ASCII NUL 和 Control-Z 出现的地方，在该字符之前均被加上了一个反斜线。如果参数是 NULL，那么结果值是一个没有单引号包围的单词 “NULL”。 QUOTE 函数在 MySQL 4.0.3 中被加入。</div>
<div id="_mcePaste">在往数据库里写数据的时候, 有时要写入的字符串中包含了一些特殊的字符,如 ‘,”,/,%等,不知道mysql本身有没有这种转义的函数,不是那些api.</div>
<p>php mysql转义特殊字符的函数一个是：addslashes<br />
一个是：mysql_escape_string<br />
mysql_escape_string与addslashes的区别在于    mysql_escape_string总是将“’”转换成“\’”       而addslashes    在magic_quotes_sybase=on时将“’”转换成“””    在magic_quotes_sybase=off时将“’”转换成“\’”php，就提供了一些函数，使你的查询语句符合你的要求，比如mysql_escape_string引用一个字符串，并返回一个结果，该结果可作为一个适当转义过的数据值在一个 SQL 语句中使用。字符串被单引号包围着返回，并且在该字符串中每个单引号(“’”)、反斜线符号(“\”)、ASCII NUL 和 Control-Z 出现的地方，在该字符之前均被加上了一个反斜线。如果参数是 NULL，那么结果值是一个没有单引号包围的单词 “NULL”。 QUOTE 函数在 MySQL 4.0.3 中被加入。在往数据库里写数据的时候, 有时要写入的字符串中包含了一些特殊的字符,如 ‘,”,/,%等,不知道mysql本身有没有这种转义的函数,不是那些api.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=137</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>flash wmode参数详解</title>
		<link>http://www.magic-jungle.com/?p=135</link>
		<comments>http://www.magic-jungle.com/?p=135#comments</comments>
		<pubDate>Tue, 10 Aug 2010 05:19:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Flash & Actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[opaque]]></category>
		<category><![CDATA[transparent]]></category>
		<category><![CDATA[window]]></category>
		<category><![CDATA[wmode]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=135</guid>
		<description><![CDATA[在做web开发中可能会遇到flash遮挡页面中元素的情况，无论怎么设置flash容器和层的深度(z-index)也无济于事，现有的解决方案是在插入flash的embed或object标签中加入”wmode”属性并设置为wmode=“transparent”或”opaque”，但wmode属性到底是什么意义，为什么可以解决这个问题呢？
window mode(wmode)
wmode即窗口模式总共有三种，看看当年Macromedia官方的说法：

Window: Use the Window value to play a Flash Player movie in its own rectangular window on a web page. This is the default value for wmode and it works the way the classic Flash Player works. This normally provides the fastest animation performance.
Opaque: By using the Opaque value you can use JavaScript to [...]]]></description>
			<content:encoded><![CDATA[<p>在做web开发中可能会遇到flash遮挡页面中元素的情况，无论怎么设置flash容器和层的深度(z-index)也无济于事，现有的解决方案是在插入flash的embed或object标签中加入”wmode”属性并设置为wmode=“transparent”或”opaque”，但wmode属性到底是什么意义，为什么可以解决这个问题呢？<span id="more-135"></span></p>
<p><strong>window mode(wmode)</strong></p>
<p>wmode即窗口模式总共有三种，看看当年Macromedia官方的说法：</p>
<ul>
<li>Window: Use the Window value to play a Flash Player movie in its own rectangular window on a web page. This is the default value for wmode and it works the way the classic Flash Player works. This normally provides the fastest animation performance.</li>
<li>Opaque: By using the Opaque value you can use JavaScript to move or resize movies that don’t need a transparent background. Opaque mode makes the movie hide everything behind it on the page. Additionally, opaque mode moves elements behind Flash movies (for example, with dynamic HTML) to prevent them from showing through.</li>
<li>Transparent: Transparent mode allows the background of the HTML page, or the DHTML layer underneath the Flash movie or layer, to show through all the transparent portions of the movie. This allows you to overlap the movie with other elements of the HTML page. Animation performance might be slower when you use this value.</li>
</ul>
<p><strong>window 模式</strong></p>
<p>默认情况下的显示模式，在这种模式下flash player有自己的窗口句柄，这就意味着flash影片是存在于Windows中的一个显示实例，并且是在浏览器核心显示窗口之上的，所以flash只是貌似显示在浏览器中，但这也是flash最快最有效率的渲染模式。由于他是独立于浏览器的HTML渲染表面，这就导致默认显示方式下flash总是会遮住位置与他重合的所有DHTML层。</p>
<p>但是大多数苹果电脑浏览器会允许DHTML层显示在flash之上，但当flash影片播放时会出现比较诡异的现象，比如DHTML层像被flash刮掉一块一样显示异常。</p>
<p><strong>Opaque 模式</strong></p>
<p>这是一种无窗口模式，在这种情况下flash player没有自己的窗口句柄，这就需要浏览器需要告诉flash player在浏览器的渲染表面绘制的时间和位置。这时flash影片就不会在高于浏览器HTML渲染表面而是与其他元素一样在同一个页面上,因此你就可以使用z-index值来控制DHTML元素是遮盖flash或者被遮盖。</p>
<p><strong>Transparent 模式</strong></p>
<p>透明模式，在这种模式下flash player会将stage的背景色alpha值将为0并且只会绘制stage上真实可见的对象，同样你也可以使用z-index来控制flash影片的深度值，但是与Opaque模式不同的是这样做会降低flash影片的回放效果，而且在9.0.115之前的flash player版本设置wmode=”opaque”或”transparent”会导致全屏模式失效。</p>
<p>了解了各种模式的实现方式和意义在以后的开发中就可以按照具体情况选择设置wmode属性的值了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=135</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何去除phpmyadmin对导入sql文件2m的限制</title>
		<link>http://www.magic-jungle.com/?p=132</link>
		<comments>http://www.magic-jungle.com/?p=132#comments</comments>
		<pubDate>Mon, 09 Aug 2010 17:55:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[2m]]></category>
		<category><![CDATA[phpmyadmin]]></category>
		<category><![CDATA[sql导入]]></category>
		<category><![CDATA[超时]]></category>
		<category><![CDATA[过大]]></category>
		<category><![CDATA[限制]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=132</guid>
		<description><![CDATA[一、修改c:\windows\php.ini文件。
如果是win2000的机器，应该是c\winnt\php.ini，用写字板打开php.ini文件：
1、查找post_max_size，指通过表单post给php的所能接收的最大值，包括表单里的所有值，默认为8m，看你自己需要进行改变。
2、查找fileuploads，首先确认file_uploads=on;是否允许通过http上传文件的开关，默认为on即是开。upload_tmp_dir;
查找upload_max_filesize;即允许上传文件大小的最大值。默认为2m。
3、如果要上传&#62;8m的文件，那么只设置上述四项还不定一定可以。最好对下面的参数也进行设置：
查找max_execution_time=600;每个php页面运行的最大时间值(秒)，默认30秒。
max_input_time=600;每个php页面接收数据所需的最大时间，默认60秒。
memory_limit=8m;每个php页面所吃掉的最大内存，默认8m。

 二、修改c:\phpmyadmin\import.php文件。
用写字板打开import.php文件：
1、查找$memory_limit，默认为$memory_limit=210241024;自己修改。
2、下边三四行的位置有同样的语句，自己修改。
 三、到这里还不行，iis的问题。
1）解决在iis6.0中，无法上传大容量文件的办法：
1、先在服务里关闭iisadminservice服务。
2、找到windows\system32\inetsrv\下的metabase.xml文件。
3、用写字板打开，找到aspmaxrequestentityallowed把它修改为需要的值（默认为：204800，即：200k）。
4、存盘，然后重启iisadminservice服务，重启iis。
2）解决在iis6.0中，无法下载超过4m的附件步骤：
1、先在服务里关闭iisadminservice服务。
2、找到windows\system32\inetsrv\下的metabase.xml文件。
3、用写字板打开，找到aspbufferinglimit把它修改为需要的值（默认为：4194304，即：4mb）。
4、存盘，然后重启iisadminservice服务，重启iis
又一方法（算是补充吧）：

二、数据备份和恢复
 默认的数据导出、和导入最大文件有2m的最大限制。如果要操作大于2m的数据库备份文件就需要预先将文件上传到phpmyadmin的某个目录。
1.首先在phpmyadmin个跟目录建立一个目录，比如叫ports
2.在config.default.php中搜$cfg[uploaddir]，这个变量定义保存导入文件存放的目录，它下面的$cfg[savedir]定义的是数据导出文件的存放目录，我们都定义为ports
$cfg[uploaddir]=ports;
$cfg[savedir]=ports;
要注意的是ports目录的权限，savedir只要能让php脚本往里边写东西。最后的就是操作完了，务必清空改目录，防止数据被别有用心的人下载。
]]></description>
			<content:encoded><![CDATA[<p><strong>一、修改c:\windows\php.ini文件。</strong><br />
如果是win2000的机器，应该是c\winnt\php.ini，用写字板打开php.ini文件：<br />
1、查找post_max_size，指通过表单post给php的所能接收的最大值，包括表单里的所有值，默认为8m，看你自己需要进行改变。<br />
2、查找fileuploads，首先确认file_uploads=on;是否允许通过http上传文件的开关，默认为on即是开。upload_tmp_dir;<br />
查找upload_max_filesize;即允许上传文件大小的最大值。默认为2m。<br />
3、如果要上传&gt;8m的文件，那么只设置上述四项还不定一定可以。最好对下面的参数也进行设置：<br />
查找max_execution_time=600;<strong>每个php页面运行的最大时间值(秒)，默认30秒。</strong><br />
max_input_time=600;<strong>每个php页面接收数据所需的最大时间，默认60秒。</strong><br />
memory_limit=8m;<strong>每个php页面所吃掉的最大内存，默认8m。</strong></p>
<p><strong></strong><span id="more-132"></span><br />
<strong> 二、修改c:\phpmyadmin\import.php文件。</strong><br />
用写字板打开import.php文件：<br />
1、查找$memory_limit，默认为$memory_limit=210241024;自己修改。<br />
2、下边三四行的位置有同样的语句，自己修改。<br />
<strong> 三、到这里还不行，iis的问题。</strong><br />
1）解决在iis6.0中，无法上传大容量文件的办法：<br />
1、先在服务里关闭iisadminservice服务。<br />
2、找到windows\system32\inetsrv\下的metabase.xml文件。<br />
3、用写字板打开，找到aspmaxrequestentityallowed把它修改为需要的值（默认为：204800，即：200k）。<br />
4、存盘，然后重启iisadminservice服务，重启iis。<br />
2）解决在iis6.0中，无法下载超过4m的附件步骤：<br />
1、先在服务里关闭iisadminservice服务。<br />
2、找到windows\system32\inetsrv\下的metabase.xml文件。<br />
3、用写字板打开，找到aspbufferinglimit把它修改为需要的值（默认为：4194304，即：4mb）。<br />
4、存盘，然后重启iisadminservice服务，重启iis<br />
<strong>又一方法（算是补充吧）：</strong></p>
<p><strong></strong><br />
二、数据备份和恢复<br />
<strong> 默认的数据导出、和导入最大文件有2m的最大限制。如果要操作大于2m的数据库备份文件就需要预先将文件上传到phpmyadmin的某个目录。</strong><br />
1.首先在phpmyadmin个跟目录建立一个目录，比如叫ports<br />
2.在config.default.php中搜$cfg[uploaddir]，这个变量定义保存导入文件存放的目录，它下面的$cfg[savedir]定义的是数据导出文件的存放目录，我们都定义为ports<br />
$cfg[uploaddir]=ports;<br />
$cfg[savedir]=ports;<br />
要注意的是ports目录的权限，savedir只要能让php脚本往里边写东西。最后的就是操作完了，务必清空改目录，防止数据被别有用心的人下载。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=132</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>php中库与框架、模板的区别</title>
		<link>http://www.magic-jungle.com/?p=130</link>
		<comments>http://www.magic-jungle.com/?p=130#comments</comments>
		<pubDate>Sat, 07 Aug 2010 18:48:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[kuangjia]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[区别]]></category>
		<category><![CDATA[库]]></category>
		<category><![CDATA[模板]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=130</guid>
		<description><![CDATA[所谓库，一个应用的封装集合，旨在增强代码复用，简化开发者的工作。对于开发者，要做的只是找到一个适合自己的库，所谓适合就是说这个库能提供你所期望的输出，了解这个库所要求的输入规则。应用的时候，就把自己的数据按照约定组织，传给库，库将返回你期望的结果，则直接使用这个返回数据就OK了。

所以框架，是一种代码结构的约定和一些为了工程代码的框架代码，旨在让工程代码条理清晰，更易维护，可读性更强，更高的层次，安全性更高，扩展性更强等。对于开发者，适合与不适合之说，并不确切，而是有了很多主观因素，比如开发者对一个框架的代码结构设计是否同意等。使用一个框架，需要了解这个框架的约定和运行机制，然后依据这个框架的约定组织自己的代码。
不论是从存在的意义还是应用方式上，库和框架有非常明显的区别，但江湖上流传的各种框架，各种语言的似乎都对这两个概念稍有混淆，尤其是PHP框架，库和框架混淆比较严重，主流的那些框架，提供各种功能，数据验证器，认证码生成器等等，十分完整，十分强大。也包括我参与的KiwiPHP还有他的升级版lotusphp，都有这种现象。
我认为对于一个好的框架来说，或者用框架这个词并不准确，是框架和库的组合体，作为这样一个东西，要造福PHP开发者，应该把框架和库这两个部分清晰的拆分开，并提供一种有机的组合方式，实现方便的库订制服务，这样一来，所有的库都可以以插件的方式集成进来，扩展性可以大大提高，而且对于框架使用者只需订制自己需要的一些库，使用起来更加轻量，效率也更高。
刚词说道框架和库的组合体，想到一个词：平台，但又感觉平台这个词太大了，一个平台需要提供一项工作所需要的一切服务。针对开发来说，框架和库是远远不够的，还有包括测试工具，IDE等等很多东西。
先说下模板

模板的主要功能是逻辑与表现的分离，即常说的PHP与HTML的分离，使得后台程序的开发和前台开发分开，最后通过模板引擎结合起来。

框架：
 一般用来开发大型的系统，现象网站系统越来越复杂了，需要考虑的东西越来越多，而框架就把一些常用的功能进行模块化，组件化，使你的开发只要做一些基础的工作，比如，框架可以帮你简化事物处理，安全性，数据流控制等问题。

一般框架里面也自带了模板引擎，有的既可以使用自带的模板引擎，也可以自定义模板引擎。

框架涉及的东西比模板多的多，也复杂的多
]]></description>
			<content:encoded><![CDATA[<p>所谓库，一个应用的封装集合，旨在增强代码复用，简化开发者的工作。对于开发者，要做的只是找到一个适合自己的库，所谓适合就是说这个库能提供你所期望的输出，了解这个库所要求的输入规则。应用的时候，就把自己的数据按照约定组织，传给库，库将返回你期望的结果，则直接使用这个返回数据就OK了。</p>
<p><span id="more-130"></span><br />
所以框架，是一种代码结构的约定和一些为了工程代码的框架代码，旨在让工程代码条理清晰，更易维护，可读性更强，更高的层次，安全性更高，扩展性更强等。对于开发者，适合与不适合之说，并不确切，而是有了很多主观因素，比如开发者对一个框架的代码结构设计是否同意等。使用一个框架，需要了解这个框架的约定和运行机制，然后依据这个框架的约定组织自己的代码。<br />
不论是从存在的意义还是应用方式上，库和框架有非常明显的区别，但江湖上流传的各种框架，各种语言的似乎都对这两个概念稍有混淆，尤其是PHP框架，库和框架混淆比较严重，主流的那些框架，提供各种功能，数据验证器，认证码生成器等等，十分完整，十分强大。也包括我参与的<a href="http://code.google.com/p/kiwiphp/"><span style="color: #3354aa;">KiwiPHP</span></a>还有他的升级版<a href="http://code.google.com/p/lotusphp/"><span style="color: #3354aa;">lotusphp</span></a>，都有这种现象。<br />
我认为对于一个好的框架来说，或者用框架这个词并不准确，是框架和库的组合体，作为这样一个东西，要造福PHP开发者，应该把框架和库这两个部分清晰的拆分开，并提供一种有机的组合方式，实现方便的库订制服务，这样一来，所有的库都可以以插件的方式集成进来，扩展性可以大大提高，而且对于框架使用者只需订制自己需要的一些库，使用起来更加轻量，效率也更高。<br />
刚词说道框架和库的组合体，想到一个词：平台，但又感觉平台这个词太大了，一个平台需要提供一项工作所需要的一切服务。针对开发来说，框架和库是远远不够的，还有包括测试工具，IDE等等很多东西。</p>
<pre><strong>先说下模板</strong>

模板的主要功能是逻辑与表现的分离，即常说的PHP与HTML的分离，使得后台程序的开发和前台开发分开，最后通过模板引擎结合起来。

<strong>框架：</strong>
<strong> </strong>一般用来开发大型的系统，现象网站系统越来越复杂了，需要考虑的东西越来越多，而框架就把一些常用的功能进行模块化，组件化，使你的开发只要做一些基础的工作，比如，框架可以帮你简化事物处理，安全性，数据流控制等问题。

一般框架里面也自带了模板引擎，有的既可以使用自带的模板引擎，也可以自定义模板引擎。

框架涉及的东西比模板多的多，也复杂的多</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=130</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP5 Session 相关函数详解</title>
		<link>http://www.magic-jungle.com/?p=128</link>
		<comments>http://www.magic-jungle.com/?p=128#comments</comments>
		<pubDate>Sat, 07 Aug 2010 13:53:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[session_destroy()]]></category>
		<category><![CDATA[session_id]]></category>
		<category><![CDATA[session_regenerate_id()]]></category>
		<category><![CDATA[session_register()]]></category>
		<category><![CDATA[session_start]]></category>
		<category><![CDATA[session_unset()]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=128</guid>
		<description><![CDATA[
http协议是WEB服务器与客户端(浏览器)相互通信的协议，它是一种无状态协议。所谓无状态，指的是不会维护http请求数据，http请求是 独立的，不持久的。而越来越复杂的WEB应用，需要保存一些用户状态信息。这时候，Session这种方案应需而生。PHP从4.1开始支持 Session管理。
Session！它是很抽象的一个概念。我们不妨先从与它几个息息相关的有迹可寻的小切入点入手，然后逐渐地认识了解Session！
Session存储
首先，我们为什么需要Session，就是因为我们需要:存储各个用户的状态数据。那么试问，如果由你来设计解决这个需求的方案，那么也许你会设置这样一个数据表用与存储各个用户的状态信息



uid
created
data
max_age


94c55770fdf044a7
1270802787
jtUsername=admin
14400


2c37df64277e4409
1270822787
jtUsername=Joe;jtBooks=8;
14400


…
…
…
…



uid : 用户唯一标识符，区分其它用户 created : 记录产生时间
data : 存放与用户相关的数据 max_age : 记录的有效时间
同样地，PHP设计管理session方案也大致如此，它分别包含了以下信息:
1，session id
用户session唯一标识符，随机生成的一串字符串，具有唯一性，随机性。主要用于区分其它用户的session数据。用户第一次访问web页面的时候，php的session初始化函数调用会分配给当前来访用户一个唯一的ID，也称之为session_id。
2，session data
我们把需要通过session保存的用户状态信息，称为用户session数据，也称为session数据。一般是在当前session生命周期，相应用的$_SESSION数据。
3，session file
PHP 默认将session数据存放在一个文件里。我们把存放session数据的文件称为session文件。它由特殊的php.ini设置 session.save_path指定session文件的存放路径，CentOS5.3操作系统，PHP5.1默认存放在/var/lib/php /session目录中。用户session文件的名称，就是以sess_为前缀，以session_id为结尾命名，比如session  id为vp8lfqnskjvsiilcp1c4l484d3，那么session文件名就是 sess_vp8lfqnskjvsiilcp1c4l484d3
4，session lifetime
我们把初始化session开始，直到注销session这段期间，称为session生命周期，这样有助于我们理解session管理函数。
由此，我们可见:当每个用户访问web, PHP的session初始化函数都会给当前来访用户分配一个唯一的session  ID。并且在session生命周期结束的时候，将用户在此周期产生的session数据持久到session文件中。用户再次访问的时 候，session初始化函数，又会从session文件中读取session数据，开始新的session生命周期。
与session存储相关php.ini设置
1,session.save_handler = file
用于读取/回写session数据的方式，默认是files。它会让PHP的session管理函数使用指定的文本文件存储session数据
2,session.save_path = “/var/lib/php/session”
指 定保存session文件的目录，可以指定到别的目录，但是指定目录必须要有httpd守护进程属主(比如apache或www等)写权限，否则无法回存 session数据。当指定目录不存在时，php session环境初始化函数是不会帮你创建指定目录的，所以需要你手工建立指定目录。
它还可以写成这样session.save_path = “N;/path” 其中N是整数。这样使得不是所有的session文件都保存在同一个目录中，而是分散在不同目录。这对于服务器处理大量session文件是很有帮助的。(注:目录需要自己手工创建)
3,session.auto_start = 0
如果启用该选项，用户的每次请求都会初始化session。我们推荐不启用该设置，最好通过session_start()显示地初始化session。
Session同步数据
一旦调用了session_start()初始化session，就意味着开始了一个session生命周期。也就是宣布了，可以使用相关函数操 作$_SESSION来管理session数据。这个session生命周期产生的数据并没有实时地写入session文件，而是通过$_SESSION 变量寄存在内存中。那么，寄存在内存的数据什么时候会写入到session文件？这也是我们这一小节的主要测试内容。
在进行测试之前，先让我们介绍几个影响session数据的PHP函数、或事件
1，session_start()
函数session_start会初始化session，也标识着session生命周期的开始。要使用session，必须初始化一个session环境。有点类似于OOP概念中调用构造函数构创建对象实例一样。
session 初始化操作，声明一个全局数组$_SESSION，映射寄存在内存的session数据。如果session文件已经存在，并且保存有session数 据，session_start()则会读取session数据，填入$_SESSION中，开始一个新的session生命周期。
2，$_SESSION
它是一个全局变量，类型是Array,映射了session生命周期的session数据，寄存在内存中。在session初始化的时候，从session文件中读取数据，填入该变量中。在session生命周期结束时，将$_SESSION数据写回session文件。
3, session_register()
在 session生命周期内，使用全局变量名称将注全局变量注册到当前session中。所谓注册，就是将变量填入$_SESSION中，值为NULL。它 不会对session文件进行任何IO操作，只是影响$_SESSION变量。注意，它的正确写法是 session_register(‘varname’)，而不是session_register($varname)
4,session_unregister()
与session_register操作正好相反，即在session生命周期,从当前session注销指定变量。同样只影响$_SESSION，并不进行任何IO操作。
5，session_unset()
在 session生命周期，从当前session中注销全部session数据，让$_SESSION成为一个空数组。它与 unset($_SESSION)的区别在于:unset直接删除$_SESSION变量，释放内存资源;另一个区别在 于，session_unset()仅在session生命周期能够操作$_SESSION数组，而unset()则在整个页面(page)生命周期都能 操作$_SESSION数组。session_unset()同样不进行任何IO操作，只影响$_SESSION数组。
6，session_destroy()
如 果说session_start()初始化一个session的话，而它则注销一个session。意味着session生命周期结束了。在 session生命周期结整后，session_register, session_unset,  [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>http协议是WEB服务器与客户端(浏览器)相互通信的协议，它是一种无状态协议。所谓无状态，指的是不会维护http请求数据，http请求是 独立的，不持久的。而越来越复杂的WEB应用，需要保存一些用户状态信息。这时候，Session这种方案应需而生。PHP从4.1开始支持 Session管理。</p>
<p>Session！它是很抽象的一个概念。我们不妨先从与它几个息息相关的有迹可寻的小切入点入手，然后逐渐地认识了解Session！<span id="more-128"></span></p>
<h3>Session存储</h3>
<p>首先，我们为什么需要Session，就是因为我们需要:存储各个用户的状态数据。那么试问，如果由你来设计解决这个需求的方案，那么也许你会设置这样一个数据表用与存储各个用户的状态信息</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="127" valign="top">uid</td>
<td width="107" valign="top">created</td>
<td width="200" valign="top">data</td>
<td width="79" valign="top">max_age</td>
</tr>
<tr>
<td width="127" valign="top">94c55770fdf044a7</td>
<td width="107" valign="top">1270802787</td>
<td width="200" valign="top">jtUsername=admin</td>
<td width="79" valign="top">14400</td>
</tr>
<tr>
<td width="127" valign="top">2c37df64277e4409</td>
<td width="107" valign="top">1270822787</td>
<td width="200" valign="top">jtUsername=Joe;jtBooks=8;</td>
<td width="79" valign="top">14400</td>
</tr>
<tr>
<td width="127" valign="top">…</td>
<td width="107" valign="top">…</td>
<td width="200" valign="top">…</td>
<td width="79" valign="top">…</td>
</tr>
</tbody>
</table>
<p><em>uid : 用户唯一标识符，区分其它用户 created : 记录产生时间<br />
data : 存放与用户相关的数据 max_age : 记录的有效时间</em></p>
<p>同样地，PHP设计管理session方案也大致如此，它分别包含了以下信息:</p>
<p>1，session id<br />
用户session唯一标识符，随机生成的一串字符串，具有唯一性，随机性。主要用于区分其它用户的session数据。用户第一次访问web页面的时候，php的session初始化函数调用会分配给当前来访用户一个唯一的ID，也称之为session_id。<br />
2，session data<br />
我们把需要通过session保存的用户状态信息，称为用户session数据，也称为session数据。一般是在当前session生命周期，相应用的$_SESSION数据。<br />
3，session file<br />
PHP 默认将session数据存放在一个文件里。我们把存放session数据的文件称为session文件。它由特殊的php.ini设置 session.save_path指定session文件的存放路径，CentOS5.3操作系统，PHP5.1默认存放在/var/lib/php /session目录中。用户session文件的名称，就是以sess_为前缀，以session_id为结尾命名，比如session  id为vp8lfqnskjvsiilcp1c4l484d3，那么session文件名就是 sess_vp8lfqnskjvsiilcp1c4l484d3<br />
4，session lifetime<br />
我们把初始化session开始，直到注销session这段期间，称为session生命周期，这样有助于我们理解session管理函数。</p>
<p>由此，我们可见:当每个用户访问web, PHP的session初始化函数都会给当前来访用户分配一个唯一的session  ID。并且在session生命周期结束的时候，将用户在此周期产生的session数据持久到session文件中。用户再次访问的时 候，session初始化函数，又会从session文件中读取session数据，开始新的session生命周期。</p>
<p>与session存储相关php.ini设置<br />
1,session.save_handler = file<br />
用于读取/回写session数据的方式，默认是files。它会让PHP的session管理函数使用指定的文本文件存储session数据<br />
2,session.save_path = “/var/lib/php/session”<br />
指 定保存session文件的目录，可以指定到别的目录，但是指定目录必须要有httpd守护进程属主(比如apache或www等)写权限，否则无法回存 session数据。当指定目录不存在时，php session环境初始化函数是不会帮你创建指定目录的，所以需要你手工建立指定目录。<br />
它还可以写成这样session.save_path = “N;/path” 其中N是整数。这样使得不是所有的session文件都保存在同一个目录中，而是分散在不同目录。这对于服务器处理大量session文件是很有帮助的。(注:目录需要自己手工创建)<br />
3,session.auto_start = 0<br />
如果启用该选项，用户的每次请求都会初始化session。我们推荐不启用该设置，最好通过session_start()显示地初始化session。</p>
<h3>Session同步数据</h3>
<p>一旦调用了session_start()初始化session，就意味着开始了一个session生命周期。也就是宣布了，可以使用相关函数操 作$_SESSION来管理session数据。这个session生命周期产生的数据并没有实时地写入session文件，而是通过$_SESSION 变量寄存在内存中。那么，寄存在内存的数据什么时候会写入到session文件？这也是我们这一小节的主要测试内容。</p>
<p>在进行测试之前，先让我们介绍几个影响session数据的PHP函数、或事件<br />
1，session_start()<br />
函数session_start会初始化session，也标识着session生命周期的开始。要使用session，必须初始化一个session环境。有点类似于OOP概念中调用构造函数构创建对象实例一样。<br />
session 初始化操作，声明一个全局数组$_SESSION，映射寄存在内存的session数据。如果session文件已经存在，并且保存有session数 据，session_start()则会读取session数据，填入$_SESSION中，开始一个新的session生命周期。<br />
2，$_SESSION<br />
它是一个全局变量，类型是Array,映射了session生命周期的session数据，寄存在内存中。在session初始化的时候，从session文件中读取数据，填入该变量中。在session生命周期结束时，将$_SESSION数据写回session文件。<br />
3, session_register()<br />
在 session生命周期内，使用全局变量名称将注全局变量注册到当前session中。所谓注册，就是将变量填入$_SESSION中，值为NULL。它 不会对session文件进行任何IO操作，只是影响$_SESSION变量。注意，它的正确写法是 session_register(‘varname’)，而不是session_register($varname)<br />
4,session_unregister()<br />
与session_register操作正好相反，即在session生命周期,从当前session注销指定变量。同样只影响$_SESSION，并不进行任何IO操作。<br />
5，session_unset()<br />
在 session生命周期，从当前session中注销全部session数据，让$_SESSION成为一个空数组。它与 unset($_SESSION)的区别在于:unset直接删除$_SESSION变量，释放内存资源;另一个区别在 于，session_unset()仅在session生命周期能够操作$_SESSION数组，而unset()则在整个页面(page)生命周期都能 操作$_SESSION数组。session_unset()同样不进行任何IO操作，只影响$_SESSION数组。<br />
6，session_destroy()<br />
如 果说session_start()初始化一个session的话，而它则注销一个session。意味着session生命周期结束了。在 session生命周期结整后，session_register, session_unset,  session_register都将不能操作$_SESSION数组，而$_SESSION数组依然可以被unset()等函数操作。这 时，session意味着是未定义的，而$_SESSION依然是一个全局变量，他们脱离了关映射关系。<br />
通过session_destroy()注销session,除了结束session生命周期外，它还会删除sesion文件，但不会影响当前$_SESSION变量。即它会产生一个IO操作。<br />
7，session_regenerate_id()<br />
调 用它，会给当前用户重新分配一个新的session  id。并且在结束当前页面生命周期的时候，将当前session数据写入session文件。前提是，调用此函数之前，当前session生命周期没有被 终止（参考第9点）。它会产生一个IO操作，创建一个新的session文件，创建新的session文件的是在session结束之前，而不是调用此函 数就立即创建新的session文件。<br />
8,session_commit()<br />
session_commit()函数是 session_write_close()函数的别名。它会结束当前session的生命周期，并且将session数据立即强制写入session文 件。不推荐通过session_commit()来手工写入session数据，因为PHP会在页面生命周期结束的时候，自动结束当前没有终止的 session生命周期。它会产生一个IO写操作<br />
9，end session<br />
结束session，默认是在页面生命周期结束的之 前，PHP会自动结束当前没有终止的session。但是还可以通过session_commit()与session_destroy()二个函数提前 结束session。不管是哪种方式，结束session都会产生IO操作，分别不一样。默认情况，产生一个IO写操作，将当前session数据写回 session文件。session_commit()则是调用该函数那刻，产生一个IO写操作，将session数据写回session文件。而 session_destroy()不一样在于，它不会将数据写回session文件，而是直接删除当前session文件。有趣的是，不管是 session_commit()，还是session_destroy()都不会清空$_SESSION数组，更不会删除$_SESSION数组，只是 所有session_*函数不能再操作session数据，因为当前的session生命周期终止了，即不能操作一个未定义对象。<br />
为了验证以上陈述，我们可以做以下测试<br />
<strong>任务一:观察session初始化与默认结束session的时候，产生的IO操作</strong></p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
//@file test_session_2.php
<a href="http://www.php.net/session_start">session_start</a>();
$pg_uuid = 'ac606826-9620-490b-b850-ea9dbce6cfd5';
//注册全局变量pg_uuid到session,但$_SESSION['pg_uuid']值为NULL,只影响$_SESSION
<a href="http://www.php.net/session_register">session_register</a>('pg_uuid');
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
<a href="http://www.php.net/fopen">fopen</a>(__FILE__, "r");
?&gt;</pre>
</div>
</pre>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
Process 21819 attached - interrupt to quit
...
st_mode=S_IFREG|0644, st_size=72, ...}) = 0
open("/var/www/html/test_session.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=72, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "&lt;p;?php\n//@file test_session.php\ns"..., 8192) = 72
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
gettimeofday({1270906664, 11602}, NULL) = 0
open("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
time(NULL)                              = 1270906664
open("/var/www/html/test_session.php", O_RDONLY) = 18
fstat64(18, {st_mode=S_IFREG|0644, st_size=72, ...}) = 0
lseek(18, 0, SEEK_CUR)                  = 0
close(18)                               = 0
chdir("/var/lib/php/session")           = 0
pwrite64(17, "", 0, 0)                  = 0
close(17)                               = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
writev(16, [{"HTTP/1.1 200 OK\r\nDate: Sat, 10 A"..., 385}], 1) = 385
write(12, "192.168.0.98 - - [10/Apr/2010:21"..., 207) = 207
shutdown(16, 1 /* send */)              = 0
epoll_wait(15,</pre>
<p>蓝色加粗，通过系统内核函数open调用打开session文件，这是由session_start()产生的调用，注意这里并没有产生读文件操 作。红色部分，将一个空字符串写入session文件。由此可见session初始化在页面生命周期开始之时，手工调用session_start可以初 始化session文件，而在页面生命周期结束之时，会自动地注销session，结束当前session生命周期，同时在此周期产生的session数 据写回session文件，我们把这种方式结束的session，称为session默认结束。</p>
<p><strong>任务2.观察session_register()查看它是否会产生磁盘操作，还是只操作$_SESSION。</strong></p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
//@file test_session_2.php
<a href="http://www.php.net/session_start">session_start</a>();
$pg_uuid = 'ac606826-9620-490b-b850-ea9dbce6cfd5';
<a href="http://www.php.net/session_register">session_register</a>('pg_uuid');	//注册全局变量pg_uuid到session,但值为NULL,只影响$_SESSION
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
<a href="http://www.php.net/fopen">fopen</a>(__FILE__, "r");
?&gt;</pre>
</div>
</pre>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
Process 21819 attached - interrupt to quit
...
open("/var/www/html/test_session_2.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=148, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "&lt;?php\nsession_start();\n$pg_uuid "..., 8192) = 148
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
open("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
time(NULL)                              = 1270907613
open("/var/www/html/test_session_2.php", O_RDONLY) = 18
fstat64(18, {st_mode=S_IFREG|0644, st_size=148, ...}) = 0
lseek(18, 0, SEEK_CUR)                  = 0
close(18)                               = 0
chdir("/var/lib/php/session")           = 0
pwrite64(17, "pg_uuid|N;", 10, 0)       = 10
close(17)                               = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
writev(16, [{"HTTP/1.1 200 OK\r\nDate: Sat, 10 A"..., 328}, {"array(1) {\n  [\"pg_uuid\"]=&gt;\n  NUL"..., 36}], 2) = 364
write(12, "192.168.0.98 - - [10/Apr/2010:21"..., 210) = 210
shutdown(16, 1 /* send */)              = 0
epoll_wait(15,
</pre>
<p>通过上面的观察，蓝色部分还是由session初始化(session_start)产生，注意这里依然没读文件操作，这是因为session文件 为空。红色部分，依然是默认结束session产生的文件写操作(pwrite)。由此，我们可以知道session_register()不会对 session文件操作，即不会把$_SESSION中的数据写回session文件,它没有产生任何IO操作。而只在session生命周期是影响当 前$_SESSION变量，即$_SESSION[‘pg_uuid’] = NULL。所以，推荐使用$_SESSION[‘pg_uuid’] =  $pg_uuid;</p>
<p><strong>任务3.观察session_destroy()与session_unset()的区别</strong></p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
<a href="http://www.php.net/session_start">session_start</a>();
echo "&lt;br/&gt;---1--&lt;br/&gt;";
$pg_uid = 1;
//$_SESSION['pg_uid'];		//该行会报一个Notice消息,即没有初始化该变量
$_SESSION['pg_name'] = 'boys';	//填入到$_SESSION变量，但不立即写入session文件,值为boys
$pg_sex = 1;
$pg_theme = 'default';
<a href="http://www.php.net/session_register">session_register</a>('pg_sex');	//填入到$_SESSION变量,但不立即写入session文件,值为NULL
<a href="http://www.php.net/session_register">session_register</a>('pg_theme');	//填入到$_SESSION变量,但不立即写入session文件,值为NULL
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
 
//--
echo "&lt;br/&gt;---2--&lt;br/&gt;";
<a href="http://www.php.net/unset">unset</a>($_SESSION['pg_theme']);	//从$_SESSION清除该元素,不立即同步到session文件
<a href="http://www.php.net/unset">unset</a>($_SESSION['pg_name']);	//从$_SESSION清除该元素,不立即同步到session文件
<a href="http://www.php.net/session_unregister">session_unregister</a>('pg_sex');	//从$_SESSION清除该元素,不立即同步到session文件
<a href="http://www.php.net/session_unregister">session_unregister</a>('pg_uid');	//从$_SESSION清除该元素,不立即同步到session文件
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
 
echo "&lt;br/&gt;---3--&lt;br/&gt;";
$_SESSION['pg_members'] = 5;	//填入$_SESSION数组，但不立即同步到session文件,值为5
$pg_boy = 6;
<a href="http://www.php.net/session_register">session_register</a>('pg_boy');	//填入$_SESSION数组，但不立即同步到session文件,值为NULL
<a href="http://www.php.net/session_unset">session_unset</a>($_SESSION);	//清空$_SESSION
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
 
echo "&lt;br/&gt;---4--&lt;br/&gt;";
$_SESSION['pg_boss'] = 3;	//填入$_SESSION数组,但不立即同步到session文件,值为3
$pg_girls = 6;
<a href="http://www.php.net/session_register">session_register</a>('pg_girls');	//填入$_session数组,但不立即同步到session文件,值为NULL
<a href="http://www.php.net/session_destroy">session_destroy</a>();		//注销session_destroy
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
 
echo "&lt;br/&gt;---5---&lt;br/&gt;";
<a href="http://www.php.net/session_unregister">session_unregister</a>('pg_boss');	//pg_boss不会被清除，还为NULL
<a href="http://www.php.net/session_unset">session_unset</a>();		//不会清空$_SESSION数组,因为session已被session_destroy注销
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
 
<a href="http://www.php.net/fopen">fopen</a>(__FILE__, "r");
 
//@这里是页面析构的时候-- 本应该将$_SESSION数据同步到session文件, 真的吗???
//@事实,没有发生任何IO操作,即没有将$_SESSION数据回写,怎么回事???
//@因为被session_destroy()消毁了session...
?&gt;</pre>
</div>
</pre>
<pre>程序输出:
---1--
array(3) { ["pg_name"]=&gt; string(4) "boys" ["pg_sex"]=&gt; NULL ["pg_theme"]=&gt; NULL }
---2--
array(0) { }
---3--
array(0) { }
---4--
array(2) { ["pg_boss"]=&gt; int(3) ["pg_girls"]=&gt; NULL }
---5---
array(2) { ["pg_boss"]=&gt; int(3) ["pg_girls"]=&gt; NULL }</pre>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
Process 21819 attached - interrupt to quit
...
open("/var/www/html/test_session_3.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=706, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "&lt;?php\nsession_start();\necho \"&lt;br"..., 8192) = 706
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
open("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=10, ...}) = 0
pread64(17, "pg_uuid|N;", 10, 0)        = 10
close(17)                               = 0
unlink("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5") = 0
time(NULL)                              = 1270910665
open("/var/www/html/test_session_3.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=706, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
close(17)                               = 0
chdir("/var/lib/php/session")           = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
...
write(12, "192.168.0.98 - - [10/Apr/2010:22"..., 211) = 211
shutdown(16, 1 /* send */)              = 0
</pre>
<p>蓝色部分是我们熟悉的session初始化的时候产生的open系统内核调用。绿色部分，是一个IO读操作，因为上一次访问页面的时候，产生了 session数据，所以这一次会将上次的session填入$_SESSION中。红色部分，可以看出，这里调用unlink删除session文件， 而且后面(页面生命周期结束时),一直没有看到前两例看到的任何与session文件有关的IO写操作，即没有将$_SESSION中的数据写回 session文件。我们也没有在session.save_path找到相应的session文件</p>
<pre>
<div>
<pre>[root@localhost html]# ls /var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5
<strong>ls</strong>: /var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5: No such <strong>file</strong> or directory</pre>
</div>
</pre>
<p>注:虽然删除了session文件，但用户再次访问web的时候，并不会给用户重新分配一个新的session id，而是依然用该session id，并且会重新创建文件名相同的session文件，即sess_SESSION-ID</p>
<p>任务4:测试并观察session_regenerate_id行为，以及$_SESSION的变化</p>
<div>
<pre><strong>&lt;?php</strong>
<a href="http://www.php.net/session_start">session_start</a>();
$_SESSION['pfid'] = 123;
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
<a href="http://www.php.net/session_regenerate_id">session_regenerate_id</a>();
<a href="http://www.php.net/var_dump">var_dump</a>($_SESSION);
<a href="http://www.php.net/fopen">fopen</a>(__FILE__, "r");
?&gt;</pre>
</div>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
Process 22641 attached - interrupt to quit
...
open("/var/www/html/test_session_4.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=141, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "&lt;?php\nsession_start();\n$_SESSION"..., 8192) = 141
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
open("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=11, ...}) = 0
pread64(17, "pfid|i:123;", 11, 0)       = 11
gettimeofday({1270915896, 122016}, NULL) = 0
time(NULL)                              = 1270915896
open("/var/www/html/test_session_4.php", O_RDONLY) = 18
fstat64(18, {st_mode=S_IFREG|0644, st_size=141, ...}) = 0
lseek(18, 0, SEEK_CUR)                  = 0
close(18)                               = 0
chdir("/var/lib/php/session")           = 0
close(17)                               = 0
open("/var/lib/php/session/sess_qoa6knu9fg77un8le99o1vk1c7", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
pwrite64(17, "pfid|i:123;", 11, 0)      = 11
close(17)                               = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
writev(16, [{"HTTP/1.1 200 OK\r\nDate: Sat, 10 A"..., 386}, {"array(1) {\n  [\"pfid\"]=&gt;\n  int(12"..., 75}], 2) = 461
write(12, "192.168.0.98 - - [11/Apr/2010:00"..., 210) = 210
shutdown(16, 1 /* send */)              = 0
</pre>
<p>请注意观察，蓝色部分，  session初始化打开的session文件是sess_4j38nv7l1fq1bj6n80l6g9cum5,这也验证了上一例的陈述。而绿色加粗 部分，而这次打开的是新session文件sess_qoa6knu9fg77un8le99o1vk1c7，并且将session数据写入到了新的 session文件中。值得注意的是，打开新文件的时候，是发生在fopen(__FILE__,  ‘r’)之后，在回写session数据到session文件之前open的新session文件。可 见，session_regenerate_id（）会给当前用户重新分配一个新的session  id，并将当前session数据写入新的session文件，另外不会删除旧的session文件。通过文件列表，也验证了，正是如此</p>
<pre>[root@localhost html]# ls -lt /var/lib/php/session/
-rw------- 1 apache apache 11 Apr 11 00:11 sess_qoa6knu9fg77un8le99o1vk1c7
-rw------- 1 apache apache 11 Apr 11 00:08 sess_4j38nv7l1fq1bj6n80l6g9cum5
-rw------- 1 apache apache  0 Apr 10 17:37 sess_ktj0giniplqf51nravl1fsga72</pre>
<p><strong>任务5.:测试并观察session_commit()是否会像session_destroy注销session，什么时候进行IO写操作</strong></p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
<a href="http://www.php.net/session_start">session_start</a>();
echo "-----&lt;br /&gt;---";
<a href="http://www.php.net/var_dump">var_dump</a>($SESSION);
 
echo "&lt;br /&gt;-----&lt;br /&gt;---";
$SESSION['pfguest'] = 'guest';
<a href="http://www.php.net/session_commit">session_commit</a>();
<a href="http://www.php.net/var_dump">var_dump</a>($SESSION);
 
echo "&lt;br /&gt;-----&lt;br /&gt;---";
<a href="http://www.php.net/session_unset">session_unset</a>();
<a href="http://www.php.net/var_dump">var_dump</a>($SESSION);
 
<a href="http://www.php.net/fopen">fopen</a>(__FILE__, 'r');
?&gt;</pre>
</div>
</pre>
<pre>程序输出如下:
-----1---array(1) { ["pfid"]=&gt; int(123) }
-----2---array(2) { ["pfid"]=&gt; int(123) ["pfguest"]=&gt; string(5) "guest" }
-----3---array(2) { ["pfid"]=&gt; int(123) ["pfguest"]=&gt; string(5) "guest" }</pre>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
Process 22641 attached - interrupt to quit
...
open("/var/www/html/test_session_5.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=246, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "&lt;?php\nsession_start();\necho \"---"..., 8192) = 246
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
open("/var/lib/php/session/sess_qoa6knu9fg77un8le99o1vk1c7", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=11, ...}) = 0
pread64(17, "pfid|i:123;", 11, 0)       = 11
pwrite64(17, "pfid|i:123;pfguest|s:5:\"guest\";", 31, 0) = 31
close(17)                               = 0
time(NULL)                              = 1270927098
open("/var/www/html/test_session_5.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=246, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
close(17)                               = 0
chdir("/var/lib/php/session")           = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
writev(16, [{"HTTP/1.1 200 OK\r\nDate: Sat, 10 A"..., 329}, {"-----1---array(1) {\n  [\"pfid\"]=&gt;"..., 222}], 2) = 551
write(12, "192.168.0.98 - - [11/Apr/2010:03"..., 211) = 211
shutdown(16, 1 /* send */)              = 0
</pre>
<p>观察测试结果,蓝色部分照旧是session初始化的时候产生的系统内核open调用,接着绿色部分是一个IO读操作，即读取session文件中 的数据，由第一个var_dump($_SESSION)输出。随后，往session加入新的一条已定义了的session记录，并且通过 session_commit()将记录写回去。红色部分就是由session_commit产生的一次IO写操作。之 后，session_unset()并没有生效，同时，我们也没有在页面生命周期结束的时候看到任何与session文件有关的IO写操作。这也正说明 了,session_commit()调用的当下，就会将session数据写回session文件，并且会像session_destroy一样注销 session，但与session_destroy不同的时，session_commit不会删除session文件，而且会将当前的session 数据写回session文件。我们可以查看，调用session_commit之后，session文件还是依然存在的</p>
<pre>[root@localhost html]# ls -lt /var/lib/php/session
-rw------- 1 apache apache 31 Apr 11 03:18 sess_qoa6knu9fg77un8le99o1vk1c7
-rw------- 1 apache apache 11 Apr 11 00:08 sess_4j38nv7l1fq1bj6n80l6g9cum5
…</pre>
<h3>总结</h3>
<p>1,用户注销web应用系统，最好的调用方式依次是session_unset(); session_destroy(); unset($_SESSION);</p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
<strong>function</strong> user_sigout() {
  <strong>global</strong> $user;
  sys_event_register('user_sigout', $user);
 
  <a href="http://www.php.net/session_unset">session_unset</a>();			//清空session
  <a href="http://www.php.net/session_destroy">session_destroy</a>();			//删除session文件
  if (<a href="http://www.php.net/isset">isset</a>($_SESSION)) {
    <a href="http://www.php.net/unset">unset</a>($_SESSIONI);	//注销$_SESSION
  }
  return TRUE;
}
?&gt;</pre>
</div>
</pre>
<p>2,尽量将键与值填入$_SESSION，而不推荐使用session_register()。同样，尽量使用unset($_SESSION[‘var’])，而不使用session_unregister()。<br />
3,对于可能产生大量session的WEB应用，推荐使用的session.save_path的格式是session.save_path=”N:/path”。注意:这些目录需要手工创建，并且有httpd守护进程属主写权限。这样做可以获得更好的性能<br />
4,如果调用了session_regenerate_id()给用户分配了新的session id。该函数并不会主动删除旧的session文件，需要定时清理旧的session文件，这样更优化。<br />
5,尽量不要使用session_commit()提交sessioin数据，因为它同时会结束当前session，PHP默认会在页面生命周期的时候提交session数据到session文件</p>
<h2>PHP5 Session 浅析II</h2>
<div>
<p>我们在&lt;&lt;<a title="php5 session 浅析I" href="http://www.perfgeeks.com/?p=183" target="_self">PHP5 Session 浅析I</a>&gt;&gt;中探讨了session存储，session同步数据以及session数据编码。我们将在这里继续探讨一下session id传递与session回收。</p>
<h3>Session ID传递</h3>
<p>session终究是因为管理用户状态信息才存在的。我们曾探讨过session id的意义：每个来访问用户都会被分配一个唯一的session  id，用于区分其它用户的session数据。换句话说,session  id是用户表明身份的一种标识，就像入场券一样。用户一旦从被分配了session id之后的每次访问(http请求)都会携带这个session  id给服务端，用于加载该用户的session数据。那么，通过什么方式传给服务端？这是我们这节探讨的内容。</p>
<p>用户端与服务端的web通信协议是http。而PHP通过http取得用户数据惯用的三种方法分别是:POST方法、GET方法还有Cookie。 而PHP默认传递方法正是Cookie,也是最佳方法。只有在客户端不支持Cookie的时候(浏览器禁用了Cookie功能)才会通过GET方法来传递 session_id，即通过在URL的query_string部分传递session id。</p>
<p>确定了传递方法，我们还有必要清楚一下session  id的传递过程。用户通过浏览器访问网页，将URL输入地址栏回车，浏览器发出请求，在调用sockect  send之前浏览器引擎会搜索有效的Cookies记录封装在http请求头的Cookie字段,一同发送出去。服务端器接收到请求后，交给PHP处理。 这时,session初始化函数如果在$_COOKIE中没有找到以session_name()作为键值存储的生素(值为session  id)，则会以为用户是第一次访问web。作为第一次访问的用户，session初始化函数总会随机生成一个session_id并且通过 setcookie()函数调用将新生成的session_id以”sesseson_name =  session_id”的格式填入http响应头Set-Cookie字段，发送给客户端（这样接下来的请求，http请求头Cookie字段都会携带该 Cookie记录给web服务器）。如果初始化函数发现用户端Cookies中已定义了存在$_COOKIE[‘sess_name’]，则会加载 与$_COOKIE[‘sess_name’]相对应的session文件($_COOKIE[‘sess_name’]就是session  ID)。如果用户Cookie记录过期，则会被浏览器删除。之后的下一次请求，服务器会以为用户又是第一次访问,如此循环。</p>
<p><em>让我们通过测与来验证以上的陈述</em></p>
<div>
<pre><strong>&lt;?php</strong>
//@file p1.php
<a href="http://www.php.net/session_start">session_start</a>();
?&gt;</pre>
</div>
<p>通过截取到的http数据包如下<br />
#<br />
T 192.168.0.98:2290 -&lt; 192.168.0.8:8080 [AP]<br />
GET /a.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1<br />
; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Accept: application/xml,application/xhtml+<br />
xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-Language: zh-CN,zh;<br />
q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3….<br />
##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2290 [AP]<br />
HTTP/1.1 200 OK..Date: Mon, 12 Apr 2010 08:25:11 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Set-Cookie<br />
: PHPSESSID=bk7655dqrm5m884c9nitfi7j00; path=/..Expires: Thu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cach<br />
e, must-revalidate, post-check=0, pre-check=0..Pragma: no-cache..Content-Length: 0..Connection: close..Content-Type: tex<br />
t/html; charset=UTF-8….<br />
##</p>
<p>第一次访问/a.php的时候,请求包里面没有设置任何Cookie，所以这里的Cookie字段为空。当然服务器php也就得不到 的$_COOKIE[‘PHPSESSID’](即session  id为空)。如此，服务器会以为用户是第一次访问web。所以session初始化的时候，会给用户分配一个唯一的session_id并且以 Cookie的方法传回给了用户端。</p>
<p>我们再来观察第二次请求与响应,会有哪些变化:<br />
#<br />
T 192.168.0.98:2314 -&lt; 192.168.0.8:8080 [AP]<br />
GET /a.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1<br />
; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Cache-Control: max-age=0..Accept: applicat<br />
ion/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..<br />
Accept-Language: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3..Cookie: PHPSESSID=bk7655dqrm5m884c9nitfi7j00..<br />
..<br />
##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2314 [AP]<br />
HTTP/1.1 200 OK..Date: Mon, 12 Apr 2010 08:32:13 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Expires: T<br />
hu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0..Pragma: no-<br />
cache..Content-Length: 0..Connection: close..Content-Type: text/html; charset=UTF-8….</p>
<p>##<br />
首先，我们观察http请求，加红色部分是第一次http请求头没有出现的内容。我们可以看到，该Cookie正是第一次访问,服务端 通过Set-Cookie要求浏览器设置的Cookie。它们是一样的,即session_id为 bk7655dqrm5m884c9nitfi7j00。然后，我们再观察这次的http响应，明显没有再要求用户端设置键为 session_name()的Cookie了。</p>
<p><em>我们再来测试伪造一个session_id发送给服务,观察服务端响应。我们写一个测试脚本，如下:</em></p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
$host = '192.168.0.8';
$port = 8080;
$path = '/p1.php';
$sid = "PHPSESSID=dk7655dqrm5m884c9nitfi7j00";
 
$fp = <a href="http://www.php.net/fsockopen">fsockopen</a>($host, $port, $error_no, $error_desc, 30);
if ($fp) {
  <a href="http://www.php.net/fputs">fputs</a>($fp, "GET {$path} HTTTP/1.1\r\n");
  <a href="http://www.php.net/fputs">fputs</a>($fp, "Host: {$host}\r\n");
  <a href="http://www.php.net/fputs">fputs</a>($fp, "Cookie: {$sid}\r\n");
  <a href="http://www.php.net/fputs">fputs</a>($fp, "Connection: close\r\n\r\n");
  while (!<a href="http://www.php.net/feof">feof</a>($fp)) {
    $d .= <a href="http://www.php.net/fgets">fgets</a>($fp, 4096);
  }
  <a href="http://www.php.net/fclose">fclose</a>();
  echo $d;
 }
?&gt;</pre>
</div>
</pre>
<p>抓到的http请求、响应数据包如下:<br />
#<br />
T 192.168.0.98:2400 -&lt; 192.168.0.8:8080 [AP]<br />
GET /p1.php HTTTP/1.1..<br />
Host: 192.168.0.8..Cookie: <strong><em>PHPSESSID=dk7655dqrm5m884c9nitfi7j00..</em></strong>Connection: close….<br />
##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2400 [AP]<br />
HTTP/1.1 200 OK..Date: Mon, 12 Apr 2010 09:03:09 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Expires: T<br />
hu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0..Pragma: no-<br />
cache..Content-Length: 11..Connection: close..Content-Type: text/html; charset=UTF-8….hello world<br />
##<br />
上 面的session_id是用户端伪造的一个值,它并不实际存在。收到这样的请求，服务端并没有检查，而是以这个session_id创建了相应的 session文件。并且，从httpd响应头部信息来看，并没给用户端分配session  id(没有Set-Cookie)。由此,我们可以推断:只要http请求头部包含了以session_name()作为键值的Cookie,那么服务端 就不认为用户是第一次访问web,亦不会给客户端分配session_id。否则，分配新的session_id,并通过Set-Cookie要求浏览器 创建该Cookie.<br />
<em>我们再来观察一下，通过session_regenerate_id()函数给用户分配一个新的session_id的情况</em></p>
<div>
<pre><strong>&lt;?php</strong>
//@file: p2.php
<a href="http://www.php.net/session_start">session_start</a>();
<a href="http://www.php.net/session_regenerate_id">session_regenerate_id</a>();
?&gt;</pre>
</div>
<p>抓取到的http数据包如下<br />
####<br />
T 192.168.0.98:2763 -&lt; 192.168.0.8:8080 [AP]<br />
GET /p2.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.<br />
1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Cache-Control: max-age=0..Accept: applica<br />
tion/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch.<br />
.Accept-Language: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3..Cookie: PHPSESSID=bk7655dqrm5m884c9nitfi7j00.<br />
… ##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2763 [AP]<br />
HTTP/1.1 200 OK..Date: Mon, 12 Apr 2010 11:39:10 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Expires: T<br />
hu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0..Pragma: no-<br />
cache..Set-Cookie: PHPSESSID=f7q6jfdug4ekfsjhop6jftgna7; path=/..Content-Length: 0..Connection: close..Content-Type: tex<br />
t/html; charset=UTF-8…. ##<br />
上 面可以观察得到,http请求头Cookie部分带了session  id，并且这个session_id还是用户第一次访问web时被分配得到的。这一次，http响应头跟第二次示例http响应有些不一样,而是像第一次 访问那样通过Set-Cookie去要求用户端浏览器更新用户的session  id。这意味着:session_genrate_id()给用户端重新生成的session id也是通过Cookie的方法传递。</p>
<p><a href="http://www.perfgeeks.com/wp-content/uploads/2010/04/php_cookie_session.jpg"><img title="php_cookie_session" src="http://222.73.211.215/pfstatic/wp-content/uploads/2010/04/php_cookie_session.jpg" alt="" width="542" height="393" /></a></p>
<p>上图正好说明了这个过程:<br />
1，User01和User02第一次去访问/p1.php，分别被分配了一个session id。<br />
2，User01和User02第二次访问web，都会使用由/p1.php分配的session_id<br />
3，User01 因为访问了/p2.php,脚本/p2.php中的session_regenerate_id()给用户User01重新分配了一个新 session_id，从用户User01第4次访问的session_id就可以看得出来，与前面几几次的session_id不同了。<br />
4，User02因为没有访问/p2.php，也就没有被服务端重新分配session id，一下沿用着上一次分配的session_id<br />
<strong>与session id传递的有关的php.ini设置</strong><br />
1,session.use_cookie = 1<br />
是否采用Cookie方法传递session id值。默认是1，表示启用。<br />
2,session.name = PHPSESSID<br />
不 管是Cookie传递sessioin_id，还是GET方法传递session_id，都需要使用键值。他们的格式分别是Cookie:   sess_name=session_id;和/path.php?sess_name=session_id，其中sess_name就是由这里指定 的。<br />
3,session.use_only_cookies = 0<br />
表示只使用Cookie 的方法传递session  id。我们说过，传递cookie的方法，除了cookie，还有GET方法，GET方法是不安全的方法。在用户端禁用了cookie的时候，会采用 GET方法传递session_id，可以通过这个设置尽用GET方法传递session_id。<br />
4，session.cookie_lifetime = 0, session.cookie_path = / 以及session.cookie_domain =<br />
如 果使用Cookie方法传递session_id的话，这里分别指定了cookie有效域、目录和时间。分别对应setcookie()函数的形 参$expire、$path和$domain。其中cookie_lifetime=0表示直到关闭浏览器才删除Cookie。还可以使用 session_set_cookie_params()函数修改这些值。<br />
5,session_name([string $name])<br />
获 取或更新session_name。如果传了name，则表示不使用默认的名称PHPSESSID(由session.name)指定，否则获取当前 session_name。注意:如果设置session_name，则必须在session_start()之前调用才生效。<br />
6,session_id([string $id])<br />
与session_name()类似，但它是读取或者设置session_id的方法。同样，设置session_id的话，必须在session_start()之前调用才有效。<br />
7,session_set_cookie_params()和session_get_cookie_params()<br />
通 过session_set_cookie_params()可以重新设定session.cookie_lifetime,  session.cookie_path以及session.cookie_domain这三个php.ini设置。而 session_get_cookie_params()则是获取这些设定的值。</p>
<h3>Session回收</h3>
<p>通过上文几节介绍，我们知道session数据存放在服务端指定的session.save_path目录中，同时会在用户端存放一条Cookie用以记录分配给用户的session id。所以，session数据失效分服务端和客户端，要删除(回收)的对象也很清楚:<br />
1，服务端:删除过期的session文件，启动PHP GC回收。<br />
2，用户端:使存储了过期session_id的用户端Cookie记录过期。通过将Cookie的Expire设置为负值，要求客户端删除Cookie。<br />
<strong>服务端:删除过期的session文件</strong><br />
PHP   GC进程被启动以后，则会扫描session.save_path，找出过期的session，并删除该session文件。所谓，过期的 session，是指操作系统当前时间与session文件最后访问时间之差大于session.gc_maxlifetime的话，该session认 为是过期了。注意:有时候，你会发现，即便是文件过期了，有可能也没有被及时地删除掉。这是因为，每次session初始化的时候，并不会都启动PHP  GC进程的，启动GC进程会大大降低php的运行效率。所有一个启动概率，这个概率由php.ini设定session.gc_probability /  session.gc_divisor二个设置决定，默认概率是1%(1/1000)。这意味着，每1000次用户请求中,会启动1次PHP  GC回收session文件。比如，我们下面看到的，过期的session文件依然存在:</p>
<pre># date;find /var/lib/php/session -type f -atime -1440 -print |xargs ls -lt
<strong>Tue Apr 13 10:10:37 CST 2010</strong>
-rw------- 1 apache apache  0 <strong>Apr 12 20:01</strong> /var/lib/php/session/sess_5tlaq5a8im3ob1bikn62motpv7
-rw------- 1 apache apache  0 <strong>Apr 12 19:39</strong> /var/lib/php/session/sess_f7q6jfdug4ekfsjhop6jftgna7
-rw------- 1 apache apache  0 <strong>Apr 12 17:03</strong> /var/lib/php/session/sess_dk7655dqrm5m884c9nitfi7j00</pre>
<p>我们可以通过编辑设置，来验证启动php session的GC机制</p>
<div>
<pre><strong>&lt;?php</strong>
//@file session_gc.php
<a href="http://www.php.net/ini_set">ini_set</a>("session.gc_probability", 100);
<a href="http://www.php.net/ini_set">ini_set</a>("session.gc_divisor", 100);
<a href="http://www.php.net/ini_set">ini_set</a>("session.gc_maxlifetime", 1440);
 
<a href="http://www.php.net/session_start">session_start</a>();
?&gt;</pre>
</div>
<pre>[root@localhost ~]# strace -p `cat /var/run/httpd.pid`
open("/var/www/html/session_gc.php", O_RDONLY) = 17
fstat64(17, {st_mode=S_IFREG|0644, st_size=144, ...}) = 0
lseek(17, 0, SEEK_CUR)                  = 0
brk(0x8d35000)                          = 0x8d35000
read(17, "&lt;?php\nini_set(\"session.gc_probab"..., 8192) = 144
read(17, "", 8192)                      = 0
read(17, "", 8192)                      = 0
close(17)                               = 0
open("/var/lib/php/session/sess_5tlaq5a8im3ob1bikn62motpv7", O_RDWR|O_CREAT, 0600) = 17
flock(17, LOCK_EX)                      = 0
fcntl64(17, F_SETFD, FD_CLOEXEC)        = 0
fstat64(17, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
open("/var/lib/php/session", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 18
fcntl64(18, F_SETFD, FD_CLOEXEC)        = 0
time(NULL)                              = 1271125492
getdents(18, /* 13 entries */, 32768)   = 516
stat64("/var/lib/php/session/sess_bk7655dqrm5m884c9nitfi7j00", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_bk7655dqrm5m884c9nitfi7j00") = 0
stat64("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5", {st_mode=S_IFREG|0600, st_size=11, ...}) = 0
unlink("/var/lib/php/session/sess_4j38nv7l1fq1bj6n80l6g9cum5") = 0
stat64("/var/lib/php/session/sess_n660qmcl38solbmp7vkhafqg17", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_n660qmcl38solbmp7vkhafqg17") = 0
stat64("/var/lib/php/session/sess_5tlaq5a8im3ob1bikn62motpv7", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_5tlaq5a8im3ob1bikn62motpv7") = 0
stat64("/var/lib/php/session/sess_qoa6knu9fg77un8le99o1vk1c7", {st_mode=S_IFREG|0600, st_size=31, ...}) = 0
unlink("/var/lib/php/session/sess_qoa6knu9fg77un8le99o1vk1c7") = 0
stat64("/var/lib/php/session/sess_dutbc682k3h4cgho2sgugc0id4", {st_mode=S_IFREG|0600, st_size=23, ...}) = 0
unlink("/var/lib/php/session/sess_dutbc682k3h4cgho2sgugc0id4") = 0
stat64("/var/lib/php/session/sess_vp8lfqnskjvsiilcp1c4l484d3", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_vp8lfqnskjvsiilcp1c4l484d3") = 0
stat64("/var/lib/php/session/sess_dk7655dqrm5m884c9nitfi7j00", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_dk7655dqrm5m884c9nitfi7j00") = 0
stat64("/var/lib/php/session/sess_f7q6jfdug4ekfsjhop6jftgna7", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
unlink("/var/lib/php/session/sess_f7q6jfdug4ekfsjhop6jftgna7") = 0
getdents(18, /* 0 entries */, 32768)    = 0
close(18)                               = 0
chdir("/var/lib/php/session")           = 0
pwrite64(17, "", 0, 0)                  = 0
close(17)                               = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
writev(16, [{"HTTP/1.1 200 OK\r\nDate: Tue, 13 A"..., 327}], 1) = 327
write(12, "192.168.0.98 - - [13/Apr/2010:10"..., 205) = 205
shutdown(16, 1 /* send */)              = 0</pre>
<p>从上面蓝色部分可以看出,通过用stat64检查session文件的状态,如果发现过期了,则会通过调用系统内核函数ulink()删除过期的 session文件。可见,session初始化的时候会启动GC,  GC会扫描session.save_path中的所有session文件,查看他们状态并且将过期的文件删除。正因为如此，所以默认设置启动的概率是 1/1000。</p>
<p><strong>客户端:删除过期session id的cookie记录</strong><br />
如果用户发现session已经过期，但是服 务端的GC还没有启动，服务端可以手通过手工代码setcookie的方式要求用户端浏览器删除键值为session_name()的Cookie记录。 这样，下回访问的时候，浏览器以为用户是第一次访问，并且重新给访问用户分配一个新的session_id。较好的做法类似这样:</p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
//@file session_destroy.php
<a href="http://www.php.net/session_start">session_start</a>();
 
$sess_name = <a href="http://www.php.net/session_name">session_name</a>();
$sess_id = <a href="http://www.php.net/session_id">session_id</a>();
<a href="http://www.php.net/list">list</a>(, $path, $domain, ,) = <a href="http://www.php.net/session_get_cookie_params">session_get_cookie_params</a>();
if ($sess_name &amp;amp;&amp;amp; <a href="http://www.php.net/isset">isset</a>($_COOKIE[$sess_name])) {
  <a href="http://www.php.net/setcookie">setcookie</a>($sess_name, '', -1, $path, $domain);
  if ($sess_id) {
    <a href="http://www.php.net/session_destroy">session_destroy</a>();
  }
 }
?&gt;</pre>
</div>
</pre>
<p>抓取的http数据包如下:<br />
#<br />
T 192.168.0.98:2638 -&lt; 192.168.0.8:8080 [AP]<br />
GET /session_destroy.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U;<br />
Windows NT 5.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Accept: application/xml,appl<br />
ication/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-Langu<br />
age: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3..Cookie: PHPSESSID=rjdtgvmueggplgqno66qlfket1....<br />
##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2638 [AP]<br />
HTTP/1.1 200 OK..Date: Tue, 13 Apr 2010 07:08:24 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Expires: T<br />
hu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0..Pragma: no-<br />
cache..<strong>Set-Cookie: PHPSESSID=deleted; expires=Mon, 13-Apr-2009 07:08:23 GMT..</strong>Content-Length: 222..Connection: close..Con<br />
tent-Type: text/html; charset=UTF-8....<br />
##<br />
T 192.168.0.98:2642 -&lt; 192.168.0.8:8080 [AP]<br />
GET /p1.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.<br />
1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Accept: application/xml,application/xhtml<br />
+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-Language: zh-CN,zh<br />
;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3....<br />
##<br />
T 192.168.0.8:8080 -&lt; 192.168.0.98:2642 [AP]<br />
HTTP/1.1 200 OK..Date: Tue, 13 Apr 2010 07:09:15 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Set-Cookie<br />
: PHPSESSID=lbmk3sc5a88e9cjuekr0aa9pc3; path=/..Expires: Thu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cach<br />
e, must-revalidate, post-check=0, pre-check=0..Pragma: no-cache..Content-Length: 11..Connection: close..Content-Type: te<br />
xt/html; charset=UTF-8....hello world<br />
##<br />
上 面观察可以知道,通过访问/session_destroy.php,它要求客户端将session_id的Cookie记录删除。而接下来访问 /p1.php的时候，http请求头没有通过Cookie将用户的session  id带给服务器(因为刚被要求删除)。而第二次请求/p1.php的http响应里头可以看到,服务端又给用户重新分配了一个新的session  id,而且不会继续使用过去的session数据。</p>
<p>与session回收相关的php.ini设置:<br />
1, session.gc_probability和session.gc_divisor<br />
由 这二个函数决定了启用GC的概率,默认是1/1000。也就是说,每一千次用户请求中有一次会启动GC回收session。启动GC进程不宜过于频繁。上 面的例子,我们可以看到,它会每次检查session.save_path目录下每个文件的状态。这样会降低php的执行效率。<br />
2, session.gc_maxlifetime = 1440<br />
设置session存活时间，单位是秒。每次GC启动后, 会通过stat得到session文件最后访问的unix时间,通过现在时间减去文件最后访问时间之间大于session.gc_maxlifetime,则会删除该文件。</p>
<h3>总结</h3>
<p>1,PHP使用Cookie的方法传递session id。尽量不要使用GET方法传递session id,因为这样很不安全。<br />
2,可以通过setcookie()的方法,将客户端的session id的Cookie记录删除。<br />
3,PHP GC进程由session初始化启动。但不是每一次用户请求都会被启动，它的启动概率默认是1/1000。过于频繁访问的网站，并发量大的网站，可减小PHP GC的启动频率。PHP GC回收session会降低php的执行效率。<br />
4,通过下面代码，优化session回收</p>
<pre>
<div>
<pre><strong>&lt;?php</strong>
<a href="http://www.php.net/session_start">session_start</a>();
if (<a href="http://www.php.net/isset">isset</a>($_SESSION['SESS_TIMEOUT'])) {
  if ($_SERVER['REQUEST_TIME'] &gt; $_SESSION['SESS_TIMEOUT']) {
    <a href="http://www.php.net/setcookie">setcookie</a>(<a href="http://www.php.net/session_name">session_name</a>(), <a href="http://www.php.net/session_id">session_id</a>(), -1, '/');
    <a href="http://www.php.net/session_unset">session_unset</a>();
    <a href="http://www.php.net/session_destroy">session_destroy</a>();
  }
} else {
  $_SESSION['SESS_TIMEOUT'] = $_SERVER['REQUEST_TIME'] + 3600;
}
?&gt;</pre>
</div>
</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=128</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php empty()函数的问题</title>
		<link>http://www.magic-jungle.com/?p=125</link>
		<comments>http://www.magic-jungle.com/?p=125#comments</comments>
		<pubDate>Thu, 05 Aug 2010 14:32:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[empty()]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=125</guid>
		<description><![CDATA[在php下 empty()
如果 var 是非空或非零的值，则 empty() 返回 FALSE。换句话说，&#8221;"、0、&#8221;0&#8243;、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的，如果 var 为空，则返回 TRUE。
&#60;?php
$a =0;
$b=&#8221;;
echo &#8220;empty:&#60;br&#62;&#8221;;

if(empty($a)){
echo &#8220;yes&#60;br&#62;&#8221;;
}else{
echo &#8220;no&#60;br&#62;&#8221;;
}
if(empty($b)){
echo &#8220;yes&#8221;;
}else{
echo &#8220;no&#8221;;
}
?&#62;
结果：
empty:
yes
yes
]]></description>
			<content:encoded><![CDATA[<p><strong>在php下 empty()</strong></p>
<p>如果 var 是非空或非零的值，则 empty() 返回 FALSE。换句话说，&#8221;"、0、&#8221;0&#8243;、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的，如果 var 为空，则返回 TRUE。</p>
<p>&lt;?php</p>
<p>$a =0;</p>
<p>$b=&#8221;;</p>
<p>echo &#8220;empty:&lt;br&gt;&#8221;;</p>
<p><span id="more-125"></span></p>
<p>if(empty($a)){</p>
<p>echo &#8220;yes&lt;br&gt;&#8221;;</p>
<p>}else{</p>
<p>echo &#8220;no&lt;br&gt;&#8221;;</p>
<p>}</p>
<p>if(empty($b)){</p>
<p>echo &#8220;yes&#8221;;</p>
<p>}else{</p>
<p>echo &#8220;no&#8221;;</p>
<p>}</p>
<p>?&gt;</p>
<p>结果：</p>
<p>empty:</p>
<p>yes</p>
<p>yes</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=125</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HTML4和HTMl5的区别，HTML5增加的内容</title>
		<link>http://www.magic-jungle.com/?p=123</link>
		<comments>http://www.magic-jungle.com/?p=123#comments</comments>
		<pubDate>Wed, 04 Aug 2010 12:12:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Javascript & Framework]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=123</guid>
		<description><![CDATA[■HTML5追加的新标签
新千年以来，超文本标记语言（HTML）5 第一次向 HTML 中引入新的元素。
新的结构元素包括 aside、figure 和 section。
新的内联元素包括 time、meter 和 progress。
新的内嵌元素有 video 和 audio。新的交互元素有 details、datagrid 和 command。
■HTML5的结构

* section：这可以是书中的一章或一节，实际上可以是在 HTML 4 中有自己的标题的任何东西
* header：页面上显示的页眉；与 head 元素不一样
* footer：页脚；可以显示电子邮件中的签名
* nav：指向其他页面的一组链接
* article：blog、杂志、文章汇编等中的一篇文章
必须分析标题的级别，才能看出各个部分的划分方式。边栏、页脚、页眉、导航条、主内容区和各篇文章都由通用的 div 元素来表示
HTML 5 增加的块级元素：
除了结构性元素之外，HTML 5 还增加了一些纯语义性的块级元素：
* aside
* figure
* dialog
aside 元素代表说明、提示、边栏、引用、附加注释等，也就是叙述主线之外的内容。
figure 元素代表一个块级图像，还可以包含说明。figure 元素不只可以显示图片。还可以使用它给 audio、video、iframe、object 和 embed 元素加说明。
dialog 元素表示几个人之间的对话。HTML 5 dt 元素可以表示讲话者，HTML 5 dd 元素可以表示讲话内容。所以，在老式浏览器中也可以以合理的方式显示对话。
HTML 5 增加的语义性内联元素
HTML 4 用 5 个不同的内联元素表示略有差异的计算机代码：var、code、kbd、tt [...]]]></description>
			<content:encoded><![CDATA[<p>■HTML5追加的新标签</p>
<p>新千年以来，超文本标记语言（HTML）5 第一次向 HTML 中引入新的元素。</p>
<p>新的结构元素包括 aside、figure 和 section。</p>
<p>新的内联元素包括 time、meter 和 progress。</p>
<p>新的内嵌元素有 video 和 audio。新的交互元素有 details、datagrid 和 command。<br />
■HTML5的结构</p>
<p><span id="more-123"></span></p>
<p>* section：这可以是书中的一章或一节，实际上可以是在 HTML 4 中有自己的标题的任何东西<br />
* header：页面上显示的页眉；与 head 元素不一样<br />
* footer：页脚；可以显示电子邮件中的签名<br />
* nav：指向其他页面的一组链接<br />
* article：blog、杂志、文章汇编等中的一篇文章</p>
<p>必须分析标题的级别，才能看出各个部分的划分方式。边栏、页脚、页眉、导航条、主内容区和各篇文章都由通用的 div 元素来表示<br />
HTML 5 增加的块级元素：</p>
<p>除了结构性元素之外，HTML 5 还增加了一些纯语义性的块级元素：</p>
<p>* aside<br />
* figure<br />
* dialog</p>
<p>aside 元素代表说明、提示、边栏、引用、附加注释等，也就是叙述主线之外的内容。</p>
<p>figure 元素代表一个块级图像，还可以包含说明。figure 元素不只可以显示图片。还可以使用它给 audio、video、iframe、object 和 embed 元素加说明。</p>
<p>dialog 元素表示几个人之间的对话。HTML 5 dt 元素可以表示讲话者，HTML 5 dd 元素可以表示讲话内容。所以，在老式浏览器中也可以以合理的方式显示对话。</p>
<p>HTML 5 增加的语义性内联元素</p>
<p>HTML 4 用 5 个不同的内联元素表示略有差异的计算机代码：var、code、kbd、tt 和 samp。但是，它无法表示时间、数字等基本数值。HTML 5 提供了几个新的内联元素来满足非技术作者的需求。</p>
<p>m</p>
<p>m 元素表示文本被 “加上标志”，但是不一定要强调。可以把它想像成书中突出显示的一节。Google 的缓存页面就是典型的用例。如果链接到一个缓存的副本，搜索词就被加上标志。例如，如果搜索 “Egret”，那么缓存的 Google 页面可能像下面这样：<br />
HTMl源代码 Egret (also known as the American Egret) is a large white wading bird found worldwide. The Great Egret flies with slow wing beats. The scientific name of the Great Egret is <em>Casmerodius albus</em>.</p>
<p>time</p>
<p>time 元素表示一个时间值，比如 5:35 P.M., EST, April 23, 2007。例如：<br />
HTMl源代码</p>
<p>I am writing this example at 5:35 P.M. on April 23rd.</p>
<p>time 元素可以帮助浏览器和其他程序识别出 HTML 页面中的时间。它不要求对元素内容应用任何特定的格式。但是，每个 time 元素都应该有一个 datetime 属性，其中包含更适合机器识别的时间值，比如：</p>
<p>HTMl 源代码</p>
<p>I am writing this example at 5:35 P.M. on April 23rd.</p>
<p>meter</p>
<p>meter 元素表示指定范围内的数字值。例如，可以用它表示薪水、投票给 Le Pen 的法国选民的百分比或考试分数。在这里，我使用 meter 标出 Software Development 2007 上一位 Google 程序员提供的数据：<br />
HTMl 源代码</p>
<p>An entry level programmer in Silicon Valley can expect to start around $90,000 per year.</p>
<p>meter 元素帮助浏览器和其他客户机识别 HTML 页面中的数量。它不要求对元素内容应用任何特定的格式。但是，每个 meter 元素可以有最多 6 个属性，它们按照更适合机器识别的形式表示这个数量：</p>
<p>* value<br />
* min<br />
* low<br />
* high<br />
* max<br />
* optimum</p>
<p>这些属性都应该包含一个十进制数字。例如，期末考试的分数可以写成下面这样：<br />
HTMl 源代码</p>
<p>Your score was B+.</p>
<p>progress</p>
<p>progress 元素表示一个正在进行的过程的状态，就像图形用户界面（GUI）应用程序中的进度条。例如，可以用它表示一个文件已经下载的百分比或者播放电影时的当前位置。下面这个进度控件表示下载已经完成了 33%：<br />
HTMl源代码</p>
<p>Downloaded:</p>
<p>33%</p>
<p>HTML5新增的内嵌的媒体</p>
<p>引入一个新的 video 元素，用来嵌入任意视频格式.例如，可以用以下代码嵌入QuickTime 电影 “a Sora in Prospect Park”：<br />
HTMl源代码</p>
<p>引入 audio 元素。例如，可以使用以下代码给 Web 页面加上背景音乐：<br />
HTMl源代码</p>
<p>autoplay 属性指示浏览器在装载页面后立即开始播放，而不等待明确的用户请求</p>
<p>引入了img元素，用来支持所有图片格式 。<br />
HTML5新增加的交互元素</p>
<p>HTML 5 也被称为 Web Applications 1.0。为了实现这个目标，增加了几个为 Web 页面提供交互体验的新元素：</p>
<p>* details<br />
* datagrid<br />
* menu<br />
* command</p>
<p>这些元素都可以根据用户的操作和选择改变显示的内容，而不需要从服务器装载新页面。</p>
<p>details</p>
<p>details 元素表示在默认情况下可能不显示的详细信息。可选的 legend 元素可以提供详细信息的摘要。details 元素的用途之一是提供脚注和尾注。例如：<br />
HTMl 源代码The bill of a Craveri&#8217;s Murrelet is about 10% thinner than the bill of a Xantus&#8217;s Murrelet.<br />
[Sibley, 2000]</p>
<p>Sibley, David Allen, The Sibley Guide to Birds, (New York: Chanticleer Press, 2000) p. 247</p>
<p>没有指定具体的显示方式。浏览器可以选用脚注、尾注和工具提示等方式。</p>
<p>每个 details 元素可以有一个 open 属性。如果设置了这个属性，那么详细信息在最初就显示出来。如果没有设置这个属性，那么会隐藏它们，直到用户要求显示它们。无论是哪种情况，用户都可以通过单击一个图标或其他控件来显示或隐藏详细信息。</p>
<p>datagrid</p>
<p>datagrid 元素提供一个网格控件。可以用它显示树、列表和表格，用户和脚本可以更新这些界面元素。与之相反，传统的表格主要用来显示静态数据。</p>
<p>datagrid 从它的内容（一个 table、select 或其他 HTML 元素）获得初始数据。</p>
<p>这个元素与常规表格的区别在于，用户可以选择行、列和单元格；把行、列和单元格折叠起来；编辑单元格；删除行、列和单元格；对网格排序；以及在客户机浏览器中直接进行其他数据操作。可以用 JavaScript 代码监视更新。Document Object Model（DOM）中增加了 HTMLDataGridElement 接口以支持这个元素（清单 10）。</p>
<p>menu和command</p>
<p>menu 元素实际上在 HTML 2 中就出现了。在 HTML 4 中废弃了它，但是 HTML 5 又恢复了它并指定了新的意义。在 HTML 5 中，menu 包含 command 元素，每个 command 元素引发一个操作。例如一个弹出警告框的菜单。<br />
HTMl 源代码</p>
<p>还可以用 checked=&#8221;checked&#8221; 属性将命令转换为复选框。通过指定 radiogroup 属性，可以将复选框转换为单选按钮，这个属性的值是互相排斥的按钮的组名。</p>
<p>除了简单的命令列表之外，还可以使用 menu 元素创建工具栏或弹出式上下文菜单，这需要将 type 属性设置为 toolbar 或 popup。</p>
<p>label 属性提供菜单的标题。例如，清单 14 显示一个 Edit 菜单。</p>
<p>■HTML5中增加的标签元素</p>
<p><a href="http://www.htmling.cn/html5/article.html">&lt;article&gt;</a> …… 定义外部的内容，一般是文章类<br />
<a href="http://www.htmling.cn/html5/aside.html">&lt;aside&gt;</a> ……… 定义 article 以外的内容,应该与 article 的内容相关。<br />
<a href="http://www.htmling.cn/html5/audio.html">&lt;audio&gt;</a> ……… 定义声音，比如音乐或其他音频流。<br />
<a href="http://www.htmling.cn/html5/canvas.html">&lt;canvas&gt;</a> …… 定义图形，比如图表和其他图像。<br />
<a href="http://www.htmling.cn/html5/command.html">&lt;command&gt;</a> … 命令按钮，比如单选按钮、复选框或按钮。<br />
<a href="http://www.htmling.cn/html5/datalist.html">&lt;datalist&gt;</a> …… 定义可选数据的列表。与 input 元素配合使用，就可以制作出输入值的下拉列表。<br />
<a href="http://www.htmling.cn/html5/details.html">&lt;details&gt;</a> …… 定义元素的细节，用户可进行查看，或通过点击进行隐藏。<br />
<a href="http://www.htmling.cn/html5/embed.html">&lt;embed&gt;</a> …… 定义嵌入的内容，比如插件。<br />
<a href="http://www.htmling.cn/html5/figcaption.html">&lt;figcaption&gt;</a> ……表示图表的字幕<br />
<a href="http://www.htmling.cn/html5/figure.html">&lt;figure&gt;</a> ……… 表示图表的时候使用<br />
<a href="http://www.htmling.cn/html5/footer.html">&lt;footer&gt;</a> …… 定义 section 或 document 的页脚<br />
<a href="http://www.htmling.cn/html5/header.html">&lt;header&gt;</a> ……定义 section 或 document 的页眉。<br />
<a href="http://www.htmling.cn/html5/hgroup.html">&lt;hgroup&gt;</a> …… 归结表示项的标题<br />
<a href="http://www.htmling.cn/html5/keygen.html">&lt;keygen&gt; </a>…… 定义生成密钥<br />
<a href="http://www.htmling.cn/html5/mark.html">&lt;mark&gt;</a> ……… 用高光突出文档里相符合的文本<br />
<a href="http://www.htmling.cn/html5/menu.html">&lt;menu&gt; </a>……… 定义菜单列表。当希望列出表单控件时使用该标签。<br />
<a href="http://www.htmling.cn/html5/meter.html">&lt;meter&gt;</a> …… 定义度量（单位）。仅用于已知最大和最小值的度量。<br />
<a href="http://www.htmling.cn/html5/nav.html">&lt;nav&gt;</a> ………… 定义导航链接的部分。<br />
<a href="http://www.htmling.cn/html5/output.html">&lt;output&gt;</a> …… 定义不同类型的输出，比如脚本的输出。<br />
<a href="http://www.htmling.cn/html5/progress.html">&lt;progress&gt;</a> … 运行中的进程。可以使用 &lt;progress&gt; 标签来显示 JavaScript 中耗费时间的函数的进程。<br />
<a href="http://www.htmling.cn/html5/section.html">&lt;section&gt;</a> …… 定义文档中的节（section）。比如章节、页眉、页脚或文档中的其他部分。<br />
<a href="http://www.htmling.cn/html5/source.html">&lt;source&gt; </a>…… 为媒介元素（比如 &lt;video&gt; 和 &lt;audio&gt;）定义媒介资源。<br />
<a href="http://www.htmling.cn/html5/summary.html">&lt;summary&gt; </a>…… 在&lt;details&gt;指定相关内容的文本<br />
<a href="http://www.htmling.cn/html5/time.html">&lt;time&gt;</a> ……… 定义日期或时间，或者两者。<br />
<a href="http://www.htmling.cn/html5/video.html">&lt;video&gt;</a> …… 定义视频，比如电影片段或其他视频流。</p>
<p><a name="abo"></a>■HTML5中将会禁止使用的标签元素</p>
<p><a href="http://www.htmling.cn/html/acronym.html">&lt;acronym&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/applet.html">&lt;applet&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/basefont.html">&lt;basefont&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/bgsound.html">&lt;bgsound&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/big.html">&lt;big&gt;</a> …………<br />
<a href="http://www.htmling.cn/html/blink.html">&lt;blink&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/center.html">&lt;center&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/dir.html">&lt;dir&gt;</a> …………<br />
<a href="http://www.htmling.cn/html/font.html">&lt;font&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/frame.html">&lt;frame&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/frameset.html">&lt;frameset&gt;</a> …<br />
<a href="http://www.htmling.cn/html/isindex.html">&lt;isindex&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/listing.html">&lt;listing&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/marquee.html">&lt;marquee&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/nobr.html">&lt;nobr&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/noembed.html">&lt;noembed&gt;</a> …<br />
<a href="http://www.htmling.cn/html/noframes.html">&lt;noframes&gt;</a> …<br />
<a href="http://www.htmling.cn/html/plaintext.html">&lt;plaintext&gt;</a> …<br />
<a href="http://www.htmling.cn/html/s.html">&lt;s&gt;</a> …………<br />
<a href="http://www.htmling.cn/html/spacer.html">&lt;spacer&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/strike.html">&lt;strike&gt;</a> ……<br />
<a href="http://www.htmling.cn/html/tt.html">&lt;tt&gt;</a> …………<br />
<a href="http://www.htmling.cn/html/u.html">&lt;u&gt;</a> …………<br />
<a href="http://www.htmling.cn/html/wbr.html">&lt;wbr&gt;</a> ………<br />
<a href="http://www.htmling.cn/html/xmp.html">&lt;xmp&gt;</a> ………</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=123</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CentOS5 MySQL php的配置</title>
		<link>http://www.magic-jungle.com/?p=120</link>
		<comments>http://www.magic-jungle.com/?p=120#comments</comments>
		<pubDate>Fri, 18 Jun 2010 06:48:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[apche]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=120</guid>
		<description><![CDATA[


困扰很久的linux下安装PHP的问题总算解决了，参考文档和经验都在下面了，供大家参考拉.
使用的软件：
freetype-2.1.10
gd-2.0.33
httpd-2.2.8
jpegsrc.v6b
libpng-1.2.8
libxml2-2.6.26
mysql-5.0.27
php-5.2.5
phpmyadmin-2.11.5.2
zlib-1.2.3
(下面的内容是参考资料和自己的经验结合，所以有些软件的版本不一样，希望大家谅解)
一、安装Mysql
1、建立msyql用户组
[root@localhost ~]# grep mysql /etc/group
#查询系统中是否有mysql这个用户组，没有则添加。
[root@localhost ~]# groupadd mysql
#增加一个名为mysql的用户组
2、建立mysql用户
[root@localhost ~]# grep mysql /etc/passwd

#查询系统中是否有mysql这个用户，没有则添加。
[root@localhost ~]# useradd mysql -g mysql -M -s /sbin/nologin
#增加一个名为mysql的用户。
-g：指定新用户所属的用户组(group)
-M：不建立根目录
-s：定义其使用的shell，/sbin/nologin代表用户不能登录系统。
3、解压：mysql
[root@localhost ~]# cd /usr/local/src/
[root@localhost src]# tar -zxvf mysql-5.0.27.tar.gz
#……(信息略)……
#解压缩
3、设置编译器的编译参数
[root@localhost src]# cd /usr/local/src/mysql-5.0.27
[root@localhost mysql-5.0.27]# ./configure &#8211;prefix=/usr/local/mysql &#8211;with-unix-socket-path=/tmp/mysql.sock &#8211;localstatedir=/usr/local/mysql/data &#8211;with-charset=gbk &#8211;without-debug &#8211;enable-assembler &#8211;without-isam &#8211;with-client-ldflags=-all-static &#8211;with-mysqld-ldflags=-all-static
#这些设置告诉编译器如何编译apache：
–prefix=/usr/local/mysql
指定msyql安装目录
–with-unix-socket-path=/tmp/mysql.sock
这个是指定mysql服务器启动后，联机套接字文件所处的位置和文件名。
–localstatedir=/usr/local/mysql/data
指定mysql的数据库目录
–with-charset=gbk
添加gbk中文字符支持
–without-debug
去除debug模式
–enable-assembler
使用一些字符函数的汇编版本
–without-isam
去掉isam表类型支持，现在很少用了，isam表是一种依赖平台的表
–with-client-ldflags=-all-static
–with-mysqld-ldflags=-all-static
4、编译和安装
[root@localhost mysql-5.0.27]# make
#“make”命令把源文件编译成可执行的二进制文件
[root@localhost mysql-5.0.27]# make install
#“make install”把二进制文件和配置文件安装在合适的目录下
6、初始化系统库
[root@localhost mysql-5.0.27]# ./scripts/mysql_install_db
7、其它设置
[root@localhost mysql-5.0.27]# cp support-files/my-medium.cnf /etc/my.cnf -fv
#注解：
-f,删除目标中同名的文件或目录，并且不给任何提示。
#还有一些其它的my.cnf配置文件。适合不同的应用规模。型式如my-*.cnf。根据自己的需要cp。
[root@localhost mysql-5.0.27]# [...]]]></description>
			<content:encoded><![CDATA[<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td id="postmessage_7973134">困扰很久的linux下安装PHP的问题总算解决了，参考文档和经验都在下面了，供大家参考拉.</p>
<p>使用的软件：<br />
freetype-2.1.10<br />
gd-2.0.33<br />
httpd-2.2.8<br />
jpegsrc.v6b<br />
libpng-1.2.8<br />
libxml2-2.6.26<br />
mysql-5.0.27<br />
php-5.2.5<br />
phpmyadmin-2.11.5.2<br />
zlib-1.2.3<br />
(下面的内容是参考资料和自己的经验结合，所以有些软件的版本不一样，希望大家谅解)</p>
<p><span style="color: #4169e1;"><span style="color: #008000;">一、安装Mysql</span></span><br />
1、建立msyql用户组<br />
[root@localhost ~]# grep mysql /etc/group<br />
#查询系统中是否有mysql这个用户组，没有则添加。<br />
[root@localhost ~]# groupadd mysql<br />
#增加一个名为mysql的用户组<br />
2、建立mysql用户<br />
[root@localhost ~]# grep mysql /etc/passwd</p>
<p><span id="more-120"></span><br />
#查询系统中是否有mysql这个用户，没有则添加。<br />
[root@localhost ~]# useradd mysql -g mysql -M -s /sbin/nologin<br />
#增加一个名为mysql的用户。<br />
-g：指定新用户所属的用户组(group)<br />
-M：不建立根目录<br />
-s：定义其使用的shell，/sbin/nologin代表用户不能登录系统。<br />
3、解压：mysql<br />
[root@localhost ~]# cd /usr/local/src/<br />
[root@localhost src]# tar -zxvf mysql-5.0.27.tar.gz<br />
#……(信息略)……<br />
#解压缩<br />
3、设置编译器的编译参数<br />
[root@localhost src]# cd /usr/local/src/mysql-5.0.27<br />
[root@localhost mysql-5.0.27]# ./configure &#8211;prefix=/usr/local/mysql &#8211;with-unix-socket-path=/tmp/mysql.sock &#8211;localstatedir=/usr/local/mysql/data &#8211;with-charset=gbk &#8211;without-debug &#8211;enable-assembler &#8211;without-isam &#8211;with-client-ldflags=-all-static &#8211;with-mysqld-ldflags=-all-static<br />
#这些设置告诉编译器如何编译apache：<br />
–prefix=/usr/local/mysql<br />
指定msyql安装目录</p>
<p>–with-unix-socket-path=/tmp/mysql.sock<br />
这个是指定mysql服务器启动后，联机套接字文件所处的位置和文件名。<br />
–localstatedir=/usr/local/mysql/data<br />
指定mysql的数据库目录<br />
–with-charset=gbk<br />
添加gbk中文字符支持<br />
–without-debug<br />
去除debug模式<br />
–enable-assembler<br />
使用一些字符函数的汇编版本<br />
–without-isam<br />
去掉isam表类型支持，现在很少用了，isam表是一种依赖平台的表<br />
–with-client-ldflags=-all-static<br />
–with-mysqld-ldflags=-all-static<br />
4、编译和安装<br />
[root@localhost mysql-5.0.27]# make<br />
#“make”命令把源文件编译成可执行的二进制文件<br />
[root@localhost mysql-5.0.27]# make install<br />
#“make install”把二进制文件和配置文件安装在合适的目录下<br />
6、初始化系统库<br />
[root@localhost mysql-5.0.27]# ./scripts/mysql_install_db<br />
7、其它设置<br />
[root@localhost mysql-5.0.27]# cp support-files/my-medium.cnf /etc/my.cnf -fv<br />
#注解：<br />
-f,删除目标中同名的文件或目录，并且不给任何提示。<br />
#还有一些其它的my.cnf配置文件。适合不同的应用规模。型式如my-*.cnf。根据自己的需要cp。<br />
[root@localhost mysql-5.0.27]# cp support-files/mysql.server /etc/init.d/mysqld<br />
#添加到起动脚本<br />
[root@localhost mysql-5.0.27]# chmod 700 /etc/init.d/mysqld<br />
[root@localhost mysql-5.0.27]# cd /usr/local<br />
[root@localhost local]# chmod 750 mysql -R<br />
#注解：<br />
-R 递归改变目录及其内容的权限。<br />
[root@localhost local]# chown -R mysql.mysql /usr/local/mysql<br />
#设置所有者，mysql起动时会以mysql用户的身份运行，这样可以提高系统的安全性。<br />
[root@localhost local]# chown -R mysql.mysql /usr/local/mysql/data<br />
[root@localhost local]# cd /usr/local/mysql/libexec<br />
[root@localhost libexec]# cp mysqld mysqld.old<br />
[root@localhost libexec]# strip mysqld</p>
<p>[root@localhost libexec]# chkconfig –add mysqld<br />
#添加一个服务，当然也可以手工添加服务。<br />
[root@localhost libexec]# chkconfig –level 345 mysqld on<br />
#设置开机时起动<br />
[root@localhost libexec]# service mysqld start<br />
#启动mysql服务<br />
[root@localhost libexec]# ln -s /usr/local/mysql/bin/mysql /sbin/mysql<br />
[root@localhost libexec]# ln -s /usr/local/mysql/bin/mysqladmin /sbin/mysqladmin<br />
[root@localhost libexec]# ln -s /usr/local/mysql/bin/mysqldump /sbin/mysqldump<br />
[root@localhost libexec]# mysqladmin -uroot password “youpassword”<br />
#设置root帐户的密码<br />
[root@localhost libexec]# mysql -uroot -p<br />
# 输入你设置的密码<br />
mysql&gt;use mysql;<br />
mysql&gt;delete from user where password=”&#8221;;<br />
#删除用于本机匿名连接的空密码帐号<br />
mysql&gt;flush privileges;<br />
mysql&gt; show databases;<br />
———-<br />
| Database |<br />
———-<br />
| mysql |<br />
| test |<br />
———-<br />
2 rows in set (0.08 sec)<br />
#显示一下数据库，测试mysql是否安装正常。<br />
mysql&gt; quit</p>
<p><span style="color: #1e90ff;">如果忘记密码，可以：<br />
我的系统是linux，最近新装好的mysql在进入mysql工具时，总是有错误提示:<br />
# mysql -uroot -p<br />
Enter password:<br />
ERROR 1045 (28000): Access denied for user </span><span style="color: #1e90ff;">&#8216;root&#8217;@'localhost&#8217;</span><span style="color: #1e90ff;"> (using password: NO)</span><br />
<span style="color: #1e90ff;">使用网上介绍的方法修改root用户的密码：<br />
# mysqladmin -uroot -p password &#8216;newpassword&#8217;<br />
Enter password:<br />
mysqladmin: connect to server at &#8216;localhost&#8217; failed<br />
error: &#8216;Access denied for user </span><span style="color: #1e90ff;">&#8216;root&#8217;@'localhost&#8217;</span><br />
<span style="color: #1e90ff;">(using password: YES)&#8217;</span><br />
<span style="color: #1e90ff;">现在终于被我找到了解决方法，如下（请先测试方法三，谢谢！）：<br />
方法一：<br />
# /etc/init.d/mysql stop<br />
# mysqld_safe &#8211;user=mysql &#8211;skip-grant-tables &#8211;skip-networking &amp;<br />
# mysql -u root mysql<br />
mysql&gt; UPDATE user SET Password=PASSWORD(&#8216;newpassword&#8217;) where USER=&#8217;root&#8217;;<br />
mysql&gt; FLUSH PRIVILEGES;<br />
mysql&gt; quit</span><br />
<span style="color: #1e90ff;"># /etc/init.d/mysql restart<br />
# mysql -uroot -p<br />
Enter password: &lt; 输入新设的密码newpassword&gt;</span></p>
<p><span style="color: #4169e1;"><span style="color: #008000;">二、安装Apache</span><br />
</span>1、下载：apache<br />
[root@localhost src]# chmod x httpd-2.2.8.tar.gz<br />
[root@localhost src]# tar -zxvf httpd-2.2.8.tar.gz<br />
3）设置编译器的编译参数<br />
[root@localhost src]# cd httpd-2.2.8<br />
[root@localhost httpd-2.2.8]# ./configure –prefix=/usr/local/apache2 –enable-module=so<br />
4）编译和安装：<br />
[root@localhost httpd-2.2.8]# make; make install<br />
#如果没有错误的话，那么Apache就已经安装在/usr/local/apache2目录中了<br />
3、启动服务：<br />
[root@localhost httpd-2.2.8]# /usr/local/apache2/bin/apachectl start<br />
4、确定启动状：<br />
[root@localhost apache2]# netstat -utl<br />
tcp 0 0 *:http *:* LISTEN<br />
#看到上面这行就表示你的Apache已经启动。<br />
#用浏览器访问，看到It works!，说明apache已经安装成功了，恭喜您！</p>
<p><span style="color: #4169e1;"><span style="color: #008000;">三、安装PHP</span><br />
</span>1、准备目录：<br />
mkdir /usr/local/modules<br />
#jpeg目录<br />
mkdir /usr/local/modules/jpeg6</p>
<p>mkdir /usr/local/modules/jpeg6/bin<br />
mkdir /usr/local/modules/jpeg6/lib<br />
mkdir /usr/local/modules/jpeg6/include<br />
mkdir /usr/local/modules/jpeg6/man<br />
mkdir /usr/local/modules/jpeg6/man/man1<br />
2、安装zlib<br />
# tar xzvf zlib-1.2.3.tar.gz<br />
# mv zlib-1.2.3 /usr/local/src/<br />
# cd /usr/local/src/zlib-1.2.3<br />
不要用&#8211;prefix自定义安装目录，影响gd的安装<br />
# ./configure<br />
# make &amp;&amp; make install<br />
3、安装freetype<br />
# tar xzvf freetype-2.3.5.tar.bz2<br />
# mv freetype-2.3.5 /usr/local/src/<br />
# cd /usr/local/src/freetype-2.3.5<br />
# ./configure &#8211;prefix=/usr/local/modules/freetype<br />
# make &amp;&amp; make install<br />
4、安装libpng<br />
# tar jxvf libpng-1.2.20.tar.bz2<br />
不要用&#8211;prefix自定义安装目录，影响gd的安装<br />
# mv libpng-1.2.20 /usr/local/src/<br />
# cd /usr/local/src/libpng-1.2.5<br />
# cp scripts/makefile.std makefile<br />
# make test<br />
# make install<br />
5、安装jpeg<br />
# tar xzvf jpegsrc.v6b.tar.gz<br />
# mv jpeg-6b /usr/local/src/<br />
# cd /usr/local/src/jpeg-6b<br />
# ./configure &#8211;prefix=/usr/local/modules/jpeg6 &#8211;enable-shared &#8211;enable-static<br />
# make &amp;&amp; make install<br />
6、安装GD<br />
# tar xzvf gd-2.0.33.tar.gz<br />
# mv gd-2.0.33 /usr/local/src/<br />
# cd /usr/local/src/gd-2.0.33<br />
# ./configure &#8211;prefix=/usr/local/modules/gd &#8211;with-jpeg=/usr/local/modules/jpeg6 &#8211;with-png &#8211;with-zlib &#8211;with-freetype=/usr/local/modules/freetype<br />
# make<br />
# make install<br />
7、安装PHP<br />
# tar -jxvf php-5.2.1.tar.bz2<br />
# mv php-5.2.1 /usr/local/src<br />
# cd /usr/local/src/php-5.2.1/<br />
# ./configure &#8211;with-apxs2=/usr/local/apache2/bin/apxs &#8211;with-mysql=/usr/local/mysql &#8211;with-gd=/usr/local/modules/gd &#8211;with-jpeg-dir=/usr/local/modules/jpeg6 &#8211;with-png-dir=/usr/lib &#8211;with-freetype-dir=/usr/local/modules/freetype &#8211;with-zlib &#8211;enable-gd</p>
<p># make &amp;&amp; make install<br />
#cp php.ini-dist /usr/local/lib/php.ini<br />
8、整合Apache和PHP<br />
修改/usr/local/apache2/conf/httpd.conf文件<br />
在行AddType application/x-gzip .gz .tgz后添加一行<br />
AddType application/x-httpd-php .php .phtml<br />
修改行DirectoryIndex index.php<br />
重新启动Apache  并且在它的/usr/local/apache2/htdocs/目录创建一个phpinfo.php文件。<br />
内容如下:<br />
&lt; ?php<br />
phpinfo();<br />
?&gt;<br />
在IE中输入http://127.0.0.1/phpinfo.php。<br />
9、配置php.ini<br />
去掉<br />
extension=php_gd<br />
extension=php_mysql.dll<br />
extension=php_mysqli.dll</p>
<p>10、安装phpMyAdmin<br />
#tar –zvxf phpMyAdmin.tar.gz<br />
mv phpMyAdmin /usr/local/apache2/htdocs/phpmyadmin</p>
<p>修改config.ini.php<br />
设置$cfg['blowfish_secret']=&#8217;config&#8217;;</p>
<p>Over~~~~</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=120</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>php mail函数在win下的使用，以及配置win下的sendmail</title>
		<link>http://www.magic-jungle.com/?p=117</link>
		<comments>http://www.magic-jungle.com/?p=117#comments</comments>
		<pubDate>Mon, 07 Jun 2010 06:32:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP & Mysql]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sendmail]]></category>
		<category><![CDATA[win]]></category>
		<category><![CDATA[邮件服务器]]></category>

		<guid isPermaLink="false">http://www.magic-jungle.com/?p=117</guid>
		<description><![CDATA[注意：如果不是自己的服务器的话用其他方法发吧，方法多得是！
mail函数在win里可以通过配置php.ini来正常使用
打开php.ini
[mail function]
; For Win32 only.
SMTP = localhost
smtp_port = 25
; For Win32 only.
sendmail_from = me@example.com
; For Unix only.  You may supply arguments as well (default: ”sendmail -t -i”).
; sendmail_path = ”&#8221;
; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail(), even in safe mode.
;mail.force_extra_parameters =
设置SMTP，smtp_port，sendmail_from。分别是pop3服务器地址，端口号这两个一般默认，sendmail_from设置的是发件人邮箱
注意的是这里需要的pop3服务器是不需要身份验证的那种而且不能使用安全方式连接的。国内有些没有提供不验证服务的…在服务器上装上smtp组件就可以了，安装方法很多网上都有
如果不打算让本机成为smtp服务器，可以使用linux常用的sendmail，这样可以通过验证使用国内的一些服务器的pop3服务器，建议是qq或者foxmail个人感觉腾讯的速度和稳定都不错。
经测试目前163、新浪的SMTP无法使用，qq和foxmail可以用，其他没测试…
win下怎么配置呢
[mail function]
; For Win32 only.
; SMTP = localhost
; smtp_port = 25
; For Win32 only.
; sendmail_from = me@example.com
; For Unix only.  You may supply arguments as well (default: ”sendmail -t -i”).
sendmail_path = ”d:/soft/sendmail/sendmail.exe -t -i”
; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail(), even in safe mode.
;mail.force_extra_parameters =
按上面的方式把前面说的三个选项前面都加上分号，把sendmail_path前面的分号去掉下载下面的文件：
sendmail压缩包
解压后找个地方放好，将里面sendmail.exe的地址填到sendmail_path并如上面所写增加-t -i参数（更多参数自己查吧）。
打开：sendmail.ini文件
修改里面的
smtp_server=smtp服务器地址
auth_username=邮箱登录名
auth_password=邮箱密码
force_sender=发件人地址全写
ok了mail函数可以正常使用了，注意如果iis使用cgi模式运行php的话用sendmail方法会出错，修改为ISAPI模式后一切正常了。
如果不是自己的服务器的话用其他方法发吧，方法多得是！
]]></description>
			<content:encoded><![CDATA[<p>注意：如果不是自己的服务器的话用其他方法发吧，方法多得是！<br />
mail函数在win里可以通过配置php.ini来正常使用<br />
打开php.ini</p>
<p>[mail function]<br />
; For Win32 only.<br />
SMTP = localhost<br />
smtp_port = 25<br />
; For Win32 only.<br />
sendmail_from = me@example.com<br />
; For Unix only.  You may supply arguments as well (default: ”sendmail -t -i”).<br />
; sendmail_path = ”&#8221;<br />
; Force the addition of the specified parameters to be passed as extra parameters<br />
; to the sendmail binary. These parameters will always replace the value of<br />
; the 5th parameter to mail(), even in safe mode.<br />
;mail.force_extra_parameters =<span id="more-117"></span></p>
<p>设置SMTP，smtp_port，sendmail_from。分别是pop3服务器地址，端口号这两个一般默认，sendmail_from设置的是发件人邮箱<br />
注意的是这里需要的pop3服务器是不需要身份验证的那种而且不能使用安全方式连接的。国内有些没有提供不验证服务的…在服务器上装上smtp组件就可以了，安装方法很多网上都有</p>
<p>如果不打算让本机成为smtp服务器，可以使用linux常用的sendmail，这样可以通过验证使用国内的一些服务器的pop3服务器，建议是qq或者foxmail个人感觉腾讯的速度和稳定都不错。</p>
<p>经测试目前163、新浪的SMTP无法使用，qq和foxmail可以用，其他没测试…</p>
<p>win下怎么配置呢</p>
<p>[mail function]<br />
; For Win32 only.<br />
; SMTP = localhost<br />
; smtp_port = 25<br />
; For Win32 only.<br />
; sendmail_from = me@example.com<br />
; For Unix only.  You may supply arguments as well (default: ”sendmail -t -i”).<br />
sendmail_path = ”d:/soft/sendmail/sendmail.exe -t -i”<br />
; Force the addition of the specified parameters to be passed as extra parameters<br />
; to the sendmail binary. These parameters will always replace the value of<br />
; the 5th parameter to mail(), even in safe mode.<br />
;mail.force_extra_parameters =</p>
<p>按上面的方式把前面说的三个选项前面都加上分号，把sendmail_path前面的分号去掉下载下面的文件：</p>
<h3><a href="http://www.xuandun.net/wp-content/uploads/2009/11/sendmail.rar" target="_self">sendmail压缩包</a></h3>
<p>解压后找个地方放好，将里面sendmail.exe的地址填到sendmail_path并如上面所写增加-t -i参数（更多参数自己查吧）。<br />
打开：sendmail.ini文件<br />
修改里面的</p>
<p>smtp_server=smtp服务器地址<br />
auth_username=邮箱登录名<br />
auth_password=邮箱密码<br />
force_sender=发件人地址全写</p>
<p>ok了mail函数可以正常使用了，注意如果iis使用cgi模式运行php的话用sendmail方法会出错，修改为ISAPI模式后一切正常了。</p>
<p>如果不是自己的服务器的话用其他方法发吧，方法多得是！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.magic-jungle.com/?feed=rss2&amp;p=117</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
