<?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>南阳理工学院PHP资源站</title>
	<atom:link href="http://php.nyist.net/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://php.nyist.net</link>
	<description>发布PHP技术文章，PHP最新动态和我院服务器上使用PHP注意事项。</description>
	<lastBuildDate>Wed, 05 Aug 2009 13:00:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP基础入门</title>
		<link>http://php.nyist.net/?p=31</link>
		<comments>http://php.nyist.net/?p=31#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:58:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=31</guid>
		<description><![CDATA[简单说一下网站的发展，早期的网络，网上全是基本的文本文件，没有图片声音，也没有文字颜色，大小等修饰。后来HTML解决了这个问题，它负责修饰这些简陋的文本，还加上图片，声音等，再后来出现了js代码，使得网页可以加入简单的动态，逻辑功能。但还是太弱了，无法存储，修改用户数据，只有基本的“展示”功能。直到动态语言ASP，PHP，JSP等出现，结合各自的解析器和数据库，极大的加强网站的功能。
这些动态语言代码组成了一个网站的骨架，而网站的血肉（具体内容）则放置到数据库中，用户访问的时候，立即由语言解析器将相应数据库内容“填”入网页骨架中，形成普通的HTML页，再发送到用户浏览器中。这些HTML代码是实时生成，根据条件变化的，“动态”一词大约就是这意思。
现在的网站简单的说就是对数据库操作的包装，将普通用户简单的操作（如点击）转换成相应的SQL语句去操作数据库而己。所以数据库操作SQL语言是重中之重。
一。PHP特点
1。分界符内部的全被当成PHP代码，分界符外部的当成普通的HTML代码。分界符通常用&#60;?    ?&#62;和&#60;?php    ?&#62;两种。
2。以分号结束代码行。（结构语句特殊，可以不用分号）
3。变量用$号加变量名表示。
4。赋值用&#8217;='号，但比较是否相等用&#8217;==&#8217;，新手经常混淆。
5。许多功能都由相应的函数完成。函数的格式是函数名加括号。中间有为数不同的参数。
6。字符串要用单引号或双引号隔开。
二。连接mysql数据库。
假设已经装好mysql，并且用户名和密码为&#8217;user&#8217;和&#8217;pass&#8217;,数据库名为&#8217;dbname&#8217;,主机为localhost(若不装成本机改用其他IP）
1.连接数据库
mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;);
这个函数将返回一个连接字串（可以简单理解为钥匙，以免每次操作数据库都要重新输入用户名等信息）。通常将这个“钥匙”赋值给一个变量。以便以后引用
$link = mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;);
为了连接失败的时候，显示明显的出错信息，可以这样
$link = mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;) or die(&#8217;无法连接&#8217;);
这样当连接失败的时候，会显示&#8217;无法连接&#8217;,并且停止程序运行。
2。选择数据库
mysql_select_db(&#8217;dbname&#8217;,$link);
选择好后面将要操作的数据库。第一个参数是数据库名，第二个是第一步得到的&#8221;钥匙&#8221;。（不一定要用$link这个变量名的）
3。通常还要设置字符集以防乱码。
mysql_query(&#8221;set names &#8216;utf8&#8242;&#8221;);
 常用的有gb2312,gbk,utf8三种编码，根据你的数据库字符集和网页字符集来设置，要三方统一才不会乱码。
4。读取数据库内容
$rs = mysql_query($sql, $link);
第一个参数是具体的SQL语句，注意要加引号。第二个参数仍然第一步得到的“钥匙”。
例如：$rs = mysql_query(&#8221;SELECT * FROM user&#8221;, $link);
将返回整个user表的内容，不过这个时候的内容还只是资源集，还必须转换为数组或者对象的形式才方便PHP使用,请看下一步。
5。将资源集转换为数组（只有select语句后需要转换。）
$row = mysql_fetch_assoc($rs);
这样就将上一次得到的$rs资源集转成数组了。数组中的元素用$row['name']这样的形式读取。例如user表中有age字段表示年龄，那么此时echo $row['age']; 就能输出具体年龄了。或者用var_dump($row)就能输出整个数组（所有字段）。
除了mysql_fetch_assoc转换方式外，还有mysql_fetch_array和mysql_fetch_object等，不过新手只要学会一种就行了。
如果是好动手的同学，一定会发现上述的$row = mysql_fetch_assoc($rs);语句，只输出一行记录的值，而不是整个表。这是因为mysql_fetch_assoc函数只能转换一行数组，如果要全表都读出来，可以用循环。

PHP代码
while($row = mysql_fetch_assoc($rs)){   
    echo $row['age'];   
}   

while循环每一次转换一行，直到转换所有行为止。
三。与HTML的结合及美化
继续以上面的例子解说，如果要输出名字和年龄.将HTML代码作为字符串输出。
1.混合html代码。第一种形式。在PHP里镶入HTML代码。

PHP代码
echo &#8216;&#60;ul&#62;&#8217;;   
while($row = mysql_fetch_assoc($rs)){   
    echo &#8216;&#60;li&#62;姓名：&#8217;.$row['name'].&#8216;年龄：&#8221;.$row['age'].&#8217;&#60;/li&#62;&#8216;;  
}  
echo &#8217;&#60;/ul&#62;&#8217;;   

 2.第二种形式，第HTML里镶入PHP代码。适合大段HTML，少量PHP代码。

XML/HTML代码
&#60;table&#62;  
&#60;?  
while($row = mysql_fetch_assoc($rs)){   
?&#62;  
&#60;tr&#62;  
&#60;td&#62;姓名：&#60;?=$row['name']?&#62;&#60;/td&#62;            &#60;td&#62;年龄：&#60;?=$row['age']?&#62;&#60;/td&#62;       &#60;td&#62;照片：&#60;img src=&#8220;&#60;?=$row['path']?&#62;&#8221;&#62;&#60;/td&#62;  
&#60;/tr&#62;  
&#60;?  }    ?&#62;  
&#60;/table&#62;  

3.美观地查看数组值

PHP代码
echo &#8216;&#60;pre&#62;&#8217;;   
print_r($row);   
echo &#8216;&#60;/pre&#62;&#8217;;   

print_r是显示变量值的函数，可以显示数组，对象等复杂类型。而echo只能显示字符串，数字之类的简单型。但是print_r默认不分行的，显示得很难看，所以用html标记&#60;pre&#62;使其分行显示。
]]></description>
			<content:encoded><![CDATA[<p>简单说一下网站的发展，早期的网络，网上全是基本的文本文件，没有图片声音，也没有文字颜色，大小等修饰。后来HTML解决了这个问题，它负责修饰这些简陋的文本，还加上图片，声音等，再后来出现了js代码，使得网页可以加入简单的动态，逻辑功能。但还是太弱了，无法存储，修改用户数据，只有基本的“展示”功能。直到动态语言ASP，PHP，JSP等出现，结合各自的解析器和数据库，极大的加强网站的功能。<span id="more-31"></span></p>
<p>这些动态语言代码组成了一个网站的骨架，而网站的血肉（具体内容）则放置到数据库中，用户访问的时候，立即由语言解析器将相应数据库内容“填”入网页骨架中，形成普通的HTML页，再发送到用户浏览器中。这些HTML代码是实时生成，根据条件变化的，“动态”一词大约就是这意思。</p>
<p>现在的网站简单的说就是对数据库操作的包装，将普通用户简单的操作（如点击）转换成相应的SQL语句去操作数据库而己。所以数据库操作SQL语言是重中之重。</p>
<p><span style="color: #0000ff;">一。PHP特点</span></p>
<p>1。分界符内部的全被当成PHP代码，分界符外部的当成普通的HTML代码。分界符通常用&lt;?    ?&gt;和&lt;?php    ?&gt;两种。</p>
<p>2。以分号结束代码行。（结构语句特殊，可以不用分号）</p>
<p>3。变量用$号加变量名表示。</p>
<p>4。赋值用&#8217;='号，但比较是否相等用&#8217;==&#8217;，新手经常混淆。</p>
<p>5。许多功能都由相应的函数完成。函数的格式是函数名加括号。中间有为数不同的参数。</p>
<p>6。字符串要用单引号或双引号隔开。</p>
<p><span style="color: #0000ff;">二。连接mysql数据库。</span></p>
<p>假设已经装好mysql，并且用户名和密码为&#8217;user&#8217;和&#8217;pass&#8217;,数据库名为&#8217;dbname&#8217;,主机为localhost(若不装成本机改用其他IP）</p>
<p>1.连接数据库</p>
<p><span style="color: #3366ff;">mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;);</span></p>
<p>这个函数将返回一个连接字串（可以简单理解为钥匙，以免每次操作数据库都要重新输入用户名等信息）。通常将这个“钥匙”赋值给一个变量。以便以后引用</p>
<p><span style="color: #3366ff;">$link = mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;);</span></p>
<p>为了连接失败的时候，显示明显的出错信息，可以这样</p>
<p><span style="color: #3366ff;">$link = mysql_connect(&#8217;localhost&#8217;,'user&#8217;,'pass&#8217;) or die(&#8217;无法连接&#8217;);</span></p>
<p>这样当连接失败的时候，会显示&#8217;无法连接&#8217;,并且停止程序运行。</p>
<p>2。选择数据库</p>
<p><span style="color: #3366ff;">mysql_select_db(&#8217;dbname&#8217;,$link);</span></p>
<p>选择好后面将要操作的数据库。第一个参数是数据库名，第二个是第一步得到的&#8221;钥匙&#8221;。（不一定要用$link这个变量名的）</p>
<p>3。通常还要设置字符集以防乱码。</p>
<p><span style="color: #3366ff;">mysql_query(&#8221;set names &#8216;utf8&#8242;&#8221;);</span></p>
<p> 常用的有gb2312,gbk,utf8三种编码，根据你的数据库字符集和网页字符集来设置，要三方统一才不会乱码。</p>
<p>4。读取数据库内容</p>
<p><span style="color: #3366ff;">$rs = mysql_query($sql, $link);</span></p>
<p>第一个参数是具体的SQL语句，注意要加引号。第二个参数仍然第一步得到的“钥匙”。</p>
<p>例如：<span style="color: #3366ff;">$rs = mysql_query(&#8221;SELECT * FROM user&#8221;, $link);</span></p>
<p>将返回整个user表的内容，不过这个时候的内容还只是资源集，还必须转换为数组或者对象的形式才方便PHP使用,请看下一步。</p>
<p>5。将资源集转换为数组（只有select语句后需要转换。）</p>
<p><span style="color: #3366ff;">$row = mysql_fetch_assoc($rs);</span></p>
<p>这样就将上一次得到的$rs资源集转成数组了。数组中的元素用$row['name']这样的形式读取。例如user表中有age字段表示年龄，那么此时echo $row['age']; 就能输出具体年龄了。或者用var_dump($row)就能输出整个数组（所有字段）。</p>
<p>除了mysql_fetch_assoc转换方式外，还有mysql_fetch_array和mysql_fetch_object等，不过新手只要学会一种就行了。</p>
<p>如果是好动手的同学，一定会发现上述的$row = mysql_fetch_assoc($rs);语句，只输出一行记录的值，而不是整个表。这是因为mysql_fetch_assoc函数只能转换一行数组，如果要全表都读出来，可以用循环。</p>
<div>
<div>PHP代码</div>
<li><span><span>while</span><span>(</span><span>$row</span><span> = mysql_fetch_assoc(</span><span>$rs</span><span>)){   </span></span></li>
<li><span>    </span><span>echo</span><span> </span><span>$row</span><span>[</span><span>'age'</span><span>];   </span></li>
<li><span>}   </span></li>
</div>
<p>while循环每一次转换一行，直到转换所有行为止。</p>
<p>三。与HTML的结合及美化</p>
<p>继续以上面的例子解说，如果要输出名字和年龄.将HTML代码作为字符串输出。</p>
<p>1.混合html代码。第一种形式。在PHP里镶入HTML代码。</p>
<div>
<div>PHP代码</div>
<li><span><span>echo</span><span> </span><span>&#8216;&lt;ul&gt;&#8217;</span><span>;   </span></span></li>
<li><span>while</span><span>(</span><span>$row</span><span> = mysql_fetch_assoc(</span><span>$rs</span><span>)){   </span></li>
<li><span>    </span><span>echo</span><span> </span><span>&#8216;&lt;li&gt;姓名：&#8217;</span><span>.</span><span>$row</span><span>[</span><span>'name'</span><span>].</span><span>&#8216;年龄：&#8221;.$row['</span><span>age</span><span>'].&#8217;</span><span>&lt;/li&gt;</span><span>&#8216;; </span> </li>
<li><span><span>} </span> </span></li>
<li><span><span>echo &#8217;</span><span>&lt;/ul&gt;&#8217;;   </span></span></li>
</div>
<p> 2.第二种形式，第HTML里镶入PHP代码。适合大段HTML，少量PHP代码。</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>&lt;</span>table</span><span>&gt;</span><span>  </span></li>
<li><span>&lt;?</span><span>  </span></li>
<li>while<span>($</span><span>row</span><span> = </span>mysql_fetch_assoc<span>($rs)){   </span></li>
<li><span>?&gt;</span><span>  </span></li>
<li><span>&lt;</span>tr<span>&gt;</span><span>  </span></li>
<li><span>&lt;</span>td<span>&gt;</span><span>姓名：</span><span>&lt;?</span><span>=$row['name']</span><span>?&gt;</span><span>&lt;/</span>td<span>&gt;</span><span>            </span><span>&lt;</span>td<span>&gt;</span><span>年龄：</span><span>&lt;?</span><span>=$row['age']</span><span>?&gt;</span><span>&lt;/</span>td<span>&gt;</span><span>       </span><span>&lt;</span>td<span>&gt;</span><span>照片：</span><span>&lt;</span>img<span> </span><span>src</span><span>=</span>&#8220;&lt;?=$row['path']?&gt;&#8221;<span>&gt;</span><span>&lt;/</span>td<span>&gt;</span><span>  </span></li>
<li><span>&lt;/</span>tr<span>&gt;</span><span>  </span></li>
<li><span>&lt;?</span><span>  }    </span><span>?&gt;</span><span>  </span></li>
<li><span>&lt;/</span>table<span>&gt;</span><span>  </span></li>
</div>
<p>3.美观地查看数组值</p>
<div>
<div>PHP代码</div>
<li><span><span>echo</span><span> </span><span>&#8216;&lt;pre&gt;&#8217;</span><span>;   </span></span></li>
<li><span>print_r(</span><span>$row</span><span>);   </span></li>
<li><span>echo</span><span> </span><span>&#8216;&lt;/pre&gt;&#8217;</span><span>;   </span></li>
</div>
<p>print_r是显示变量值的函数，可以显示数组，对象等复杂类型。而echo只能显示字符串，数字之类的简单型。但是print_r默认不分行的，显示得很难看，所以用html标记&lt;pre&gt;使其分行显示。</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=31</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP中使用模板引擎</title>
		<link>http://php.nyist.net/?p=28</link>
		<comments>http://php.nyist.net/?p=28#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:55:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>
		<category><![CDATA[smarty]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=28</guid>
		<description><![CDATA[一.什么是模板？
使用模板引擎可以使业务逻辑与显示逻辑分开——这是很欠扁但也是网上公认的说法，呃，说得很准确，但估计只有会使用模板的人才能理解……其实刚开始大可以简单的理解模板为“PHP与HTML代码分离的方法”。
二。为什么要使用模板技术？
让程序（PHP层）与显示（HTML层）分离可以使代码更清晰易懂，要修改程序问题就去PHP层找，要改显示问题就去HTML层改。更重要的是这样的设计可以让不懂PHP的前台美工也能修改页面。如果不是很理解没关系，你只要知道这是迈向其它高级开发模式的必经之路就可以了。
三。有哪些模板技术？
我使用过PHPLIB库中的模板类，后来又使用了smarty和smartyLight,也试过原生的PHP方式实现的模板，现在大家基本上都用smarty。PHP方式相对来说最容易实现，学得也快，但不适合团队合作。
四。smarty广被攻击的“弱点”
smarty的语法太复杂，学它简直就是学一门新语言——其实你不需要复杂的功能，它就简单得很，如果你需要它复杂的功能，那你应该感谢它！根据我的经验，刚开始用一个东西，大家都喜欢简洁精炼，但随着应用的复杂，大多会抱怨它功能不足……
smarty有几百K，它太大了，慢！——其实大小与速度不成正比，smarty有编译缓存和静态缓存机制，甚至可以局部缓存
另外它的自定义插件用起来非常爽，modify,block等，我这几天正用它的block来输出页面组件。
 五。下载，配置smarty
因为我后来一直用smarty的简化版smartyLight,它们的语法大部分相同但也有不同，所以没办法把我现在的代码搬出来以免出错，好吧，为了写这篇，我去下载完整版smarty。
 http://www.smarty.net/download.php
下载2.6.18版的吧，最新的是2008的，不一定很稳定
其它目录都删了，保留libs目录就可以了，如果为了学习可以保留demo目录。
六。实战
使用模板引擎后，PHP代码与模板分离了，一般写一个应用都有PHP和HTML两个页面
PHP部分有三个部分组成：载入与配置、赋值、载入模板解析，其中第一部分是公用的，也就是放到公共页里以后都不需要再写的。第三部分即dispay方法，就一行代码，所以重点在第二部分。
（注：数组都分索引数组和关联数组两种来说明，索引数组即以数字为键的数组，关联数组是每个键有个字符串名称的数组，实在不理解就翻书去）
A。普通变量赋值与使用.

PHP代码
header(&#8216;Content-Type:text/html;charset=utf-8&#8242;);   
require &#8216;../libs/Smarty.class.php&#8217;;   
  
$smarty = new Smarty;   
  
$smarty-&#62;compile_check = true;   
$smarty-&#62;debugging = false; //调试时设为true   
  
//以上操作通常在包含页里,也就是说和数据库链接那样的操作类似,写一次就行了,根本不用记   
//下面是实际的代码,PHP部分没啥难的,各种类型的变量,数组,对象统统可以用assign方法赋值给模板.   
$smarty-&#62;assign(&#8220;name&#8221;,&#8220;星野天河&#8221;);                     //这句是第二部分。普通的变量   
$smarty-&#62;display(&#8216;index.tpl&#8217;); //载入模板  

 最后一句的display方法是载入默认模板目录下的index.tpl模板，当然可以修改默认的模板目录。假如要改到abc目录。（不要照抄啊，出错我不负责）

PHP代码
$smarty-&#62;template_dir = &#8216;/abc/&#8217;;  

模板部分（本例为index.tpl文件）

XML/HTML代码
普通变量的使用格式: {$name}&#60;br&#62;  

 这样大括号中的内容会被上面11行定义的name值代替。使用这个你可以把网页标题，关键字，站长名字、图片路径、js路径、网站根目录、文档根等信息都在包含页里直接赋值了（一次性操作），之后在模板里任何地方可以直接使用。路径问题也不至于错乱，修改起来也省事。
B。一维索引数组的赋值与使用

PHP代码
$smarty-&#62;assign(&#8220;persons&#8221;,array(&#8220;星野天河&#8221;,&#8220;小蕊&#8221;,&#8220;天空&#8221;,&#8220;西&#8221;,&#8216;奶瓶&#8217;));  

将数组丢给$persons变量，html中循环输出数组有两种格式。第一种如下

XML/HTML代码
{section name=item loop=$persons}   
    {$persons[item]}&#60;br&#62;  
{/section}  

section是smarty的循环结构， loop表示要循环哪个变量，这里是$persons这个变量(上面ＰＨＰ代码中赋值的数组),name表示循环中的每一项值用什么表示，可以随便取名的，例如叫item，那下面就要用{$persons[item]}表示数组中的一个项。
不过我更习惯使用第二种模式——foreach循环，因为与PHP格式接近，容易理解，并且更重要的是——省代码！效率也高些，记住下面的格式。

XML/HTML代码
{foreach item=person from=$persons}   
    {$person}&#60;br&#62;  
{/foreach}  

可以理解为把$persons数组拆开，每一项都丢进person变量中，与以下PHP代码完全一样。所以，把section忘了吧。

PHP代码
foreach($persons as $person){   
        echo $person;   
}  

C。一维关联数组
如果是一维相关数组的话，那更简单，不需要使用循环了。

PHP代码
$smarty-&#62;assign(&#8220;user&#8221;,array(&#8216;name&#8217;=&#62;&#8220;星野天河&#8221;,&#8216;iq&#8217;=&#62;138, &#8216;qq&#8217;=&#62;15957674));    //一维相关数组的赋值  


XML/HTML代码
一维关联数组的使用: {$user.name}: {$user.iq} {$user.qq}  

看见了吧，简单透顶，{$user.name}相当于PHP中的{$user['name']},这点和smarty简化版不同（我更喜欢后者的格式{$user[name]}
D.二维索引数组

PHP代码
$smarty-&#62;assign(&#8220;all&#8221;, array(array(1,2,3,4,5), array(6,7,8,9,10), array(11,12,13,14,15)));   


XML/HTML代码
{foreach item=nums from=$all}   
    {foreach item=num from=$nums}   
        {$num}   
    {/foreach}   
    &#60;br&#62;  
{/foreach}  

如果对操作PHP数组熟练,很容易理解这种循环镶套,第一轮把$all二维数组中的每一个元素拆到$nums变量中,第二轮再把$nums变量(这里是一维数组了)拆开丢进$num变量中.
E。二维关联数组的使用
PHP部分

PHP代码
$smarty-&#62;assign(&#8220;guests&#8221;, array(   
       array(&#8220;title&#8221; =&#62; &#8220;第一条留言的标题&#8221;, &#8220;content&#8221; =&#62; &#8220;第一条标题的内容&#8221;, &#8220;author&#8221; =&#62; &#8220;留言者小蕊&#8221;),           
        array(&#8220;title&#8221; =&#62; &#8220;第二条留言&#8221;, &#8220;content&#8221; =&#62; &#8220;今天带笔了,要签名的排队&#8221;, &#8220;author&#8221; =&#62; &#8220;星野大叔&#8221;))   
);  

实际的应用中,这个二维数组通常是数据库输出结果,所以为了模板使用方便,用db类吧,直接输出数组的那种.赶紧扔了那种wliel($row=mysql_fetch_assoc($rs)){ //一堆操作 }使用数据库的方式.
回归正题,看一下模板里怎么用二维关联数组吧.这回我不说累赘的section模式了.看foreach

XML/HTML代码
{foreach item=guest from=$guests}   
    {$guest.title}&#60;br&#62;  
    &#60;p&#62;{$guest.content}&#60;/p&#62;  
    留言者:{$guest.author}&#60;br&#62;  
{/foreach}  

应该能够理解,将二维数组中的每一个元素(通常是数据库中的每一条记录)扔进guest变量中,这个变量就是一维相关数组了,使用方式与一维相关数组完全相同.
F.三维,四维……
二维及其以上的数组都分不清是索引还是关联数组了，很可能是混合型的，但都是以以一维数组的方式为基的，只要理解数组的每一维属于哪种，用正常的方法解开（以上两种方式之一）一层一层解开就行了，不要看到N维数组就头痛。
呃说了一大堆，发现我只说数组，没有说对象如何使用，这是因为我大多用数组的关系，对象的循环与数组一样，只不过内部的使用格式不同罢了，可能{$item.id}变成{$item-&#62;id}这样子，因为很少用对象模式输出数据库内容，又一直用smartyLight,所以smarty的记不清了，但要使用的时候上百度，一分钟内就能找到答案。
 附：
一般默认配置就可以使用了，但要更好的使用可能需要改一下配置。

PHP代码
$tpl-&#62;template_dir = __SITE_ROOT . &#8220;/templates/&#8221;;    
$tpl-&#62;compile_dir = __SITE_ROOT . &#8220;/templates_c/&#8221;;    
$tpl-&#62;config_dir = __SITE_ROOT . &#8220;/configs/&#8221;;    
$tpl-&#62;cache_dir = __SITE_ROOT . &#8220;/cache/&#8221;;    
$tpl-&#62;left_delimiter = &#8216;&#60;{&#8217;;    
$tpl-&#62;right_delimiter = &#8216;}&#62;&#8217;;  

 template_dir是模板目录，compile_dir是编译目录（不理解没关系，但必须有这个目录)，最后两个是模板中使用变量的包含符，可以不用大括号以避开与js的冲突。这是因为js中有大括号
不过我还是喜欢用大括号做包含符，因为简单与习惯，也有办法避开js冲突。例如

XML/HTML代码
&#60;script&#62;  
{literal}   
function abc(){   
    //包含在{literal}中的代码不会被模板引擎解析，所以js中的大括号就与模板的大括号无关了。   
}   
{/literal}   
&#60;/script&#62;  
  

要注意只有在js中有大括号的时候才需要用literal包含，如果只是外链的js就不需要了，因为没有大括号。js的冲突与解决方法同样适合于css代码。改模板包含符还是使用literal看你喜好了
 
总结：
其实用smarty还是很简单的，只不过把使用变量的方式改一下、再用DB类直接输出数组代替原来的过程式写法（如果不这么做，使用smarty会比较麻烦)，重点就是记格式了，理解上没有难点。
附带说个非常有用的功能

XML/HTML代码
{include file=&#8220;header.tpl&#8221; title=foo}  

 在模板中可以用这个加载其它模板，而且你赋值的变量，在载入页 (header.tpl)中仍然可以使用，不像phplib模板类那样还要再赋值。后面带的参数任意，title=foo表示在header.tpl页中，$title变量值改为foo,这很有用，因为头文件中，通常标题，关键字，css文件路径要重新定义的。
之后的进阶功能还有很多，不过做为入门教程，这里写的已经可以打发一段时间了，高级功能嘛，有朋友问的时候再写，俺一向比较懒
]]></description>
			<content:encoded><![CDATA[<p>一.什么是模板？</p>
<p>使用模板引擎可以使业务逻辑与显示逻辑分开——这是很欠扁但也是网上公认的说法，呃，说得很准确，但估计只有会使用模板的人才能理解……其实刚开始大可以简单的理解模板为“PHP与HTML代码分离的方法”。<span id="more-28"></span></p>
<p><span style="color: #008080;">二。为什么要使用模板技术？</span></p>
<p>让程序（PHP层）与显示（HTML层）分离可以使代码更清晰易懂，要修改程序问题就去PHP层找，要改显示问题就去HTML层改。更重要的是这样的设计可以让不懂PHP的前台美工也能修改页面。如果不是很理解没关系，你只要知道这是迈向其它高级开发模式的必经之路就可以了。</p>
<p><span style="color: #008080;">三。有哪些模板技术？</span></p>
<p>我使用过PHPLIB库中的模板类，后来又使用了smarty和smartyLight,也试过原生的PHP方式实现的模板，现在大家基本上都用smarty。PHP方式相对来说最容易实现，学得也快，但不适合团队合作。</p>
<p><span style="color: #008080;">四。smarty广被攻击的“弱点”</span></p>
<p>smarty的语法太复杂，学它简直就是学一门新语言——其实你不需要复杂的功能，它就简单得很，如果你需要它复杂的功能，那你应该感谢它！根据我的经验，刚开始用一个东西，大家都喜欢简洁精炼，但随着应用的复杂，大多会抱怨它功能不足……</p>
<p>smarty有几百K，它太大了，慢！——其实大小与速度不成正比，smarty有编译缓存和静态缓存机制，甚至可以局部缓存</p>
<p>另外它的自定义插件用起来非常爽，modify,block等，我这几天正用它的block来输出页面组件。</p>
<p> <span style="color: #008080;">五。下载，配置smarty</span></p>
<p>因为我后来一直用smarty的简化版smartyLight,它们的语法大部分相同但也有不同，所以没办法把我现在的代码搬出来以免出错，好吧，为了写这篇，我去下载完整版smarty。</p>
<p> <a href="http://www.smarty.net/download.php">http://www.smarty.net/download.php</a></p>
<p>下载2.6.18版的吧，最新的是2008的，不一定很稳定</p>
<p>其它目录都删了，保留libs目录就可以了，如果为了学习可以保留demo目录。</p>
<p><span style="color: #008080;">六。实战</span></p>
<p>使用模板引擎后，PHP代码与模板分离了，一般写一个应用都有PHP和HTML两个页面</p>
<p>PHP部分有三个部分组成：载入与配置、赋值、载入模板解析，其中第一部分是公用的，也就是放到公共页里以后都不需要再写的。第三部分即dispay方法，就一行代码，所以重点在第二部分。</p>
<p>（注：数组都分索引数组和关联数组两种来说明，索引数组即以数字为键的数组，关联数组是每个键有个字符串名称的数组，实在不理解就翻书去）</p>
<p><span style="color: #800080;">A。普通变量赋值与使用.</span></p>
<div>
<div>PHP代码</div>
<li><span><span>header(</span><span>&#8216;Content-Type:text/html;charset=utf-8&#8242;</span><span>);   </span></span></li>
<li><span>require</span><span> </span><span>&#8216;../libs/Smarty.class.php&#8217;</span><span>;   </span></li>
<li><span>  </span></li>
<li><span>$smarty</span><span> = </span><span>new</span><span> Smarty;   </span></li>
<li><span>  </span></li>
<li><span>$smarty</span><span>-&gt;compile_check = true;   </span></li>
<li><span>$smarty</span><span>-&gt;debugging = false; </span><span>//调试时设为true </span><span>  </span></li>
<li><span>  </span></li>
<li><span>//以上操作通常在包含页里,也就是说和数据库链接那样的操作类似,写一次就行了,根本不用记 </span><span>  </span></li>
<li><span>//下面是实际的代码,PHP部分没啥难的,各种类型的变量,数组,对象统统可以用assign方法赋值给模板. </span><span>  </span></li>
<li><span>$smarty</span><span>-&gt;assign(</span><span>&#8220;name&#8221;</span><span>,</span><span>&#8220;星野天河&#8221;</span><span>);                     </span><span>//这句是第二部分。普通的变量 </span><span>  </span></li>
<li><span>$smarty</span><span>-&gt;display(</span><span>&#8216;index.tpl&#8217;</span><span>); //载入模板  </span></li>
</div>
<p> 最后一句的display方法是载入默认模板目录下的index.tpl模板，当然可以修改默认的模板目录。假如要改到abc目录。（不要照抄啊，出错我不负责）</p>
<div>
<div>PHP代码</div>
<li><span><span>$smarty</span><span>-&gt;template_dir = </span><span>&#8216;/abc/&#8217;</span><span>;  </span></span></li>
</div>
<p>模板部分（本例为index.tpl文件）</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>普通变量的使用格式: {$name}</span><span>&lt;</span>br</span><span>&gt;</span><span>  </span></li>
</div>
<p> 这样大括号中的内容会被上面11行定义的name值代替。使用这个你可以把网页标题，关键字，站长名字、图片路径、js路径、网站根目录、文档根等信息都在包含页里直接赋值了（一次性操作），之后在模板里任何地方可以直接使用。路径问题也不至于错乱，修改起来也省事。</p>
<p><span style="color: #800080;">B。一维索引数组的赋值与使用</span></p>
<div>
<div>PHP代码</div>
<li><span><span>$smarty</span><span>-&gt;assign(</span><span>&#8220;persons&#8221;</span><span>,</span><span>array</span><span>(</span><span>&#8220;星野天河&#8221;</span><span>,</span><span>&#8220;小蕊&#8221;</span><span>,</span><span>&#8220;天空&#8221;</span><span>,</span><span>&#8220;西&#8221;</span><span>,</span><span>&#8216;奶瓶&#8217;</span><span>));  </span></span></li>
</div>
<p>将数组丢给$persons变量，html中循环输出数组有两种格式。第一种如下</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>{section </span><span>name</span><span>=</span>item</span><span> </span><span>loop</span><span>=$persons}   </span></li>
<li><span>    {$persons[item]}</span><span>&lt;</span>br<span>&gt;</span><span>  </span></li>
<li><span>{/section}  </span></li>
</div>
<p>section是smarty的循环结构， loop表示要循环哪个变量，这里是$persons这个变量(上面ＰＨＰ代码中赋值的数组),name表示循环中的每一项值用什么表示，可以随便取名的，例如叫item，那下面就要用{$persons[item]}表示数组中的一个项。</p>
<p>不过我更习惯使用第二种模式——foreach循环，因为与PHP格式接近，容易理解，并且更重要的是——省代码！效率也高些，记住下面的格式。</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>{foreach </span><span>item</span><span>=</span>person</span><span> </span><span>from</span><span>=$persons}   </span></li>
<li><span>    {$person}</span><span>&lt;</span>br<span>&gt;</span><span>  </span></li>
<li><span>{/foreach}  </span></li>
</div>
<p>可以理解为把$persons数组拆开，每一项都丢进person变量中，与以下PHP代码完全一样。所以，把section忘了吧。</p>
<div>
<div>PHP代码</div>
<li><span><span>foreach</span><span>(</span><span>$persons</span><span> </span><span>as</span><span> </span><span>$person</span><span>){   </span></span></li>
<li><span>        </span><span>echo</span><span> </span><span>$person</span><span>;   </span></li>
<li><span>}  </span></li>
</div>
<p><span style="color: #800080;">C。一维关联数组</span></p>
<p>如果是一维相关数组的话，那更简单，不需要使用循环了。</p>
<div>
<div>PHP代码</div>
<li><span><span>$smarty</span><span>-&gt;assign(</span><span>&#8220;user&#8221;</span><span>,</span><span>array</span><span>(</span><span>&#8216;name&#8217;</span><span>=&gt;</span><span>&#8220;星野天河&#8221;</span><span>,</span><span>&#8216;iq&#8217;</span><span>=&gt;138, </span><span>&#8216;qq&#8217;</span><span>=&gt;15957674));    </span><span>//一维相关数组的赋值</span><span>  </span></span></li>
</div>
<div>
<div>XML/HTML代码</div>
<li><span><span>一维关联数组的使用: {$user.name}: {$user.iq} {$user.qq}  </span></span></li>
</div>
<p>看见了吧，简单透顶，{$user.name}相当于PHP中的{$user['name']},这点和smarty简化版不同（我更喜欢后者的格式{$user[name]}</p>
<p><span style="color: #800080;">D.二维索引数组</span></p>
<div>
<div>PHP代码</div>
<li><span><span>$smarty</span><span>-&gt;assign(</span><span>&#8220;all&#8221;</span><span>, </span><span>array</span><span>(</span><span>array</span><span>(1,2,3,4,5), </span><span>array</span><span>(6,7,8,9,10), </span><span>array</span><span>(11,12,13,14,15)));   </span></span></li>
</div>
<div>
<div>XML/HTML代码</div>
<li><span><span>{foreach </span><span>item</span><span>=</span>nums</span><span> </span><span>from</span><span>=$all}   </span></li>
<li><span>    {foreach </span><span>item</span><span>=</span>num<span> </span><span>from</span><span>=$nums}   </span></li>
<li><span>        {$num}   </span></li>
<li><span>    {/foreach}   </span></li>
<li><span>    </span><span>&lt;</span>br<span>&gt;</span><span>  </span></li>
<li><span>{/foreach}  </span></li>
</div>
<p>如果对操作PHP数组熟练,很容易理解这种循环镶套,第一轮把$all二维数组中的每一个元素拆到$nums变量中,第二轮再把$nums变量(这里是一维数组了)拆开丢进$num变量中.</p>
<p><span style="color: #800080;">E。二维关联数组的使用</span></p>
<p>PHP部分</p>
<div>
<div>PHP代码</div>
<li><span><span>$smarty</span><span>-&gt;assign(</span><span>&#8220;guests&#8221;</span><span>, </span><span>array</span><span>(   </span></span></li>
<li><span>       </span><span>array</span><span>(</span><span>&#8220;title&#8221;</span><span> =&gt; </span><span>&#8220;第一条留言的标题&#8221;</span><span>, </span><span>&#8220;content&#8221;</span><span> =&gt; </span><span>&#8220;第一条标题的内容&#8221;</span><span>, </span><span>&#8220;author&#8221;</span><span> =&gt; </span><span>&#8220;留言者小蕊&#8221;</span><span>),           </span></li>
<li><span>        </span><span>array</span><span>(</span><span>&#8220;title&#8221;</span><span> =&gt; </span><span>&#8220;第二条留言&#8221;</span><span>, </span><span>&#8220;content&#8221;</span><span> =&gt; </span><span>&#8220;今天带笔了,要签名的排队&#8221;</span><span>, </span><span>&#8220;author&#8221;</span><span> =&gt; </span><span>&#8220;星野大叔&#8221;</span><span>))   </span></li>
<li><span>);  </span></li>
</div>
<p>实际的应用中,这个二维数组通常是数据库输出结果,所以为了模板使用方便,用db类吧,直接输出数组的那种.赶紧扔了那种wliel($row=mysql_fetch_assoc($rs)){ //一堆操作 }使用数据库的方式.</p>
<p>回归正题,看一下模板里怎么用二维关联数组吧.这回我不说累赘的section模式了.看foreach</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>{foreach </span><span>item</span><span>=</span>guest</span><span> </span><span>from</span><span>=$guests}   </span></li>
<li><span>    {$guest.title}</span><span>&lt;</span>br<span>&gt;</span><span>  </span></li>
<li><span>    </span><span>&lt;</span>p<span>&gt;</span><span>{$guest.content}</span><span>&lt;/</span>p<span>&gt;</span><span>  </span></li>
<li><span>    留言者:{$guest.author}</span><span>&lt;</span>br<span>&gt;</span><span>  </span></li>
<li><span>{/foreach}  </span></li>
</div>
<p>应该能够理解,将二维数组中的每一个元素(通常是数据库中的每一条记录)扔进guest变量中,这个变量就是一维相关数组了,使用方式与一维相关数组完全相同.</p>
<p><span style="color: #800080;">F.三维,四维……</span></p>
<p>二维及其以上的数组都分不清是索引还是关联数组了，很可能是混合型的，但都是以以一维数组的方式为基的，只要理解数组的每一维属于哪种，用正常的方法解开（以上两种方式之一）一层一层解开就行了，不要看到N维数组就头痛。</p>
<p>呃说了一大堆，发现我只说数组，没有说对象如何使用，这是因为我大多用数组的关系，对象的循环与数组一样，只不过内部的使用格式不同罢了，可能{$item.id}变成{$item-&gt;id}这样子，因为很少用对象模式输出数据库内容，又一直用smartyLight,所以smarty的记不清了，但要使用的时候上百度，一分钟内就能找到答案。</p>
<p><span style="color: #ff0000;"> 附：</span></p>
<p>一般默认配置就可以使用了，但要更好的使用可能需要改一下配置。</p>
<div>
<div>PHP代码</div>
<li><span><span>$tpl</span><span>-&gt;template_dir = __SITE_ROOT . </span><span>&#8220;/templates/&#8221;</span><span>;    </span></span></li>
<li><span>$tpl</span><span>-&gt;compile_dir = __SITE_ROOT . </span><span>&#8220;/templates_c/&#8221;</span><span>;    </span></li>
<li><span>$tpl</span><span>-&gt;config_dir = __SITE_ROOT . </span><span>&#8220;/configs/&#8221;</span><span>;    </span></li>
<li><span>$tpl</span><span>-&gt;cache_dir = __SITE_ROOT . </span><span>&#8220;/cache/&#8221;</span><span>;    </span></li>
<li><span>$tpl</span><span>-&gt;left_delimiter = </span><span>&#8216;&lt;{&#8217;</span><span>;    </span></li>
<li><span>$tpl</span><span>-&gt;right_delimiter = </span><span>&#8216;}&gt;&#8217;</span><span>;  </span></li>
</div>
<p> template_dir是模板目录，compile_dir是编译目录（不理解没关系，但必须有这个目录)，最后两个是模板中使用变量的包含符，可以不用大括号以避开与js的冲突。这是因为js中有大括号</p>
<p>不过我还是喜欢用大括号做包含符，因为简单与习惯，也有办法避开js冲突。例如</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>&lt;</span>script</span><span>&gt;</span><span>  </span></li>
<li><span>{literal}   </span></li>
<li><span>function abc(){   </span></li>
<li><span>    //包含在{literal}中的代码不会被模板引擎解析，所以js中的大括号就与模板的大括号无关了。   </span></li>
<li><span>}   </span></li>
<li><span>{/literal}   </span></li>
<li><span>&lt;/</span>script<span>&gt;</span><span>  </span></li>
<li><span>  </span></li>
</div>
<p>要注意只有在js中有大括号的时候才需要用literal包含，如果只是外链的js就不需要了，因为没有大括号。js的冲突与解决方法同样适合于css代码。改模板包含符还是使用literal看你喜好了</p>
<p> </p>
<p><span style="font-size: large; color: #0000ff;"><strong>总结：</strong></span></p>
<p>其实用smarty还是很简单的，只不过把使用变量的方式改一下、再用DB类直接输出数组代替原来的过程式写法（如果不这么做，使用smarty会比较麻烦)，重点就是记格式了，理解上没有难点。</p>
<p>附带说个非常有用的功能</p>
<div>
<div>XML/HTML代码</div>
<li><span><span>{include </span><span>file</span><span>=</span>&#8220;header.tpl&#8221;</span><span> </span><span>title</span><span>=</span>foo<span>}  </span></li>
</div>
<p> 在模板中可以用这个加载其它模板，而且你赋值的变量，在载入页 (header.tpl)中仍然可以使用，不像phplib模板类那样还要再赋值。后面带的参数任意，title=foo表示在header.tpl页中，$title变量值改为foo,这很有用，因为头文件中，通常标题，关键字，css文件路径要重新定义的。</p>
<p>之后的进阶功能还有很多，不过做为入门教程，这里写的已经可以打发一段时间了，高级功能嘛，有朋友问的时候再写，俺一向比较懒</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=28</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP5中的PDO使用入门</title>
		<link>http://php.nyist.net/?p=26</link>
		<comments>http://php.nyist.net/?p=26#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:53:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>
		<category><![CDATA[pdo]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=26</guid>
		<description><![CDATA[以前由于兼容性的问题，一直只封装了mysql和mysqli，没有封装pdo，不过我想现在已经没有必要死拖着php4不放了，应该彻底面对PHP5及其后版本。
优点：
1.效率更高
类似于adodb，phplib等库，pdo支持多种数据库，也就是说如果不使用mysql做为数据库程序也不需要进行什么更改，仅仅改一个参数就行了，由于pdo对多数据库操作的封装是用C实现的，因此比adodb等PHP实现方式效率更高，并且以后的php6版本也不再支
持mysql系列函数。
在连续执行相同结构的sql时，可以先预备好结构，最后一次性执行，这样也会提升效率。
2.更安全
输入sql使用占位符的方式，基本消除sql注入现象发生。当然以前的方式过滤得当也同样安全。
为了不修改程序，封装了PDO的操作。

PHP代码
&#60;?php  
/** 
 * 虽然尽量照顾到mysql和mysqli的兼容性,没有使用占位符模式,不过最近加入的新办法仍有可能没加入mysql,mysqli中 
 * 
 */  
class db extends PDO  
{  
    var $count;     //记录执行语句数.  
    var $sql;       //记录全部sql和运行间隔  
    var $startTime;     //开始时间,基本上整个页面的开始时间与db类开始运行时的时间很接近,误差在0.005秒左右,要求不严格情况下可以当作页面开始时间  
    var $runTime;       //记录上次运行时间  
    /** 
     * 用pdo连接mysql 
     */  
    public function __construct($user, $pass, $dbname, $host=&#8220;localhost&#8221;,  $charset = &#8220;utf8&#8243;, $options = array(PDO::ATTR_PERSISTENT =&#62; true))  
    {  
        try{  
            parent::__construct(&#8220;mysql:host=&#8221;.$host.&#8220;;dbname=&#8221;.$dbname, $user, $pass, $options);  
            $this-&#62;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);   //异常处理：也可以使用PDO默认的异常处理ERRMODE_EXCEPTION  
            $this-&#62;setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);    //fetch模式，关联数组  
            $this-&#62;query(&#8220;SET NAMES &#8217;$charset&#8217;&#8221;);       //连接字符集  
            if(DEBUG){  
                $this-&#62;startTime = microtime();  
                $this-&#62;runTime = $this-&#62;startTime;  
            }  
        }catch (PDOException $e){  
            die(&#8216;无法连接mysql，请检查参数&#8217;);  
        }  
    }  
      
    /** 
     * 取得所有数据,返回二维数组，可使用占位符 
     * @example getAll(&#8221;select * from test&#8221;) 
     * @return array 
     */  
    public function getAll($sql)  
    {  
        $rs = $this-&#62;prepare($sql);  
        $params = func_get_args();  
        $paramsCnt = count($params);  
        for ($i=1; $i&#60;$paramsCnt; $i++) {  
            $rs-&#62;bindParam($i, $params[$i]);  
        }  
  
        $rs-&#62;execute();  
        $all = $rs-&#62;fetchAll();  
        if(DEBUG) self::debug($sql);  
        unset($rs);  
        return $all;  
    }  
      
    /** 
     * 取单行记录,可以用传统sql语句方式，或者占位符方式，可以有任意多个占位符 
     * @example getRow(&#8221;select * from test where id = 11&#8243;) 
     * @example getRow(&#8221;select * from test where id &#62; ? and gender = ?&#8221;, $id, 1); 
     * @return 一维数组 
     */  
    public function getOne($sql)  
    {  
  
        $rs = $this-&#62;prepare($sql);  
        $params = func_get_args();  
        $paramsCnt = count($params);  
        for ($i=1; $i&#60;$paramsCnt; $i++) {  
            $rs-&#62;bindParam($i, $params[$i]);  
        }  
        $rs-&#62;execute();  
        $row = $rs-&#62;fetch();  
          
        if(DEBUG) self::debug($sql);  
        unset($rs);  
        return $row;  
    }  
      
    /** 
     * 取第一条记录第一个字段的值，用于只需要取一个字段的情况，也可用于复杂的统计记录数 
     * @example getOne(&#8221;select count(*) from test&#8221;);    //统计记录数 
     * @example getOne(&#8221;select count(*) from test where username=? and grade=?&#8221;, $username, $grade); 
     */  
    public function getField($sql)  
    {  
        $rs = $this-&#62;prepare($sql);  
        $params = func_get_args();  
        $paramsCnt = count($params);  
        for ($i=1; $i&#60;$paramsCnt; $i++) {  
            $rs-&#62;bindParam($i, $params[$i]);  
        }  
        $rs-&#62;execute();  
        $value = $rs-&#62;fetchColumn();  
        if(DEBUG) self::debug($sql);  
        unset($rs);  
        return $value;  
    }  
    /** 
     * 扩展PDO::exec()，增加占位符功能 
     * @param string    $sql 
     * @param int&#124;bool  失败返回false.update和delete成功返回影响的行数，insert返回插入的id 
     */  
    public function exec($sql)  
    {  
        $rs = $this-&#62;prepare($sql);  
        $params = func_get_args();  
        $paramsCnt = count($params);  
        for ($i=1; $i&#60;$paramsCnt; $i++) {  
            $rs-&#62;bindParam($i, $params[$i]);  
        }  
        $retval = $rs-&#62;execute();  
        if ($retval === false) return false;  
        if(strpos(strtolower($sql), &#8216;insert&#8217;) !==false) {  
            return $this-&#62;lastInsertId();  
        }  
        if(DEBUG) self::debug($sql);  
        return $rs-&#62;rowCount();  
    }  
      
    /** 
     * 计算符合条件的记录总数.如果语句较复杂，可以用getField达到同样效果 
     * @param str $table        表名 
     * @param str $condition    记录必须符合的条件.如&#8221;id &#62; 100&#8243; 
     * @return int          总数 
     * 例：  $num = $db-&#62;dbCount(&#8217;t_person&#8217;); 
     *  $num = $db-&#62;dbCount(&#8217;t_person&#8217;, &#8217;p_id &#62; 100&#8242;, &#8217;p_id&#8217;); 
     */  
    function dbCount($table, $condition = &#8221;, $field=&#8216;*&#8217;)  
    {  
        if($condition != &#8221;) {  
            if(strtoupper(substr(trim($condition),0,5)) != &#8216;WHERE&#8217;) $condition = &#8220;WHERE $condition&#8221;;  
        }  
        $sql = &#8220;SELECT COUNT($field) FROM `$table` $condition&#8221;;  
        //这里不统计sql语句，因为在getField方法里统计了  
        return $this-&#62;getField($sql);  
    }  
  
    /** 
     * 常用于分页中，取记录集时要limit，但统计总数又得忽略limit，郁闷啊，以前老是要另写一句统计总数.呵呵，现在爽了 
     * 用法： 
     * $rs = $db-&#62;getAll(&#8221;SELECT SQL_CALC_FOUND_ROWS * FROM t_person LIMIT ?, ?&#8221;, $start, $end); 
     * $total = $db-&#62;foundRows(); 
     */  
    public function foundRows()  
    {  
        $rs = $this-&#62;query(&#8216;SELECT found_rows()&#8217;);  
        return $rs-&#62;fetchColumn();  
    }  
  

    //取最大值  
    function getMax($table, $field, $condition=&#8221;){  
        if(!emptyempty($condition)) $condition = &#8216;WHERE &#8217;.$condition;  
        $sql = &#8220;SELECT max(`&#8221;.$field.&#8220;`) FROM `$table` $condition&#8221;;  
        return $this-&#62;getField($sql);  
    }  
    //取最小值  
    function getMin($table, $field, $condition=&#8221;){  
        if(!emptyempty($condition)) $condition = &#8216;WHERE &#8217;.$condition;  
        $sql = &#8220;SELECT min(`&#8221;.$field.&#8220;`) FROM `$table` $condition&#8221;;  
        $this-&#62;getField($sql);  
    }  
} 

]]></description>
			<content:encoded><![CDATA[<p>以前由于兼容性的问题，一直只封装了mysql和mysqli，没有封装pdo，不过我想现在已经没有必要死拖着php4不放了，应该彻底面对PHP5及其后版本。<span id="more-26"></span></p>
<p>优点：</p>
<p>1.效率更高</p>
<p>类似于adodb，phplib等库，pdo支持多种数据库，也就是说如果不使用mysql做为数据库程序也不需要进行什么更改，仅仅改一个参数就行了，由于pdo对多数据库操作的封装是用C实现的，因此比adodb等PHP实现方式效率更高，并且以后的php6版本也不再支</p>
<p>持mysql系列函数。</p>
<p>在连续执行相同结构的sql时，可以先预备好结构，最后一次性执行，这样也会提升效率。</p>
<p>2.更安全</p>
<p>输入sql使用占位符的方式，基本消除sql注入现象发生。当然以前的方式过滤得当也同样安全。</p>
<p>为了不修改程序，封装了PDO的操作。</p>
<div>
<div>PHP代码</div>
<li><span><span>&lt;?php  </span></span></li>
<li><span><span>/**</span> </span></li>
<li><span><span> * 虽然尽量照顾到mysql和mysqli的兼容性,没有使用占位符模式,不过最近加入的新办法仍有可能没加入mysql,mysqli中</span> </span></li>
<li><span><span> *</span> </span></li>
<li><span><span> */</span><span>  </span></span></li>
<li><span><span>class</span><span> db </span><span>extends</span><span> PDO  </span></span></li>
<li><span>{  </span></li>
<li><span>    <span>var</span><span> </span><span>$count</span><span>;     </span><span>//记录执行语句数.</span><span>  </span></span></li>
<li><span>    <span>var</span><span> </span><span>$sql</span><span>;       </span><span>//记录全部sql和运行间隔</span><span>  </span></span></li>
<li><span>    <span>var</span><span> </span><span>$startTime</span><span>;     </span><span>//开始时间,基本上整个页面的开始时间与db类开始运行时的时间很接近,误差在0.005秒左右,要求不严格情况下可以当作页面开始时间</span><span>  </span></span></li>
<li><span>    <span>var</span><span> </span><span>$runTime</span><span>;       </span><span>//记录上次运行时间</span><span>  </span></span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 用pdo连接mysql</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> __construct(</span><span>$user</span><span>, </span><span>$pass</span><span>, </span><span>$dbname</span><span>, </span><span>$host</span><span>=</span><span>&#8220;localhost&#8221;</span><span>,  </span><span>$charset</span><span> = </span><span>&#8220;utf8&#8243;</span><span>, </span><span>$options</span><span> = </span><span>array</span><span>(PDO::ATTR_PERSISTENT =&gt; true))  </span></span></li>
<li><span>    {  </span></li>
<li><span>        try{  </span></li>
<li><span>            parent::__construct(<span>&#8220;mysql:host=&#8221;</span><span>.</span><span>$host</span><span>.</span><span>&#8220;;dbname=&#8221;</span><span>.</span><span>$dbname</span><span>, </span><span>$user</span><span>, </span><span>$pass</span><span>, </span><span>$options</span><span>);  </span></span></li>
<li><span>            <span>$this</span><span>-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);   </span><span>//异常处理：也可以使用PDO默认的异常处理ERRMODE_EXCEPTION</span><span>  </span></span></li>
<li><span>            <span>$this</span><span>-&gt;setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);    </span><span>//fetch模式，关联数组</span><span>  </span></span></li>
<li><span>            <span>$this</span><span>-&gt;query(</span><span>&#8220;SET NAMES &#8217;$charset&#8217;&#8221;</span><span>);       </span><span>//连接字符集</span><span>  </span></span></li>
<li><span>            <span>if</span><span>(DEBUG){  </span></span></li>
<li><span>                <span>$this</span><span>-&gt;startTime = microtime();  </span></span></li>
<li><span>                <span>$this</span><span>-&gt;runTime = </span><span>$this</span><span>-&gt;startTime;  </span></span></li>
<li><span>            }  </span></li>
<li><span>        }catch (PDOException <span>$e</span><span>){  </span></span></li>
<li><span>            <span>die</span><span>(</span><span>&#8216;无法连接mysql，请检查参数&#8217;</span><span>);  </span></span></li>
<li><span>        }  </span></li>
<li><span>    }  </span></li>
<li><span>      </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 取得所有数据,返回二维数组，可使用占位符</span> </span></li>
<li><span><span>     * @example getAll(&#8221;select * from test&#8221;)</span> </span></li>
<li><span><span>     * @return array</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> getAll(</span><span>$sql</span><span>)  </span></span></li>
<li><span>    {  </span></li>
<li><span>        <span>$rs</span><span> = </span><span>$this</span><span>-&gt;prepare(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        <span>$params</span><span> = func_get_args();  </span></span></li>
<li><span>        <span>$paramsCnt</span><span> = </span><span>count</span><span>(</span><span>$params</span><span>);  </span></span></li>
<li><span>        <span>for</span><span> (</span><span>$i</span><span>=1; </span><span>$i</span><span>&lt;</span><span>$paramsCnt</span><span>; </span><span>$i</span><span>++) {  </span></span></li>
<li><span>            <span>$rs</span><span>-&gt;bindParam(</span><span>$i</span><span>, </span><span>$params</span><span>[</span><span>$i</span><span>]);  </span></span></li>
<li><span>        }  </span></li>
<li><span>  </span></li>
<li><span>        <span>$rs</span><span>-&gt;execute();  </span></span></li>
<li><span>        <span>$all</span><span> = </span><span>$rs</span><span>-&gt;fetchAll();  </span></span></li>
<li><span>        <span>if</span><span>(DEBUG) self::debug(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        unset(<span>$rs</span><span>);  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$all</span><span>;  </span></span></li>
<li><span>    }  </span></li>
<li><span>      </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 取单行记录,可以用传统sql语句方式，或者占位符方式，可以有任意多个占位符</span> </span></li>
<li><span><span>     * @example getRow(&#8221;select * from test where id = 11&#8243;)</span> </span></li>
<li><span><span>     * @example getRow(&#8221;select * from test where id &gt; ? and gender = ?&#8221;, $id, 1);</span> </span></li>
<li><span><span>     * @return 一维数组</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> getOne(</span><span>$sql</span><span>)  </span></span></li>
<li><span>    {  </span></li>
<li><span>  </span></li>
<li><span>        <span>$rs</span><span> = </span><span>$this</span><span>-&gt;prepare(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        <span>$params</span><span> = func_get_args();  </span></span></li>
<li><span>        <span>$paramsCnt</span><span> = </span><span>count</span><span>(</span><span>$params</span><span>);  </span></span></li>
<li><span>        <span>for</span><span> (</span><span>$i</span><span>=1; </span><span>$i</span><span>&lt;</span><span>$paramsCnt</span><span>; </span><span>$i</span><span>++) {  </span></span></li>
<li><span>            <span>$rs</span><span>-&gt;bindParam(</span><span>$i</span><span>, </span><span>$params</span><span>[</span><span>$i</span><span>]);  </span></span></li>
<li><span>        }  </span></li>
<li><span>        <span>$rs</span><span>-&gt;execute();  </span></span></li>
<li><span>        <span>$row</span><span> = </span><span>$rs</span><span>-&gt;fetch();  </span></span></li>
<li><span>          </span></li>
<li><span>        <span>if</span><span>(DEBUG) self::debug(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        unset(<span>$rs</span><span>);  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$row</span><span>;  </span></span></li>
<li><span>    }  </span></li>
<li><span>      </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 取第一条记录第一个字段的值，用于只需要取一个字段的情况，也可用于复杂的统计记录数</span> </span></li>
<li><span><span>     * @example getOne(&#8221;select count(*) from test&#8221;);    //统计记录数</span> </span></li>
<li><span><span>     * @example getOne(&#8221;select count(*) from test where username=? and grade=?&#8221;, $username, $grade);</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> getField(</span><span>$sql</span><span>)  </span></span></li>
<li><span>    {  </span></li>
<li><span>        <span>$rs</span><span> = </span><span>$this</span><span>-&gt;prepare(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        <span>$params</span><span> = func_get_args();  </span></span></li>
<li><span>        <span>$paramsCnt</span><span> = </span><span>count</span><span>(</span><span>$params</span><span>);  </span></span></li>
<li><span>        <span>for</span><span> (</span><span>$i</span><span>=1; </span><span>$i</span><span>&lt;</span><span>$paramsCnt</span><span>; </span><span>$i</span><span>++) {  </span></span></li>
<li><span>            <span>$rs</span><span>-&gt;bindParam(</span><span>$i</span><span>, </span><span>$params</span><span>[</span><span>$i</span><span>]);  </span></span></li>
<li><span>        }  </span></li>
<li><span>        <span>$rs</span><span>-&gt;execute();  </span></span></li>
<li><span>        <span>$value</span><span> = </span><span>$rs</span><span>-&gt;fetchColumn();  </span></span></li>
<li><span>        <span>if</span><span>(DEBUG) self::debug(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        unset(<span>$rs</span><span>);  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$value</span><span>;  </span></span></li>
<li><span>    }  </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 扩展PDO::exec()，增加占位符功能</span> </span></li>
<li><span><span>     * @param string    $sql</span> </span></li>
<li><span><span>     * @param int|bool  失败返回false.update和delete成功返回影响的行数，insert返回插入的id</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> </span><span>exec</span><span>(</span><span>$sql</span><span>)  </span></span></li>
<li><span>    {  </span></li>
<li><span>        <span>$rs</span><span> = </span><span>$this</span><span>-&gt;prepare(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        <span>$params</span><span> = func_get_args();  </span></span></li>
<li><span>        <span>$paramsCnt</span><span> = </span><span>count</span><span>(</span><span>$params</span><span>);  </span></span></li>
<li><span>        <span>for</span><span> (</span><span>$i</span><span>=1; </span><span>$i</span><span>&lt;</span><span>$paramsCnt</span><span>; </span><span>$i</span><span>++) {  </span></span></li>
<li><span>            <span>$rs</span><span>-&gt;bindParam(</span><span>$i</span><span>, </span><span>$params</span><span>[</span><span>$i</span><span>]);  </span></span></li>
<li><span>        }  </span></li>
<li><span>        <span>$retval</span><span> = </span><span>$rs</span><span>-&gt;execute();  </span></span></li>
<li><span>        <span>if</span><span> (</span><span>$retval</span><span> === false) </span><span>return</span><span> false;  </span></span></li>
<li><span>        <span>if</span><span>(</span><span>strpos</span><span>(</span><span>strtolower</span><span>(</span><span>$sql</span><span>), </span><span>&#8216;insert&#8217;</span><span>) !==false) {  </span></span></li>
<li><span>            <span>return</span><span> </span><span>$this</span><span>-&gt;lastInsertId();  </span></span></li>
<li><span>        }  </span></li>
<li><span>        <span>if</span><span>(DEBUG) self::debug(</span><span>$sql</span><span>);  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$rs</span><span>-&gt;rowCount();  </span></span></li>
<li><span>    }  </span></li>
<li><span>      </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 计算符合条件的记录总数.如果语句较复杂，可以用getField达到同样效果</span> </span></li>
<li><span><span>     * @param str $table        表名</span> </span></li>
<li><span><span>     * @param str $condition    记录必须符合的条件.如&#8221;id &gt; 100&#8243;</span> </span></li>
<li><span><span>     * @return int          总数</span> </span></li>
<li><span><span>     * 例：  $num = $db-&gt;dbCount(&#8217;t_person&#8217;);</span> </span></li>
<li><span><span>     *  $num = $db-&gt;dbCount(&#8217;t_person&#8217;, &#8217;p_id &gt; 100&#8242;, &#8217;p_id&#8217;);</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>function</span><span> dbCount(</span><span>$table</span><span>, </span><span>$condition</span><span> = </span><span>&#8221;</span><span>, </span><span>$field</span><span>=</span><span>&#8216;*&#8217;</span><span>)  </span></span></li>
<li><span>    {  </span></li>
<li><span>        <span>if</span><span>(</span><span>$condition</span><span> != </span><span>&#8221;</span><span>) {  </span></span></li>
<li><span>            <span>if</span><span>(</span><span>strtoupper</span><span>(</span><span>substr</span><span>(trim(</span><span>$condition</span><span>),0,5)) != </span><span>&#8216;WHERE&#8217;</span><span>) </span><span>$condition</span><span> = </span><span>&#8220;WHERE $condition&#8221;</span><span>;  </span></span></li>
<li><span>        }  </span></li>
<li><span>        <span>$sql</span><span> = </span><span>&#8220;SELECT COUNT($field) FROM `$table` $condition&#8221;</span><span>;  </span></span></li>
<li><span>        <span>//这里不统计sql语句，因为在getField方法里统计了</span><span>  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$this</span><span>-&gt;getField(</span><span>$sql</span><span>);  </span></span></li>
<li><span>    }  </span></li>
<li><span>  </span></li>
<li><span>    <span>/**</span> </span></li>
<li><span><span>     * 常用于分页中，取记录集时要limit，但统计总数又得忽略limit，郁闷啊，以前老是要另写一句统计总数.呵呵，现在爽了</span> </span></li>
<li><span><span>     * 用法：</span> </span></li>
<li><span><span>     * $rs = $db-&gt;getAll(&#8221;SELECT SQL_CALC_FOUND_ROWS * FROM t_person LIMIT ?, ?&#8221;, $start, $end);</span> </span></li>
<li><span><span>     * $total = $db-&gt;foundRows();</span> </span></li>
<li><span><span>     */</span><span>  </span></span></li>
<li><span>    <span>public</span><span> </span><span>function</span><span> foundRows()  </span></span></li>
<li><span>    {  </span></li>
<li><span>        <span>$rs</span><span> = </span><span>$this</span><span>-&gt;query(</span><span>&#8216;SELECT found_rows()&#8217;</span><span>);  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$rs</span><span>-&gt;fetchColumn();  </span></span></li>
<li><span>    }  </span></li>
<li><span>  <br />
</span></li>
<li><span>    <span>//取最大值</span><span>  </span></span></li>
<li><span>    <span>function</span><span> getMax(</span><span>$table</span><span>, </span><span>$field</span><span>, </span><span>$condition</span><span>=</span><span>&#8221;</span><span>){  </span></span></li>
<li><span>        <span>if</span><span>(!</span><span>empty</span><span>empty</span><span>(</span><span>$condition</span><span>)) </span><span>$condition</span><span> = </span><span>&#8216;WHERE &#8217;</span><span>.</span><span>$condition</span><span>;  </span></span></li>
<li><span>        <span>$sql</span><span> = </span><span>&#8220;SELECT max(`&#8221;</span><span>.</span><span>$field</span><span>.</span><span>&#8220;`) FROM `$table` $condition&#8221;</span><span>;  </span></span></li>
<li><span>        <span>return</span><span> </span><span>$this</span><span>-&gt;getField(</span><span>$sql</span><span>);  </span></span></li>
<li><span>    }  </span></li>
<li><span>    <span>//取最小值</span><span>  </span></span></li>
<li><span>    <span>function</span><span> getMin(</span><span>$table</span><span>, </span><span>$field</span><span>, </span><span>$condition</span><span>=</span><span>&#8221;</span><span>){  </span></span></li>
<li><span>        <span>if</span><span>(!</span><span>empty</span><span>empty</span><span>(</span><span>$condition</span><span>)) </span><span>$condition</span><span> = </span><span>&#8216;WHERE &#8217;</span><span>.</span><span>$condition</span><span>;  </span></span></li>
<li><span>        <span>$sql</span><span> = </span><span>&#8220;SELECT min(`&#8221;</span><span>.</span><span>$field</span><span>.</span><span>&#8220;`) FROM `$table` $condition&#8221;</span><span>;  </span></span></li>
<li><span>        <span>$this</span><span>-&gt;getField(</span><span>$sql</span><span>);  </span></span></li>
<li><span>    }  </span></li>
<li><span>} </span></li>
</div>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=26</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL数据库快速入门</title>
		<link>http://php.nyist.net/?p=24</link>
		<comments>http://php.nyist.net/?p=24#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:50:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=24</guid>
		<description><![CDATA[ 
一。MYSQL基础
 简述：mysql是一种高效免费的数据库系统.虽然非常复杂不过用于做网站就不需要多高深的知识，知道一些基本概念就行了。安装了mysql后可以建立许多数据库，每个数据库又可以建立许多表，一般来说一个程序只使用一个数据库。 
数据表由若干个“字段”组成。如下表。假设表的名字为user
编号 姓名 　年龄 　简介
1 　张三 　15 　　这是个白痴
2 　李四 　20 　　他经常跟张三比谁聪明
3 　王五 　18 　　他只比张三笨一点
……
假设人物有100万个。这个人物表里面，每一行就叫一个“记录”，每一列有个列名，如编号，姓名，年龄，简介这就是四个“字段”了。定义了字段，才知道这一列表示的是什么内容，大的表甚至有一百多个字段。注意字
段名不要用中文，但记录的内容里可以有中文（必须是gbk,gb2312或utf8编码）
通常操作数据库都使用通用的SQL语言。（其他数据库系统也用），用SQL语言操作数据库可以极大的简化程序操作。
1.试想如果上表中要得到一个按年龄排序的表，数据量达到几十万的时候将是很恐怖的一件工作，可能要辛苦一个月时间，而且为了维持顺序，每次加入新“记录”还得找半天位置。那学会数据库和SQL
语言后会怎么做呢？只需要一句
 SELECT * FROM user ORDER BY 年龄
 有了这句代码，数据库就把整个表的记录按年龄为顺序列出来，一句代码就完成了以前痛苦的工作。
3.然后修改呢？比如过了一年，每个人年龄增加了一岁，是不是一个个手动去改呢？再试试SQL语句操作数据库吧
 UPDATE user SET 年龄＝年龄＋1
4.要删除20岁以下的所有人呢？
 DELETE FROM user WHERE 年龄&#60;20
添加一个新人物这样做
 INSERT INTO user VALUES(100,&#8217;马六&#8217;，25,&#8217;这里填人物简介&#8217;)
注意，以上为了便于理解，将字段名设成中文了，实际上要用英文，最好用英文单词，有些字段甚至已经约定成俗了，例如姓名用name,密码用pass或者password等，别人一看就能理解你的数据表。
 
二:建立表.
开始不需要学习创建表的语句,用navicat操作或phpmyadmin就可以.
比如navicat的新建表.
在字段选项卡里,可以填入各字段的属性,
名称:即字段名(id,name之类的),
类型:是这个字段的值类型,例如年龄字段肯定用数字(int)吧,姓名肯定用字符串(varchar),而简介由于可能很久,通常用长文件型(text).
长度:通常指字符的最长限制,数字型不用定义,自动有限制.
十进制:不管
允许空:添加的时候是否允许不加值.
主键:数据库里一般有一个字段做为主键,每条记录的主键值绝不能相同,是记录的唯一标志.(比如人的身份证号),没有好的唯一标志,通常都是建一个id字段,设为主键,并且设为自动增加.(在navicat设计
表的时候,下方有个&#8221;自动递增&#8221;选项.这样添加的时候,不用添加id值,数据库会自动分配一个编号给它.每加一条记录,编号自动加1,永不重复.
例如上表,在navicat里这么创建表
名称  　　　　类型 　　长度　 十进制 　允许空? 　 (主键?)  
id  　　　　　int     　　　　　　　　　　　　　　　主键(自动递增)
name  　　　varchar 　20
age 　 　　　int
description 　text   　　　　　　是    
text是长文本的,属于备注型,在查看记录的时候,要点上方的备注才能看到text的值.
除了上面的三种类型,常用的还有时间类型(datetime),布尔型(只有1和0两个值,表示真和假)
上面三种基本类型还有变型,例如smallint表示短整型,int能表示11位数字,而短整的就小一些.
 设计表实战:一个日志表
 
 
根据需要可以继续加字段
一个通讯录的表



 字段名
类型
长度 
允许空？ 
主键？ 
备注 


 id
 int
 
否
是 
主键（自增列） 


name
varchar 
20 
 
 
 名字


nick 
varchar 
20 
 
 
 妮称、网名


class 
varchar 
20 
 
 
 类型


qq
varchar
12 
 
 
 


phone 
varchar 
15 
 
 
 电话


photo 
varchar 
100 
 
 
相片路径 


description 
text 
1000 
 
 
简介、备注



qq和电话虽然是数字,但是不用于数学计算,所以一般还是用字符型比较好.
上传图片的时候,实际上是上传到硬盘目录里,数据库只保存图片的地址而己(删除记录的时候根据地址再删了图片文件).虽然也可以把真正图片存入数据库,但那样做,会使数据库庞大而缓慢.这些可以以后再学现在最关键的是多设计一些表,然后在PHP里练习以下的四个语句。当然直接用navicat或phpmyadmin练习也可以，效率更高点。
三。简单SQL语法
简述：人们对于数据的操作不外乎“添加”“删除”“修改”“读取”这四种。这四种操作里
1.添加记录
 INSERT INTO 表名（字段1，字段2，字段3) VALUES(值1,值2,值3)
 解释:格式都是这样子的,如果看得懂英语很容易理解什么意思,具体应用中自己替换&#8221;表名&#8221;,字段名和值三个部分.
 实例:仍然以上表为例.但不再用中文字段名,而用英文代替.编号=id,姓名=name,年龄=age,简介=description
   
2.删除记录
 DELETE FROM 表名 WHERE 条件
 解释:如果没有后面的WHERE 条件,将会删除整个表,一般情况下都限定条件的.
 实例:

SQL代码
INSERT INTO user(name,age,description) VALUES(&#8216;赵云&#8217;,17,&#8216;三国名将&#8217;)   
INSERT INTO user VALUES(11,\&#8216;赵云\&#8217;,17,\&#8217;三国名将\&#8217;)         //如果所有字段都添加值,可以省略字段部分.实际上编号id字段都设置成主键,并且自动增加,一般不用人工输入值.   

 

SQL代码
DELETE FROM user //这样会删除整个user表记录.但是表结构(字段信息)还在   
DELETE FROM user WHERE age&#62;20 //删除年龄大于20的记录   
DELETE FROM user WHERE name=&#8216;张三&#8217; //删除姓名为张三的,注意字符要加引号   

3.修改记录
 UPDATE 表名 SET 字段1=值1,字段2=值2 WHERE 条件
 解释: 修改记录的字段值,多少个字段要改就写多少个&#8221;字段=值&#8221;
 实例:

SQL代码
UPDATE user SET age=age+1 //所有人年龄加1   
  UPDATE user SET name=&#8216;张山&#8217; WHERE name=&#8216;张三&#8217; //修改名字为&#8220;张三&#8221;,条件是这条记录的姓名为&#8220;张三&#8221;.(即只改张三的姓名为&#8220;张山&#8221;.条件子句是经常用到的.   

4.读取记录.
 SELECT * FROM 表名 WHERE 条件 ORDER BY 字段 LIMIT 数字
 解释:这是最常用到的语句.
 实例: 注意:LIMIT子句必须写在最后,条件子句(WHERE)和排序子句(ORDER)随便顺序都可以,像HTML的属性一样,没有先后和依附关系.

SQL代码
UPDATE user SET age=age+1 //所有人年龄加1   
UPDATE user SET name=&#8216;张山&#8217; WHERE name=&#8216;张三&#8217; //修改名字为&#8220;张三&#8221;,条件是这条记录的姓名为&#8220;张三&#8221;.(即只改张三的姓名为&#8220;张山&#8221;.条件子句是经常用到的.   

 四:SQL进阶
 1.复合条件:稍微复杂一点的情形中,可能不只需要一个条件.
 例如我要年龄&#62;20的,并且编号&#62;1000的,这就需要复合条件了,其实也非常简单,用and或or把条件组合起来就行了.
 例:

SQL代码
SELECT * FROM user age&#62;20 AND id&#62;1000 //年龄&#62;20并且编号&#62;1000   
SELECT * FROM user age&#62;20 OR id&#62;1000 //年龄&#62;20或者编号&#62;1000   

  能理解&#8221;并且&#8221;和&#8221;或者&#8221;的区别吧? 2.相反排序.与正排序比,反排序只需要加一个词

SQL代码
SELECT * FROM user age&#62;20 AND id&#62;1000 //年龄&#62;20并且编号&#62;1000   
SELECT * FROM user age&#62;20 OR id&#62;1000 //年龄&#62;20或者编号&#62;1000 [...]]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>一。MYSQL基础</p>
<p> 简述：mysql是一种高效免费的数据库系统.虽然非常复杂不过用于做网站就不需要多高深的知识，知道一些基本概念就行了。安装了mysql后可以建立许多数据库，每个数据库又可以建立许多表，一般来说一个程序只使用一个数据库。 <span id="more-24"></span></p>
<p>数据表由若干个“字段”组成。如下表。假设表的名字为user</p>
<p><span style="color: #009990;"><span style="color: #003330;"><span style="color: #003390;">编号 姓名 　年龄 　简介</span><br />
</span>1 　张三 　15 　　这是个白痴<br />
2 　李四 　20 　　他经常跟张三比谁聪明<br />
3 　王五 　18 　　他只比张三笨一点</span><br />
……<br />
假设人物有100万个。这个人物表里面，每一行就叫一个“记录”，每一列有个列名，如编号，姓名，年龄，简介这就是四个“字段”了。定义了字段，才知道这一列表示的是什么内容，大的表甚至有一百多个字段。注意字</p>
<p>段名不要用中文，但记录的内容里可以有中文（必须是gbk,gb2312或utf8编码）</p>
<p><span style="color: #0000f0;">通常操作数据库都使用通用的SQL语言。（其他数据库系统也用），用SQL语言操作数据库可以极大的简化程序操作。</span></p>
<p>1.试想如果上表中要得到一个按年龄排序的表，数据量达到几十万的时候将是很恐怖的一件工作，可能要辛苦一个月时间，而且为了维持顺序，每次加入新“记录”还得找半天位置。那学会数据库和SQL</p>
<p>语言后会怎么做呢？只需要一句</p>
<p><span style="color: #3366ff;"> SELECT * FROM user ORDER BY 年龄</span></p>
<p> 有了这句代码，数据库就把整个表的记录按年龄为顺序列出来，一句代码就完成了以前痛苦的工作。</p>
<p>3.然后修改呢？比如过了一年，每个人年龄增加了一岁，是不是一个个手动去改呢？再试试SQL语句操作数据库吧</p>
<p><span style="color: #3366ff;"> UPDATE user SET 年龄＝年龄＋1</span></p>
<p>4.要删除20岁以下的所有人呢？</p>
<p><span style="color: #00f000;"> </span><span style="color: #3366ff;">DELETE FROM user WHERE 年龄&lt;20</span></p>
<p>添加一个新人物这样做</p>
<p><span style="color: #00f000;"> </span><span style="color: #3366ff;">INSERT INTO user VALUES(100,&#8217;马六&#8217;，25,&#8217;这里填人物简介&#8217;)</span></p>
<p><span style="color: #ff0000;">注意，以上为了便于理解，将字段名设成中文了，实际上要用英文，最好用英文单词</span>，有些字段甚至已经约定成俗了，例如姓名用name,密码用pass或者password等，别人一看就能理解你的数据表。</p>
<p> </p>
<h3><span style="color: #0036f0;">二:建立表.</span></h3>
<p>开始不需要学习创建表的语句,用navicat操作或phpmyadmin就可以.<br />
比如navicat的新建表.</p>
<p>在字段选项卡里,可以填入各字段的属性,</p>
<p>名称:即字段名(id,name之类的),</p>
<p>类型:是这个字段的值类型,例如年龄字段肯定用数字(int)吧,姓名肯定用字符串(varchar),而简介由于可能很久,通常用长文件型(text).</p>
<p>长度:通常指字符的最长限制,数字型不用定义,自动有限制.<br />
十进制:不管</p>
<p>允许空:添加的时候是否允许不加值.</p>
<p>主键:数据库里一般有一个字段做为主键,每条记录的主键值绝不能相同,是记录的唯一标志.(比如人的身份证号),没有好的唯一标志,通常都是建一个id字段,设为主键,并且设为自动增加.(在navicat设计</p>
<p>表的时候,下方有个&#8221;自动递增&#8221;选项.这样添加的时候,不用添加id值,数据库会自动分配一个编号给它.每加一条记录,编号自动加1,永不重复.</p>
<p>例如上表,在navicat里这么创建表</p>
<p><span style="color: #000800;">名称  　　　　类型 　　长度　 十进制 　允许空? 　 (主键?)</span>  <br />
<span style="color: #009990;">id  　　　　　int     　　　　　　　　　　　　　　　主键(自动递增)<br />
name  　　　varchar 　20<br />
age 　 　　　int<br />
description 　text   　　　　　　是</span>    </p>
<p>text是长文本的,属于备注型,在查看记录的时候,要点上方的备注才能看到text的值.<br />
除了上面的三种类型,常用的还有时间类型(datetime),布尔型(只有1和0两个值,表示真和假)<br />
上面三种基本类型还有变型,例如smallint表示短整型,int能表示11位数字,而短整的就小一些.</p>
<p> <span style="font-size: small; color: #0036f0;">设计表实战:一个日志表</span></p>
<p> </p>
<p> </p>
<p>根据需要可以继续加字段</p>
<p><span style="font-size: small; color: #0036f0;">一个通讯录的表</span></p>
<table border="\&quot;1\&quot;" cellspacing="\&quot;1\&quot;" cellpadding="\&quot;1\&quot;">
<tbody>
<tr>
<td> 字段名</td>
<td>类型</td>
<td>长度 </td>
<td>允许空？ </td>
<td>主键？ </td>
<td>备注 </td>
</tr>
<tr>
<td> id</td>
<td> int</td>
<td> </td>
<td>否</td>
<td>是 </td>
<td>主键（自增列） </td>
</tr>
<tr>
<td>name</td>
<td>varchar </td>
<td>20 </td>
<td> </td>
<td> </td>
<td> 名字</td>
</tr>
<tr>
<td>nick </td>
<td>varchar </td>
<td>20 </td>
<td> </td>
<td> </td>
<td> 妮称、网名</td>
</tr>
<tr>
<td>class </td>
<td>varchar </td>
<td>20 </td>
<td> </td>
<td> </td>
<td> 类型</td>
</tr>
<tr>
<td>qq</td>
<td>varchar</td>
<td>12 </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>phone </td>
<td>varchar </td>
<td>15 </td>
<td> </td>
<td> </td>
<td> 电话</td>
</tr>
<tr>
<td>photo </td>
<td>varchar </td>
<td>100 </td>
<td> </td>
<td> </td>
<td>相片路径 </td>
</tr>
<tr>
<td>description </td>
<td>text </td>
<td>1000 </td>
<td> </td>
<td> </td>
<td>简介、备注</td>
</tr>
</tbody>
</table>
<p>qq和电话虽然是数字,但是不用于数学计算,所以一般还是用字符型比较好.<br />
上传图片的时候,实际上是上传到硬盘目录里,数据库只保存图片的地址而己(删除记录的时候根据地址再删了图片文件).虽然也可以把真正图片存入数据库,但那样做,会使数据库庞大而缓慢.这些可以以后再学现在最关键的是多设计一些表,然后在PHP里练习以下的四个语句。当然直接用navicat或phpmyadmin练习也可以，效率更高点。</p>
<h3><span style="color: #0036f0;">三。简单SQL语法</span></h3>
<p>简述：人们对于数据的操作不外乎“添加”“删除”“修改”“读取”这四种。这四种操作里</p>
<p>1.添加记录<br />
<span style="color: #3366ff;"> INSERT INTO 表名（字段1，字段2，字段3) VALUES(值1,值2,值3)<br />
</span> 解释:格式都是这样子的,如果看得懂英语很容易理解什么意思,具体应用中自己替换&#8221;表名&#8221;,字段名和值三个部分.<br />
 实例:仍然以上表为例.但不再用中文字段名,而用英文代替.编号=id,姓名=name,年龄=age,简介=description<br />
<span style="color: #3366ff;">   </span><br />
2.删除记录<br />
<span style="color: #3366ff;"> DELETE FROM 表名 WHERE 条件</span><span style="color: #00f000;"><br />
</span> 解释:如果没有后面的WHERE 条件,将会删除整个表,一般情况下都限定条件的.<br />
 实例:</p>
<div>
<div>SQL代码</div>
<li><span><span>INSERT</span><span> </span><span>INTO</span><span> </span><span>user</span><span>(</span><span>name</span><span>,age,description) </span><span>VALUES</span><span>(</span><span>&#8216;赵云&#8217;</span><span>,17,</span><span>&#8216;三国名将&#8217;</span><span>)   </span></span></li>
<li><span>INSERT</span><span> </span><span>INTO</span><span> </span><span>user</span><span> </span><span>VALUES</span><span>(11,\</span><span>&#8216;赵云\&#8217;,17,\&#8217;三国名将\&#8217;</span><span>)         //如果所有字段都添加值,可以省略字段部分.实际上编号id字段都设置成主键,并且自动增加,一般不用人工输入值.   </span></li>
</div>
<p> </p>
<div>
<div>SQL代码</div>
<li><span><span>DELETE</span><span> </span><span>FROM</span><span> </span><span>user</span><span> //这样会删除整个</span><span>user</span><span>表记录.但是表结构(字段信息)还在   </span></span></li>
<li><span>DELETE</span><span> </span><span>FROM</span><span> </span><span>user</span><span> </span><span>WHERE</span><span> age&gt;20 //删除年龄大于20的记录   </span></li>
<li><span>DELETE</span><span> </span><span>FROM</span><span> </span><span>user</span><span> </span><span>WHERE</span><span> </span><span>name</span><span>=</span><span>&#8216;张三&#8217;</span><span> //删除姓名为张三的,注意字符要加引号   </span></li>
</div>
<p>3.修改记录<br />
<span style="color: #00f000;"> <span style="color: #808080;">UPDATE 表名 SET 字段1=值1,字段2=值2 WHERE 条件</span><br />
</span> 解释: 修改记录的字段值,多少个字段要改就写多少个&#8221;字段=值&#8221;<br />
 实例:</p>
<div>
<div>SQL代码</div>
<li><span><span>UPDATE</span><span> </span><span>user</span><span> </span><span>SET</span><span> age=age+1 //所有人年龄加1   </span></span></li>
<li><span>  </span><span>UPDATE</span><span> </span><span>user</span><span> </span><span>SET</span><span> </span><span>name</span><span>=</span><span>&#8216;张山&#8217;</span><span> </span><span>WHERE</span><span> </span><span>name</span><span>=</span><span>&#8216;张三&#8217;</span><span> //修改名字为</span><span>&#8220;张三&#8221;</span><span>,条件是这条记录的姓名为</span><span>&#8220;张三&#8221;</span><span>.(即只改张三的姓名为</span><span>&#8220;张山&#8221;</span><span>.条件子句是经常用到的.   </span></li>
</div>
<p>4.读取记录.<br />
 <span style="color: #3366ff;">SELECT * FROM 表名 WHERE 条件 ORDER BY 字段 LIMIT 数字<br />
</span> 解释:这是最常用到的语句.<br />
 实例: 注意:LIMIT子句必须写在最后,条件子句(WHERE)和排序子句(ORDER)随便顺序都可以,像HTML的属性一样,没有先后和依附关系.</p>
<div>
<div>SQL代码</div>
<li><span><span>UPDATE</span><span> </span><span>user</span><span> </span><span>SET</span><span> age=age+1 //所有人年龄加1   </span></span></li>
<li><span>UPDATE</span><span> </span><span>user</span><span> </span><span>SET</span><span> </span><span>name</span><span>=</span><span>&#8216;张山&#8217;</span><span> </span><span>WHERE</span><span> </span><span>name</span><span>=</span><span>&#8216;张三&#8217;</span><span> //修改名字为</span><span>&#8220;张三&#8221;</span><span>,条件是这条记录的姓名为</span><span>&#8220;张三&#8221;</span><span>.(即只改张三的姓名为</span><span>&#8220;张山&#8221;</span><span>.条件子句是经常用到的.   </span></li>
</div>
<p> <span style="color: #0036f0;">四:SQL进阶</span><br />
 1.复合条件:稍微复杂一点的情形中,可能不只需要一个条件.</p>
<p> 例如我要年龄&gt;20的,并且编号&gt;1000的,这就需要复合条件了,其实也非常简单,用and或or把条件组合起来就行了.<br />
 例:</p>
<div>
<div>SQL代码</div>
<li><span><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> age&gt;20 </span><span>AND</span><span> id&gt;1000 //年龄&gt;20并且编号&gt;1000   </span></span></li>
<li><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> age&gt;20 </span><span>OR</span><span> id&gt;1000 //年龄&gt;20或者编号&gt;1000   </span></li>
</div>
<p>  能理解&#8221;并且&#8221;和&#8221;或者&#8221;的区别吧? 2.相反排序.与正排序比,反排序只需要加一个词</p>
<div>
<div>SQL代码</div>
<li><span><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> age&gt;20 </span><span>AND</span><span> id&gt;1000 //年龄&gt;20并且编号&gt;1000   </span></span></li>
<li><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> age&gt;20 </span><span>OR</span><span> id&gt;1000 //年龄&gt;20或者编号&gt;1000   </span></li>
</div>
<p> </p>
<div>
<div>SQL代码</div>
<li><span><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> </span><span>ORDER</span><span> </span><span>BY</span><span> id </span><span>DESC</span><span> //读全表,并按id反排序(即大的编号排前面)   </span></span></li>
</div>
<p> 3.读取中间一部分记录.例如从10到204.读取一部分字段.有时候字段太多的时候管用.比如只想知道张三的编号</p>
<div>
<div>SQL代码</div>
<li><span><span>SELECT</span><span> * </span><span>FROM</span><span> </span><span>user</span><span> LIMIT 10,10  //从第10条开始,读取10条.   </span></span></li>
</div>
<p> </p>
<div>
<div>SQL代码</div>
<li><span><span>SELECT</span><span> id </span><span>FROM</span><span> </span><span>user</span><span> </span><span>WHERE</span><span> </span><span>name</span><span> = </span><span>&#8216;张三&#8217;</span><span>  </span></span></li>
<li><span>//或者还需要知道年龄   </span></li>
<li><span>SELECT</span><span> id,age </span><span>FROM</span><span> </span><span>user</span><span> </span><span>WHERE</span><span> </span><span>name</span><span>=</span><span>&#8216;张三&#8217;</span><span>  </span></li>
<li><span>   </span></li>
</div>
<p>&#8230;&#8230;&#8230;</p>
<p>注意事项,各字段不用按顺序写,添加记录的时候也一样,不过字段名和值要一一对应,例如name字段放第二位,后面的姓名就填在第二位.</p>
<p> </p>
<p> </p>
<table border="\&quot;1\&quot;" cellspacing="\&quot;1\&quot;" cellpadding="\&quot;1\&quot;">
<tbody>
<tr>
<td>名称</td>
<td>类型</td>
<td>长度</td>
<td>允许空?</td>
<td>(主键?)</td>
<td>备注</td>
</tr>
<tr>
<td>id</td>
<td>int</td>
<td> </td>
<td>否</td>
<td>是</td>
<td> 主键（自增列）</td>
</tr>
<tr>
<td>title</td>
<td>varchar</td>
<td>50</td>
<td>是</td>
<td> </td>
<td>标题</td>
</tr>
<tr>
<td>content</td>
<td>varchar</td>
<td>50</td>
<td>是</td>
<td> </td>
<td>内容</td>
</tr>
<tr>
<td>addtime</td>
<td>datetime</td>
<td> </td>
<td>是</td>
<td> </td>
<td>加入时间</td>
</tr>
<tr>
<td>class</td>
<td>varchar</td>
<td>20</td>
<td>是</td>
<td> </td>
<td>分类</td>
</tr>
<tr>
<td>author</td>
<td>varchar</td>
<td>20</td>
<td>是</td>
<td> </td>
<td>作者</td>
</tr>
<tr>
<td>click</td>
<td>int</td>
<td> </td>
<td>是</td>
<td> </td>
<td>点击数</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=24</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP模板引擎smarty入门</title>
		<link>http://php.nyist.net/?p=17</link>
		<comments>http://php.nyist.net/?p=17#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:43:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=17</guid>
		<description><![CDATA[内容提示：Smarty是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。

Smsrty简介
Smarty是一个使用PHP写出来的模板PHP模板引擎，是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲，目的就是要使用PHP程序员同美工分离，使用的程序员改变程序的逻辑内容不会影响到美工的页面设计，美工重新修改页面不会影响到程序的程序逻辑，这在多人合作的项目中显的尤为重要。
Smarty优点
1. 速度：采用Smarty编写的程序可以获得最大速度的提高，这一点是相对于其它的模板引擎技术而言的。
2. 编译型：采用Smarty编写的程序在运行时要编译成一个非模板技术的PHP文件，这个文件采用了PHP与HTML混合的方式，在下一次访问模板时将WEB请求直接转换到这个文件中，而不再进行模板重新编译（在源程序没有改动的情况下）
3. 缓存技术：Smarty选用的一种缓存技术，它可以将用户最终看到的HTML文件缓存成一个静态的HTML页，当设定Smarty的cache属性为true时，在Smarty设定的cachetime期内将用户的WEB请求直接转换到这个静态的HTML文件中来，这相当于调用一个静态的HTML文件。
4. 插件技术：Smarty可以自定义插件。插件实际就是一些自定义的函数。
5. 模板中可以使用if/elseif/else/endif。在模板文件使用判断语句可以非常方便的对模板进行格式重排。
不适合使用Smarty的地方
与其他模板引擎相比Smarty有其独特的优势，但是，这并不意味着它是万能的，优势是相对的，在一些场合，其优势反而为成为其劣势，比如以下场合：
1. 需要实时更新的内容。例如像股票显示，它需要经常对数据进行更新，导致经常重新编译模板，所以这类型的程序使用Smarty会使模板处理速度变慢。
2. 小项目。小项目因为项目简单而美工与程序员兼于一人的项目，使用Smarty会在一定程度上丧失PHP开发迅速的优点。
Smsrty应用深层剖析
        用PHP实现MVC开发模式的逻辑层和表示层有多种模板引擎可供选择，但是官方引擎SMARTY诞生后，选择就有了变化。它的理念和实现都是相当&#8221;前卫&#8221;的。本文主要讨论SMARTY之于其他模板引擎的不同特点，简要介绍了该引擎的安装及使用，并用一个小的测试案例对比了SMARTY和PHPLIB template的速度和易用性。
一、MVC需要模板
         MVC最早是在SmallTalk语言的开发过程中总结出的一种设计模式，MVC分别代表了&#8221;模型&#8221;、&#8221;视图&#8221;和&#8221;控制&#8221;，目的就是让不同的开发角色在大中型项目中各司其职。在网络应用程序的开发中，可以用下图来表示各概念之间的关系。
 

         该图展示了一个简单的WEB应用程序，用户在浏览器上看到信息是数据库服务器上的内容，但在这之前经过了应用服务器加工。开发人员负责的就是建立数据结构、处理数据的逻辑以及表示数据的方法。
         96年CGI在中国开始流行的时候，早期的WEB程序员都是从HTML开始自学成材的，在PERL中print一行行的HTML并不是一件难事，但是随着网络的一步步提速，页面大小也从当初的二、三十K暴涨了十倍。写CGI程序就产生了一个迫切的要求：分开PERL和HTML源码。于是，社会进步体现在开发小组内部的分工上。由于美工和程序员对互相的工作并不是十分熟悉，在进行合作的过程中需要用一种约定的&#8221;语言&#8221;进行交流。
        这种语言并不是我们的母语或者英语，术语叫做&#8221;模板&#8221;，逻辑和表示依靠它联系。它是结合了HTML和脚本语言特征的一种表达方式。通过这种方式，表示层可以按照用户所希望的格式来显示经过逻辑层处理过的数据。如果你有Windows平台下MFC的开发经验,那么一定会很熟悉Document/Document Template/View的封装，这就是一个很典型的MVC例子。对于Web应用来说，个人认为J2EE中的EJB/servlets/JSP是最强大的，当然还有简洁优美的Structs。另一个很有名的实现就是COM/DCOM+ASP，这个组合在我国是最多人使用的。
通过几种MVC实现在WEB应用程序里的对比，可以得到一个关于模板的概念：一组插入了HTML的脚本或者说是插入了脚本HTML，通过这种插入的内容来表示变化的数据。下面给出一个模板文件的例子，这个模板经过处理后在浏览器里显示&#8221;Hello, world!&#8221;
 



 &#60;html&#62;
   &#60;head&#62;
      &#60;title&#62;$greetings&#60;/title&#62;
   &#60;/head&#62;
   &#60;body&#62;
      $greetings
   &#60;body&#62;
&#60;/html&#62;



这里暂且省略处理方式，在后面做专门对比讨论。
二、为什么选SMARTY?
       对PHP来说，有很多模板引擎可供选择，比如最早的PHPLIB template和后起之秀Fast template，经过数次升级，已经相当成熟稳定。如果你对目前手中的模板引擎很满意，那么&#8230;&#8230;也请往下看，相信你作为一个自由软件爱好者或者追求效率和优雅的开发者，下面的SMARTY介绍多少会有点意思。
        除了个人偏好的影响，我一直倾向于使用官方标准的实现，比如APACHE的XML引擎Axis。好处就是可以获得尽可能好的兼容性(比如早期MFC对于Win3x的兼容性就比其它的应用程序框架好，当然现在各种版本都很完善了)。SMARTY发布之前我一直使用的是 PEAR 中的Integrated Template eXtension。这个引擎和PHPLIB template、Fast template几乎是兼容的，从模板的语法到对模板的处理同出一辙：都是将模板读入内存然后调用parse()函数，用数据对预置的标记进行替换。
        下面看看SMARTY是怎么做的。接到request后，先判断是否第一次请求该url，如果是，将该url所需的模板文件&#8221;编译&#8221;成php脚本，然后redirect；如果不是，就是说该url的模板已经被&#8221;编译&#8221;过了，检查不需要重编译后可以马上redirect，重编译条件可以自己设定为固定时限，默认的是模板文件被修改。 
        怎么样，看起来是不是有点眼熟？想起来了──这不就是JSP的原理嘛！的确，这种&#8221;编译&#8221;用在PHP这样的解释性脚本引擎上显得匪夷所思，但是仔细想想，JAVA不也是由JVM解释执行的吗？这就叫&#8221;没有做不到，只有想不到&#8221;。
        既然谈到了JAVA，就再对PHP的未来发表一点看法。PHP官方网站上宣布了要在2003年年底发布PHP5.0版。这个版本拥有很多崭新的特性：比如异常处理，命名空间，更加面向对象等等。可以说越来越向JAVA靠拢，SMARTY也是新特性之一，使得PHP更适用于大中型项目的开发。但是似乎离我当初选择它的原因──灵巧易用──越来越远了。但就一个软件的生存周期来看，PHP正处在成长期，开发者赋予它更多的功能，以期能胜任商业应用是利大于弊的。作为PHP的忠实用户，肯定不希望PHP总是被人指责&#8221;能力不足&#8221;吧？
        为什么选择SMARTY，仅仅因为它很像JSP？当然有更为充分的理由。首先，除了第一次编译的成本比较高之外，只要不修改模板文件，编译好的cache脚本就随时可用，省去了大量的parse()时间；其次SMARTY像PHP一样有丰富的函数库，从统计字数到自动缩进、文字环绕以及正则表达式都可以直接使用；如果觉得不够，比如需要数据结果集分页显示的功能，SMARTY还有很强的扩展能力，可以通过插件的形式进行扩充。
        事实胜于雄辩。我设计了一个测试程序，通过速度和开发难度这两个因素对比了一下SMARTY和PHPLIB template，选PHPLIB template的原因是在patrick的文章 《在PHP世界中选择最合适的模板》中有一个PHPLIB template对Fast template的竞赛，结果PHPLIB template大获全胜，这使得SMARTY有了一个很好的对手。在测试之前，先谈一下在安装过程中需要注意的问题。
三、可能遇到的问题
        在SMARTY的 官方网站上，有详尽的用户手册，可以选择在线HTML和PDF格式的版本。这里就不再涉及手册上已有的内容，只是把初次使用可能遇到的问题做个解释。
 

        第一个问题就很要命：提示说找不到所需文件？并不是每一个人都按照SMARTY默认目录结构来写应用的。这里需要手工指定，假设目录结构如下：
就需要在index.php里指定目录结构：



$smart-&#62;template_dir = &#8220;smarty/templates/&#8221;;
$smart-&#62;compile_dir = &#8220;smarty/templates_c/&#8221;;
$smart-&#62;config_dir = &#8220;smarty/configs/&#8221;;
$smart-&#62;cache_dir = &#8220;smarty/cache/&#8221;;



        第一个问题解决了，紧接着就是第二个：我刚用Dreamweaver生成的漂亮模板怎么不能用？并不是模板文件有什么问题，而是因为SMARTY默认的标记分隔符是{}，不巧的是Javascript肯定包含这个标记。好在我们可以用任意字符当作分隔符，再加上这两句：



$smart-&#62;left_delimiter [...]]]></description>
			<content:encoded><![CDATA[<p><strong><span style="color: #ff0000;">内容提示：</span></strong>Smarty是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。</p>
<p><span id="more-17"></span><br />
<strong>Smsrty简介</strong><br />
Smarty是一个使用PHP写出来的模板PHP模板引擎，是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲，目的就是要使用PHP程序员同美工分离，使用的程序员改变程序的逻辑内容不会影响到美工的页面设计，美工重新修改页面不会影响到程序的程序逻辑，这在多人合作的项目中显的尤为重要。<br />
<strong>Smarty优点</strong><br />
1. 速度：采用Smarty编写的程序可以获得最大速度的提高，这一点是相对于其它的模板引擎技术而言的。<br />
2. 编译型：采用Smarty编写的程序在运行时要编译成一个非模板技术的PHP文件，这个文件采用了PHP与HTML混合的方式，在下一次访问模板时将WEB请求直接转换到这个文件中，而不再进行模板重新编译（在源程序没有改动的情况下）<br />
3. 缓存技术：Smarty选用的一种缓存技术，它可以将用户最终看到的HTML文件缓存成一个静态的HTML页，当设定Smarty的cache属性为true时，在Smarty设定的cachetime期内将用户的WEB请求直接转换到这个静态的HTML文件中来，这相当于调用一个静态的HTML文件。<br />
4. 插件技术：Smarty可以自定义插件。插件实际就是一些自定义的函数。<br />
5. 模板中可以使用if/elseif/else/endif。在模板文件使用判断语句可以非常方便的对模板进行格式重排。</p>
<p><strong>不适合使用Smarty的地方</strong><br />
与其他模板引擎相比Smarty有其独特的优势，但是，这并不意味着它是万能的，优势是相对的，在一些场合，其优势反而为成为其劣势，比如以下场合：<br />
1. 需要实时更新的内容。例如像股票显示，它需要经常对数据进行更新，导致经常重新编译模板，所以这类型的程序使用Smarty会使模板处理速度变慢。<br />
2. 小项目。小项目因为项目简单而美工与程序员兼于一人的项目，使用Smarty会在一定程度上丧失PHP开发迅速的优点。</p>
<p><strong>Smsrty应用深层剖析<br />
        </strong>用PHP实现MVC开发模式的逻辑层和表示层有多种模板引擎可供选择，但是官方引擎SMARTY诞生后，选择就有了变化。它的理念和实现都是相当&#8221;前卫&#8221;的。本文主要讨论SMARTY之于其他模板引擎的不同特点，简要介绍了该引擎的安装及使用，并用一个小的测试案例对比了SMARTY和PHPLIB template的速度和易用性。<br />
<strong>一、MVC需要模板<br />
         </strong>MVC最早是在SmallTalk语言的开发过程中总结出的一种设计模式，MVC分别代表了&#8221;模型&#8221;、&#8221;视图&#8221;和&#8221;控制&#8221;，目的就是让不同的开发角色在大中型项目中各司其职。在网络应用程序的开发中，可以用下图来表示各概念之间的关系。</p>
<p> </p>
<p align="center"><span style="color: #ff0000;"><img class="alignnone size-full wp-image-18" title="01" src="http://php.nyist.net/wp-content/uploads/2009/08/01.gif" alt="01" width="477" height="259" /></span></p>
<p>         该图展示了一个简单的WEB应用程序，用户在浏览器上看到信息是数据库服务器上的内容，但在这之前经过了应用服务器加工。开发人员负责的就是建立数据结构、处理数据的逻辑以及表示数据的方法。<br />
         96年CGI在中国开始流行的时候，早期的WEB程序员都是从HTML开始自学成材的，在PERL中print一行行的HTML并不是一件难事，但是随着网络的一步步提速，页面大小也从当初的二、三十K暴涨了十倍。写CGI程序就产生了一个迫切的要求：分开PERL和HTML源码。于是，社会进步体现在开发小组内部的分工上。由于美工和程序员对互相的工作并不是十分熟悉，在进行合作的过程中需要用一种约定的&#8221;语言&#8221;进行交流。<br />
        这种语言并不是我们的母语或者英语，术语叫做&#8221;模板&#8221;，逻辑和表示依靠它联系。它是结合了HTML和脚本语言特征的一种表达方式。通过这种方式，表示层可以按照用户所希望的格式来显示经过逻辑层处理过的数据。如果你有Windows平台下MFC的开发经验,那么一定会很熟悉Document/Document Template/View的封装，这就是一个很典型的MVC例子。对于Web应用来说，个人认为J2EE中的EJB/servlets/JSP是最强大的，当然还有简洁优美的Structs。另一个很有名的实现就是COM/DCOM+ASP，这个组合在我国是最多人使用的。</p>
<p>通过几种MVC实现在WEB应用程序里的对比，可以得到一个关于模板的概念：一组插入了HTML的脚本或者说是插入了脚本HTML，通过这种插入的内容来表示变化的数据。下面给出一个模板文件的例子，这个模板经过处理后在浏览器里显示&#8221;Hello, world!&#8221;</p>
<p> </p>
<table style="width: 563px; height: 166px;" border="0" cellspacing="1" cellpadding="10" width="563" bgcolor="#0099cc">
<tbody>
<tr>
<td style="WORD-BREAK: break-all; LINE-HEIGHT: 18px" width="100%" bgcolor="#ddedfb"><span style="font-size: x-small;"> </span><span><span style="font-size: x-small;">&lt;html&gt;<br />
   &lt;head&gt;<br />
      &lt;title&gt;$greetings&lt;/title&gt;<br />
   &lt;/head&gt;<br />
   &lt;body&gt;<br />
      $greetings<br />
   &lt;body&gt;<br />
&lt;/html&gt;</span></span></td>
</tr>
</tbody>
</table>
<p>这里暂且省略处理方式，在后面做专门对比讨论。<br />
<strong>二、为什么选SMARTY?<br />
       </strong>对PHP来说，有很多模板引擎可供选择，比如最早的PHPLIB template和后起之秀Fast template，经过数次升级，已经相当成熟稳定。如果你对目前手中的模板引擎很满意，那么&#8230;&#8230;也请往下看，相信你作为一个自由软件爱好者或者追求效率和优雅的开发者，下面的SMARTY介绍多少会有点意思。<br />
        除了个人偏好的影响，我一直倾向于使用官方标准的实现，比如APACHE的XML引擎Axis。好处就是可以获得尽可能好的兼容性(比如早期MFC对于Win3x的兼容性就比其它的应用程序框架好，当然现在各种版本都很完善了)。SMARTY发布之前我一直使用的是 PEAR 中的Integrated Template eXtension。这个引擎和PHPLIB template、Fast template几乎是兼容的，从模板的语法到对模板的处理同出一辙：都是将模板读入内存然后调用parse()函数，用数据对预置的标记进行替换。<br />
        下面看看SMARTY是怎么做的。接到request后，先判断是否第一次请求该url，如果是，将该url所需的模板文件&#8221;编译&#8221;成php脚本，然后redirect；如果不是，就是说该url的模板已经被&#8221;编译&#8221;过了，检查不需要重编译后可以马上redirect，重编译条件可以自己设定为固定时限，默认的是模板文件被修改。 <br />
        怎么样，看起来是不是有点眼熟？想起来了──这不就是JSP的原理嘛！的确，这种&#8221;编译&#8221;用在PHP这样的解释性脚本引擎上显得匪夷所思，但是仔细想想，JAVA不也是由JVM解释执行的吗？这就叫&#8221;没有做不到，只有想不到&#8221;。<br />
        既然谈到了JAVA，就再对PHP的未来发表一点看法。PHP官方网站上宣布了要在2003年年底发布PHP5.0版。这个版本拥有很多崭新的特性：比如异常处理，命名空间，更加面向对象等等。可以说越来越向JAVA靠拢，SMARTY也是新特性之一，使得PHP更适用于大中型项目的开发。但是似乎离我当初选择它的原因──灵巧易用──越来越远了。但就一个软件的生存周期来看，PHP正处在成长期，开发者赋予它更多的功能，以期能胜任商业应用是利大于弊的。作为PHP的忠实用户，肯定不希望PHP总是被人指责&#8221;能力不足&#8221;吧？<br />
        为什么选择SMARTY，仅仅因为它很像JSP？当然有更为充分的理由。首先，除了第一次编译的成本比较高之外，只要不修改模板文件，编译好的cache脚本就随时可用，省去了大量的parse()时间；其次SMARTY像PHP一样有丰富的函数库，从统计字数到自动缩进、文字环绕以及正则表达式都可以直接使用；如果觉得不够，比如需要数据结果集分页显示的功能，SMARTY还有很强的扩展能力，可以通过插件的形式进行扩充。<br />
        事实胜于雄辩。我设计了一个测试程序，通过速度和开发难度这两个因素对比了一下SMARTY和PHPLIB template，选PHPLIB template的原因是在patrick的文章 《在PHP世界中选择最合适的模板》中有一个PHPLIB template对Fast template的竞赛，结果PHPLIB template大获全胜，这使得SMARTY有了一个很好的对手。在测试之前，先谈一下在安装过程中需要注意的问题。</p>
<p><strong>三、可能遇到的问题<br />
        </strong>在SMARTY的 官方网站上，有详尽的用户手册，可以选择在线HTML和PDF格式的版本。这里就不再涉及手册上已有的内容，只是把初次使用可能遇到的问题做个解释。</p>
<p> </p>
<p align="center"><img class="alignnone size-full wp-image-20" title="03" src="http://php.nyist.net/wp-content/uploads/2009/08/03.jpg" alt="03" width="359" height="147" /></p>
<p>        第一个问题就很要命：提示说找不到所需文件？并不是每一个人都按照SMARTY默认目录结构来写应用的。这里需要手工指定，假设目录结构如下：<br />
就需要在index.php里指定目录结构：</p>
<table style="width: 572px; height: 94px;" border="0" cellspacing="1" cellpadding="10" width="572" bgcolor="#0099cc">
<tbody>
<tr>
<td style="WORD-BREAK: break-all; LINE-HEIGHT: 18px" width="100%" bgcolor="#ddedfb"><span><span style="font-size: x-small;">$smart-&gt;template_dir = &#8220;smarty/templates/&#8221;;<br />
$smart-&gt;compile_dir = &#8220;smarty/templates_c/&#8221;;<br />
$smart-&gt;config_dir = &#8220;smarty/configs/&#8221;;<br />
$smart-&gt;cache_dir = &#8220;smarty/cache/&#8221;;</span></span></td>
</tr>
</tbody>
</table>
<p>        第一个问题解决了，紧接着就是第二个：我刚用Dreamweaver生成的漂亮模板怎么不能用？并不是模板文件有什么问题，而是因为SMARTY默认的标记分隔符是{}，不巧的是Javascript肯定包含这个标记。好在我们可以用任意字符当作分隔符，再加上这两句：</p>
<table style="width: 573px; height: 58px;" border="0" cellspacing="1" cellpadding="10" width="573" bgcolor="#0099cc">
<tbody>
<tr>
<td style="WORD-BREAK: break-all; LINE-HEIGHT: 18px" width="100%" bgcolor="#ddedfb"><span><span style="font-size: x-small;">$smart-&gt;left_delimiter = &#8220;{/&#8221;;<br />
$smart-&gt;right_delimiter = &#8220;/}&#8221;;</span></span></td>
</tr>
</tbody>
</table>
<p>这下安装就基本完成，没问题了。</p>
<p><strong>四、反衬和类比<br />
        </strong>先构思一下对测试的设计。主要的评比因素当然是速度了。为了进行速度测试，采取了算术平均数的作法。在测试页面中重复将页面生成N遍，再对比总页面生成时间。另一个重要因素是易用性(至于扩展性不用比较已经有结果了)，所以使用的模板不能太小。我用的是我个人主页的的页面，一个用Firework+Dreamweaver生成的HTML文件，大小约7K。其中的变量设置也采取最常用的区块，在PHPLIB template里叫block,而SMARTY则称section。别小看这称呼的不同，易用性标准分两块：模板文件和脚本文件的语法是否简明易用。</p>
<p> </p>
<p align="center"> </p>
<p>        下面就深入到测试中来。先看看两种模板文件的语法：蓝条左边是PHPLIB template的模板，右边属于SMARTY。个人偏好是不一样的，所以这里不作评论。着重对比一下脚本里的处理语句，先看PHPLIB template的：</p>
<table style="width: 570px; height: 166px;" border="0" cellspacing="1" cellpadding="10" width="570" bgcolor="#0099cc">
<tbody>
<tr>
<td style="WORD-BREAK: break-all; LINE-HEIGHT: 18px" width="100%" bgcolor="#ddedfb"><span><span style="font-size: x-small;">$tpl-&gt;set_file(&#8217;phplib&#8217;, &#8216;bigfile.htm&#8217;);<br />
$tpl-&gt;set_block(&#8217;phplib&#8217;, &#8216;row&#8217;, &#8216;rows&#8217;);<br />
for ($j = 0; $j &lt; 10; $j++){<br />
        $tpl-&gt;set_var(&#8217;tag&#8217; ,&#8221;$j&#8221;);<br />
        $tpl-&gt;parse(&#8217;rows&#8217;, &#8216;row&#8217;, true);<br />
}<br />
$tpl-&gt;parse(&#8217;out&#8217;, &#8216;phplib&#8217;);<br />
$tpl-&gt;p(&#8217;out&#8217;);</span></span></td>
</tr>
</tbody>
</table>
<p>下面是SMARTY的：</p>
<table style="width: 570px; height: 58px;" border="0" cellspacing="1" cellpadding="10" width="570" bgcolor="#0099cc">
<tbody>
<tr>
<td style="WORD-BREAK: break-all; LINE-HEIGHT: 18px" width="100%" bgcolor="#ddedfb"><span><span style="font-size: x-small;">$smart-&gt;assign(&#8217;row&#8217;,$row);<br />
$smart-&gt;display(&#8217;bigfile.htm&#8217;);</span></span></td>
</tr>
</tbody>
</table>
<p>        SMARTY只用了tags和row两个变量，而PHPLIB template则多了模板文件的handler，还有一个莫名其妙的out。说实在的这个out我当初学的时候就不知道为什么要存在，现在看起来，还是别扭。为什么SMARTY少那么多处理语句呢？答案是工作由引擎完成了。如果你喜欢钻研源程序，可以发现在Smarty_compiler.class.php里有一个名叫_compile_tag()的函数，由它负责把section这个标签转换成php语句。这不是一个普通的标签，它带有参数和数据，节省了脚本编程的工作量，而模板标签上的工作量相差又不大，可以判定在易用性上SMARTY高出一畴。</p>
<p>下面该轮到我们最关注的速度了，毕竟对于一个熟练的web开发者来说，掌握再困难的工具不过是时间问题，何况模板引擎这种学习曲线平缓的技术。而速度则是web应用程序的生命，尤其是模板引擎使用在并发访问量很大的站点上，这点就更重要了。测试开始前，我觉得PHPLIB template会在这一环节上胜出，因为它经历了很多次升级，已经基本没有什么bug,而且SMARTY的引擎个头太大，不像它的对手只有两个文件。<br />
         果然，测试结果如下图，PHPLIB template有25%的速度优势：</p>
<p> </p>
<p align="center"><img src="http://www.blueidea.com/articleimg/2006/01/3148/04.gif" border="0" alt="" width="457" height="188" /></p>
<p>但不会一直这样，我又按了一次刷新，这次得到了不一样的结果：</p>
<p align="left"><img src="http://www.blueidea.com/articleimg/2006/01/3148/05.gif" border="0" alt="" width="461" height="189" /></p>
<p align="left">PHPLIB基本没变化，但是SMARTY提高了25%的速度。继续刷新，得到的都是类似于第二次的结果：SMARTY比PHPLIB template 快上近10%。我想这就是编译型比解释型快的原理了。SMARTY引擎本身就很大，加上还要把模板编译成php文件，速度当然比不上小巧的PHPLIB template。但这只是第一次的情况。第二次接到请求的时候，SMARTY发现该模板已经被编译过了，于是最耗时的一步被跳过了，而对手还要按部就班地进行查找和替换工作。这是编译原理里讲到的很经典的&#8221;用空间换时间&#8221;例子。<br />
<strong>五、结论<br />
         </strong>结论就是如果你已经爱上SMARTY了，那么还等什么呢？当然并不是说它就全能，就如同我用MVC模式来写我的个人网站，非但没有减少工作量，反而总是要为不同层次间的耦合劳神。<br />
        SMARTY不适合什么呢？举个手册里的经典例子：天气预报网站。我还想到一个：股市大盘。在这种网站上用SMARTY会由于经常的重编译而效率偏低，还是PHPLIB template更为适合。<br />
        本文并不是为了对比两种引擎，而是为了说明SMARTY的优势。使用它最有意义之处在于它是PHP新体系的一部份，作为一支独立的力量，除了.NET和JAVA ONE这两大体系之外，大中型web开发还有别的选择。这对于GNU项目来说，其意义无异于刘邓大军千里跃进大别山。</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=17</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP5.3中的新特性之：命名空间</title>
		<link>http://php.nyist.net/?p=10</link>
		<comments>http://php.nyist.net/?p=10#comments</comments>
		<pubDate>Sun, 19 Jul 2009 15:40:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP技术文章]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=10</guid>
		<description><![CDATA[PHP对命名空间的支持是一项人们期待已久的特性了。加入这一特性的主要目的是为了解决PHP中的超长类名问题。如果你准备开发一个大一点的库，那就不得不使用比较长的类名来避免命名冲突的问题。]]></description>
			<content:encoded><![CDATA[<p>我在上一篇文章中曾经提到过，PHP 5.3版本将会在2008年的早些时候发布， 现在我想应该是时候谈一谈这个版本的新特性了。在这些特性中，重量级的特性包括 命名空间, 静态延迟绑定(late static binding) 以及 mysqlnd，当然还有其他的一些有趣的改进， 比如 __callStatic和dynamic static calls。这一节我们先来分析一下“命名空间”的细节。<br />
PHP对命名空间的支持是一项人们期待已久的特性了。加入这一特性的主要目的是为了解决PHP中的超长类名问题。如果你准备开发一个大一点的库，那就不得不使用比较长的类名来避免命名冲突的问题，</p>
<p><span id="more-10"></span></p>
<p>比如下面这种怪物名字： Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive.</p>
<p>从5.3开始你可以使用命名空间来组织你的代码了。 不同的命名空间内可以包含相同名字的类、函数以及常量。 声明一个命名空间非常简单，只需要在文件的开始处加上namespace 语句，像下面这样<br />
<span id="more-12"> </span></p>
<p> </p>
<p><!--p<br-->/** classes/my/foo/MyClass.php */</p>
<p>namespace my::foo;</p>
<p>class MyClass {}//定义一个类</p>
<p>// 当然，也可以定义函数和常量<br />
function myFunc() { }<br />
const MY_CONST = ‘foo’;</p>
<p>?&gt;</p>
<p>有多种方法来访问<br />
<!--p<br-->/** test.php */<br />
include(‘classes/my/foo/MyClass.php’);</p>
<p>// 可以随时通过完整的名称来访问一个类<br />
$foo = new my::foo::MyClass();</p>
<p>// 还可以使用use语句来导入一个命名空间<br />
use my::foo;<br />
// 然后，通过foo来引用 my::foo这个命名空间<br />
$foo = new foo::MyClass();</p>
<p>// 也可以只导入一个类<br />
use my::foo::MyClass;<br />
$foo = new MyClass;</p>
<p>// 可以为命名空间或者命名空间中的类创建别名<br />
use my::foo as MyFoo;<br />
use my::foo::MyClass as MyFooClass;<br />
$foo = new MyFoo::MyClass();<br />
$foo = new MyFooClass();</p>
<p>// 注意， 下面的两种写法是等价的：</p>
<p>use my::foo;<br />
use my::foo as foo;</p>
<p>// 也可以用同样的方法来访问函数和常量<br />
my::foo::myFunc();<br />
myFoo::myFunc();<br />
my::foo::MY_CONST;<br />
myFoo::MY_CONST;</p>
<p>?&gt;</p>
<p>use语句只能导入命名空间和类，下面这种写法就不行： use my::foo::MY_CONST;。一个use语句的有效范围是从它被定义开始直到文件的结尾，你可以在全局范围内任何地方使用它。 你可以在多个文件中使用相同的命名空间。但是一个文件只应该包含一个命名空间 (这一行为可能会在最终版本中被改变，也可能用package来替换namespace关键字 <img src='http://php.nyist.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> )。 尽管不能import一个函数或者常量， 但是仍然可以使用一些前缀来从命名空间中访问他们。在PHP 5.3的早期版本中，import 关键字被用来代替 use， 现在这一点已经被改变了。<br />
“空”命名空间 (::)</p>
<p>如果你在函数或常量名前面使用 :: 前缀， 他们将会被从当前的引用规则中独立出来，这在命名空间中十分有用。<br />
Life with namesapces (porting code to PHP 5.3)</p>
<p>如果你打算使用命名空间，那么下面几处缺陷是你应该注意的：<br />
类的命名规则</p>
<p>首先，要避免在类名中使用PHP的保留字，仔细看下面的代码：<br />
<!--p<br-->/** classes/my/form/element/static.php */<br />
class MyFormElementStatic {}<br />
?&gt;</p>
<p>而在使用命名空间后，代码会变成这样：<br />
<!--p<br-->/** classes/my/form/element/static.php */<br />
namespace my::form::element;<br />
class Static {}<br />
?&gt;</p>
<p>但是因为Static 是一个保留字，所以这段代码最终会导致一个致命错误。如果你有很多类似名字的类，那么对你来说这确实是一个坏消息。<br />
Autoloading</p>
<p>从5.3版本开始， __autoload()将使用类的全路径名称，这就意味着如果你已经使用了__autoload()，就要对它做一下适当的修改，举个简单的例子<br />
<!--p<br-->/** test.php */<br />
function __autoload($className)<br />
{<br />
require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;<br />
}</p>
<p>$foo = new my::foo::MyClass();<br />
?&gt;</p>
<p>或者选择 SPL的形式 来完成类似的功能<br />
<!--p<br-->/** classes/my/core/classloader.php */<br />
namespace my::core;</p>
<p>function classLoader($className)<br />
{<br />
require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;<br />
}</p>
<p>spl_autoload_register(‘my::core::classLoader’);<br />
?&gt;</p>
<p><!--p<br-->/** test.php */<br />
require ‘classes/my/core/classLoader.php’;<br />
$foo = new my::foo::MyClass();</p>
<p>?&gt;</p>
<p><strong>get_class(), get_parent_class(), 及其他.</strong></p>
<p>当你使用这类函数的时候也要注意，他们也同样返回一个类的全路径名称。</p>
<p><strong>反射 API</strong></p>
<p>反射 API 同样也要反映出这种新的语言特性，这部分的计划是这样的：</p>
<p>* 创建一个包含下面这些方法的ReflectionNamespace类： getName(), getClasses(), getFunctions(), getFiles()<br />
* 扩展ReflectionClass 和ReflectionFunction 类并加入getNamespace() 这一新方法。</p>
<p><strong>下面这些知识也是你应该了解的：</strong></p>
<p><strong>常量： __NAMESPACE__<br />
</strong><br />
在这一版本中我们引入了一个新的常量: __NAMESPACE__，它包含了当前引用的命名空间的名字，比如你可以使用下面的方式来实现一个SPL风格的loader<br />
<!--p<br-->/** classes/my/core/classloader.php */<br />
namespace my::core;</p>
<p>function classLoader($className)<br />
{<br />
require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;<br />
}</p>
<p>spl_autoload_register(__NAMESPACE__.‘::classLoader’);</p>
<p>?&gt;</p>
<p><strong>PHP对命名空间内的元素的解析流程</strong></p>
<p>我不想对这部分内容作过多的解释，你可以在 PHP namespaces README 这里阅读到详细的规则（fidy注：作者对这部分的解释确实比较“简略”，建议还是读一下那个readme，其中的关键部分我会在后面贴出来）。 记住一个要点，就是PHP会首先参照当前的命名空间来解析一个元素， 让我们来看例子<br />
<!--p<br-->namespace my::foo;<br />
…<br />
mysql_connect();<br />
…<br />
::mysql_connect();<br />
?&gt;<br />
当你调用mysql_connect()的时候，PHP会首先到my::foo 下面去找这个函数。如果找到了就调用它，没找到的话再去调用PHP内部集成的mysql_connect()函数，而其他命名空间中定义的mysql_connect()函数你是没办法访问到的。而使用::bar() 这种写法则可以访问到全局命名空间中的函数，它可能是PHP的内部函数，也可能是用户自定义的。<br />
<!--p<br-->namespace my::foo;</p>
<p>core::bar();</p>
<p>::core::bar();<br />
?&gt;</p>
<p>在core::bar()这种情况下， PHP 会首先尝试调用my::foo::core 下面的函数bar()，如果没有找到，则尝试调用my::foo命名空间下的类core（如果存在的话）的静态方法bar()，最后尝试调用PHP的内置类core的bar()方法。</p>
<p>::core::bar()这种情况下，PHP会首先尝试调用core命名空间下的 函数 bar() ，然后尝试调用全局范围内类core的静态方法bar()。</p>
<p>现在PHP对命名空间的支持还没有完成，很可能将来会做一些必要的改动。</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=10</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>test</title>
		<link>http://php.nyist.net/?p=8</link>
		<comments>http://php.nyist.net/?p=8#comments</comments>
		<pubDate>Sun, 19 Jul 2009 15:39:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[我院服务器PHP应用]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=8</guid>
		<description><![CDATA[特殊贴
]]></description>
			<content:encoded><![CDATA[<p>特殊贴</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=8</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world！</title>
		<link>http://php.nyist.net/?p=1</link>
		<comments>http://php.nyist.net/?p=1#comments</comments>
		<pubDate>Sun, 19 Jul 2009 15:04:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP最新资讯]]></category>

		<guid isPermaLink="false">http://php.nyist.net/?p=1</guid>
		<description><![CDATA[欢迎使用 WordPress 。这是系统自动生成的演示文章。编辑或者删除它，开始您的博客！
]]></description>
			<content:encoded><![CDATA[<p>欢迎使用 WordPress 。这是系统自动生成的演示文章。编辑或者删除它，开始您的博客！</p>
]]></content:encoded>
			<wfw:commentRss>http://php.nyist.net/?feed=rss2&amp;p=1</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
