PHP编程开发的10条原则

  1. 在合适的时候使用PHP – Rasmus Lerdorf

没有谁比PHP的创建者Rasmus Lerdorf明白PHP用在什么地方是更合理的,他于1995年发布了PHP这门语言,从那时起,PHP就像燎原之火,烧遍了整个开发阵营,改变了互联网的世界。可是,Rasmus并不是因此而创建PHP的。PHP是为了解决WEB开发者的实际问题而诞生的。

和许多开源项目一样,PHP变得流行,流行的动机并不能用正常的哲学来进行解释,甚至流行得有些孤芳自赏。它完全可以作为一个案例,一个解决各种Web问题的工具需求所引起的案例,因此当PHP刚出现的时候,这种工具需求全部聚焦到PHP的身上。

但是,你不能奢望PHP可以解决所有问题。Lerdorf是第一个承认PHP只是一种工具的人,并且PHP也有很多力所不能及的情况。

根据工作的不同来选择合适的工具。我跑了很多家公司,为了说服他们部署和使用PHP,但是这并不意味着PHP对所有问题都适用。它只是可以一个解决大部分问题的front-end脚步语言。

作为一个web开发者,尝试用PHP解决所有问题是不科学的,同时也会浪费你的时间。当PHP玩不转的时候,不要犹豫,试用一下其他的语言吧。

  2. 使用多表存储提高规模伸缩性 – Matt Mullenweg

没有人愿意质疑Matt Mullenweg在PHP方面的权威性,他开发了这个星球上最流行的blog系统,(依靠一个强大的社区力量支持): WordPress. 创建Wordpress以后,Matt和他的团队启动了WordPress.com平台,一个基于WordPress MU的免费blog站点。现在,Wordpress.com已经拥有大约400万用户, 这些用户每天提供超过 140,000篇的日志。

如果有人知道如何让网站的规模伸缩自如,这个人一定是Matt Mullenweg。2006年的时候 Matt对Wordpress的数据结构进行了前瞻性的改进,并且解释了为什么Wordpress MU对每个blog使用独立的MYSQL表格, 而不是把所有的blog数据都塞进一个巨大的表格。

我们测试过这个方法,但是发现如果要扩展它的伸缩性,代价太高。如果用一个整体的数据结构,在大流量面前,你将会面临服务器硬件的问题。在MU里面。用户们都被分布到独立的表格当中,并且可以轻易地组织起来。举个例子,WordPress.com把用户的数据分散存储到4096个数据库中,这些数据库可以分散大规模的数据访问,实现流量和压力分流。

数据表的可迁移性让代码(blog)可以运行得更快,并且让系统具备更强的伸缩性。依靠强大的缓存策略和灵活的数据库运用策略, Matt向人们展示了时下最流行的Facebook和Wordpress.com都可以在PHP下稳定运行,并且处理惊人的访问量。

  3. 千万不要相信用户 – Dave Child

Dave Child是Added Bytes (previously ilovejackdaniels.com) 网站的核心人物,这个网站以他出色的《cheat sheets for many programming languages》而闻名。 Dave为很多英国的公司服务,并且已经在编程世界里树立起相当的权威。

Dave为PHP开发者提供了很多深谋远虑的建议,并总结成了《writing secure code in PHP》:千万不要相信你的用户,他们甚至可能会伤害你。

有一条web开发的基本原则,我重复多少遍都觉得不够,那就是:千万不要相信你的用户,同时要假设你网站中的每个数据单元都是从用户那里收集来的恶意代码。很多时候,你必须用JAVAscript在客户端检验表单提交过来的内容, 如果你习惯了如此,那么,这是一个好习惯。如果安全性对你来说很重要,这就是最重要最需要学习的原则。

Dave目前正致力于为它的《Writing Secure PHP》系列书籍整理实例,书的最后他说:

最后,变得偏执一点吧。除非你认为你的站点永远不会受到攻击,否则就正视所有的问题,当问题真正发生的时候,你的情况会变得很糟。你需要把每个用户都看成会带来一场攻防站的黑客,想尽一切办法来保护站点的安全,同时想好相应问题的解决方案。

  4. 多使用PHP缓存 – Ben Balbo

Ben Balbo开发了Site Point,一个为developers和designers提供指导的网站。他是墨尔本PHP开发和开源俱乐部的成员, 因此他对PHP有一定的了解,同时对PHP caching有一定的想法和经验

如果你拥有一个访问量很大,但更新并不频繁的站点(比如blog,基于某种CMS),或许它需要进行一些改造,这些改造不会花费太多的时间,但是对性能有突出的贡献。 如果要为一个复杂/更新频率很快的站点建立缓存机制,过程可能会很曲折,但是好处也是显而易见的。

PHP缓存技术有很多种,Ben为我们推荐了如下一些:

缓存函数的运行结果

设置过期时间

缓存IE下载的文件

模板缓存技术

Cache_Lite

由于PHP作为动态语言的特性,缓存机制对于更新频率并不快的站点来说非常重要。

  5. 使用IDE, Templates和Snippets加速PHP开发 – Chad Kieffer

当Chad Kieffer从UI设计和数据库优化的工作中抽身出来的时候,他会在他的博客2 tablespoons上分享很多技术经验。由于Chad多方面的全面发展,他经常可以发现其他程序员不能发现的问题,并形成相关经验,尤其是他开发网站的方法。他参与了网站开发的各个环节,因此他的建议对于提高网站开发的大局观非常有用。

Chad认为使用Eclipse PDT(Eclipse’s PHP development package) 这样的IDE,同时使用一些模板技术和开源项目可以有效地提高PHP的开发速度。

紧凑的计划,长长的to do lists以及deadlines让开发人员非常苦闷。不过有些功能,比如Eclipse Templates,可以有效减少编码的时间和出错的几率。

通常来说,任何项目都可以自动化,自动化程度越高, 你完成项目的时间就越短。花时间来开发使用频率很高的框架和模板,将会节省你以后更多时间。同时,使用像Eclipse and the PDT package这样的IDE,你会发现效率得到明显提高,IDE可以自动闭合,补全分号并且可以在本地debug。

  6. 利用好PHP的过滤函数 – Joey Sochacki

或许Joey Sochacki并不像Matt Mullenweg那样有名 ,但他也是一个经验丰富的开发者,并且通过他的博客Devolio分享了很多技术经验

Joey发现在编写php代码的过程中有很多地方需要进行过滤,但却并没有太多的coder关注php的内置过滤函数。

过滤数据是我们经常需要做的事情,但是很多功能丰富的PHP内置过滤函数却不为人知。使用类似filter_* 的PHP内置函数,我们几乎可以处理所有的过滤任务,包括数据类型验证/URL/email和IP地址验证/特殊字符处理等等。

过滤是一件复杂的事情,但是我相信joey的发现会给你很多启发,让你认识到PHP强大的过滤功能。

  7. 使用PHP框架 – Josh Sharp

对于是否应该使用Z end, CakePHP, Code Igniter, 或者 其他PHP框架,一直存在着很多争议,但是在web开发者的心中,他们有自己衡量的标准。

Josh Sharp自己创建了一家提供面包和黄油服务的网站,因此他对于使用PHP框架来开发网站有一定的经验。他认为使用一个PHP框架来进行项目开发(use a PHP framework ),可以有效地节省时间,并且减少出错的几率。为什么?因为他觉得PHP实在是太好上手了。

PHP的易于使用有时候也有缺陷,因为并不严格的语法,经常会导致很多错误代码的诞生。但如果使用一个PHP框架,出错的几率就会大大减少。

PHP框架可以让你的代码结构更加规范,并且节省大量时间。

8. 不要使用PHP框架 – Rasmus Lerdorf

与Josh的观点恰恰相反,PHP的鼻祖Rasmus Lerdorf却认为最好不要使用PHP框架,为什么?因为不基于框架的PHP性能更好。Rasmus在Drupalcon 2008的演讲上,用“Hello World”的例子来对比了一些框架PHP和简单PHP之间的性能,结果显示框架PHP的性能要远远落后。

  9. 使用批处理 – Jack D. Herrington

Jack Herrington对PHP世界并不陌生, 并且为大名鼎鼎的IBM developerWorks贡献过超过30篇的专搞, 同时出版过《PHP Hacks》的书,因此他是一个真正的专家。

Herrington推荐使用批处理和Cron来代替那些可以运行在后台的程序脚步,Web用户并不愿意在线等待你的处理过程,所以有些事情更适合放到后台来处理。

诚然,在某些情况下,这有点大材小用了,但是你可以清楚地看到,使用Cron, MySQL, PHP面向对象的方法以及Pear::DB这些便捷的工具来创建一个批处理工具并不是一件复杂的事情。

Jack认为使用cron, PHP和MySQL在后台处理一些任务,比起多进程的业务逻辑要划算得多。

两种方法我都尝试过,我认为Cron非常符合”Keep It Simple, Stupid” (KISS) 的原则,它让后台处理变得简单。与多进程的业务逻辑相比,它没有内存溢出的风险。你可以创建一个简单的批处理脚本,并且在cron中运行,这个脚本会定时检查是否有任务需要处理,处理完之后就会自动退出,因此你不用担心是否有进程卡壳,或者陷入死循环。

  10. 及时启用错误报告 – David Cummings

David Cummings有一个专门提供CMS软件服务的公司 ,并且获得过几次奖 ,他有非常丰富的PHP开发经验。David曾经写过《two PHP tips he wished he’d learned in the beginning》,其中一点就是:及时启用错误报告,这会节省大量的时间。

我告诉人们,最重要的事情就是最大程度地开启PHP的错误报告,为什么?因为PHP可能会隐藏很多小问题:

变量没有预定义

在代码片段中引用了不可用的变量

使用了未定义的常量这些因素看起来并不是什么大事,除非你在使用面向对象的方法编写一些类库。通常,关闭错误报告将可能使你付出更大的成本来维护你的代码。

错误报告可以帮你轻易地找到代码的问题所在,如果错误报告的等级够高,细微的错误都能被立即发现,帮助你节省整体debug的时间。

二维数组排序(array_multisort)

在调取数据的时候由于条件是id in (‘1’,’2’…),类似于这样的排序一般是按照括号里边写的顺序,也可以指定给他顺序

就是加入 select * from table where id IN (3,6,9,1,2,5,8,7) order by field(id,3,6,9,1,2,5,8,7);  红色部分,

但是我要的是按照其中某个字段的排序,所以做了如下排序得到了想要的结果

 

php计算两个文件的相对路径

网上也看到很多方法,但是有写方法在某些特定目录下不好使考虑不周全

以下代码可以完全实现(可能效率不怎么样)

或者

 

关于php计算两个路径的相对路径问题

此问题可能有很多解决办法,这是从网上查到的(大部分是这个代码)代码如下:

这里有个问题!!!!!!!!在子目录中有相同的文件名怎么样

如果这个路径是这样的:

那么将会返回一个错误的路径,因为子目录有重复($a2array[‘3’] = $b2array[‘3’]),返回的路径是../../13/../

所以上边的方法是不严谨的!!!!!!!!!!

以下是我自己写的

php抽象类(abstruct)和接口(interface)的说明、区别和应用场景

一、 抽象类abstract class

.抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。

.抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。

.如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。

  1. abstract class  

  2.   

  3.     protected $value1 0;  

  4.     private $value2 1;  

  5.     public $value3 2;  

  6.       

  7.     public function my_print()  

  8.      

  9.         echo “hello,world/n”;  

  10.      

  11.       

  12.     abstract protected function abstract_func1();  

  13.     abstract protected function abstract_func2();  

  14.  

  15. abstract class extends  

  16.  

  17.     public function abstract_func1()  

  18.      

  19.        echo “implement the abstract_func1 in class A/n”;  

  20.      

  21.       

  22.     //abstract protected function abstract_func2();  

  23.  

  24. class extends  

  25.  

  26.     public function abstract_func2()  

  27.      

  28.        echo “implement the abstract_func2 in class A/n”;  

  29.      

  30.  

.如果像下面这样创建了一个继承自 的子类 ,但是不实现抽象方法 abstract_func() 

  1. Class extends A{};  

那么程序将出现以下错误:

  1. Fatal error: Class contains abstract method and must therefore be declared abstract or implement the remaining methods (A::abstract_func)  

.如果 实现了抽象方法 abstract_func() ,那么 中 abstract_func() 方法的访问控制不能比 中 abstract_func() 的访问控制更严格,也就是说:

(1)如果 中 abstract_func() 声明为 public ,那么 中 abstract_func() 的声明只能是 public ,不能是 protected 或 private

(2)如果 中 abstract_func() 声明为 protected ,那么 中 abstract_func() 的声明可以是 public 或 protected ,但不能是 private

(3)如果 中 abstract_func() 声明为 private ,嘿嘿,不能定义为 private 哦!( Fatal error : Abstract function A::abstract_func() cannot be declared private 

二、 接口interface

.抽象类提供了具体实现的标准,而接口则是纯粹的模版。接口只定义功能,而不包含实现的内容。接口用关键字 interface 来声明。

. interface 是完全抽象的,只能声明方法,而且只能声明 public 的方法,不能声明 private 及 protected 的方法,不能定义方法体,也不能声明实例变量 。然而, interface 却可以声明常量变量 。但将常量变量放在 interface 中违背了其作为接口的作用而存在的宗旨,也混淆了 interface 与类的不同价值。如果的确需要,可以将其放在相应的 abstract class 或 Class 中.

  1. interface iA  
  2.  
  3.     const AVAR=3;  
  4.     public function iAfunc1();  
  5.     public function iAfunc2();  
  6.  
  7. echo iA:: AVAR;  

.任何实现接口的类都要实现接口中所定义的所有方法

  1. class implements iA  
  2.  
  3.     public function iAfunc1(){echo “in iAfunc1″;}  
  4.     public function iAfunc2(){echo “in iAfunc2″;}  
  5.  

否则该类必须声明为 abstract 

  1. abstract class implements iA{}  

.一个类可以在声明中使用 implements 关键字来实现某个接口。这么做之后,实现接口的具体过程和继承一个仅包含抽象方法的抽象类是一样的。一个类可以同时继承一个父类和实现任意多个接口。 extends 子句应该在 implements 子句之前。 PHP 只支持继承自一个父类,因此 extends 关键字后只能跟一个类名。

  1. interface iB  
  2.  
  3.     public function iBfunc1();  
  4.     public function iBfunc2();  
  5.  
  6. class extends implements iA,iB  
  7.  
  8.     public function abstract_func1()  
  9.      
  10.        echo “implement the abstract_func1 in class A/n”;  
  11.      
  12.     public function abstract_func2()  
  13.      
  14.        echo “implement the abstract_func2 in class A/n”;  
  15.      
  16.     public function iAfunc1(){echo “in iAfunc1″;}  
  17.     public function iAfunc2(){echo “in iAfunc2″;}  
  18.     public function iBfunc1(){echo “in iBfunc1″;}  
  19.     public function iBfunc2(){echo “in iBfunc2″;}  
  20.  
  21.    
  22. class extends implements iA,iB  
  23.  
  24.     public function abstract_func1()  
  25.      
  26.        parent::abstract_func1();  
  27.        echo “override the abstract_func1 in class A/n”;  
  28.      
  29.     public function abstract_func2()  
  30.      
  31.        echo “implement the abstract_func2 in class A/n”;  
  32.      
  33.     public function iAfunc1(){echo “in iAfunc1″;}  
  34.     public function iAfunc2(){echo “in iAfunc2″;}  
  35.     public function iBfunc1(){echo “in iBfunc1″;}  
  36.     public function iBfunc2(){echo “in iBfunc2″;}  
  37.  

.接口不可以实现另一个接口,但可以继承多个

  1. interface iC extends iA,iB{}  
  2. class implements iC  
  3.  
  4.     public function iAfunc1(){echo “in iAfunc1″;}  
  5.     public function iAfunc2(){echo “in iAfunc2″;}  
  6.     public function iBfunc1(){echo “in iBfunc1″;}  
  7.     public function iBfunc2(){echo “in iBfunc2″;}  
  8.  

三、 抽象类和接口的异同

1. 相同点:

(1) 两者都是抽象类,都不能实例化。

(2) interface 实现类及 abstract class 的子类都必须要实现已经声明的抽象方法。

2. 不同点:

(1) interface 需要实现,要用 implements ,而 abstract class 需要继承,要用 extends 

(2) 一个类可以实现多个 interface ,但一个类只能继承一个 abstract class 

(3) interface 强调特定功能的实现,而 abstract class 强调所属关系。

(4) 尽管 interface 实现类及 abstract class 的子类都必须要实现相应的抽象方法,但实现的形式不同。 interface 中的每一个方法都是抽象方法,都只是声明的 (declaration, 没有方法体 ,实现类必须要实现。而 abstract class 的子类可以有选择地实现。这个选择有两点含义: a) abstract class 中并非所有的方法都是抽象的,只有那些冠有 abstract 的方法才是抽象的,子类必须实现。那些没有 abstract 的方法,在 abstract class 中必须定义方法体; b) abstract class 的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。

(5) abstract class 是 interface 与 class 的中介。 abstract class 在 interface 及 class 中起到了承上启下的作用。一方面, abstract class 是抽象的,可以声明抽象方法,以规范子类必须实现的功能;另一方面,它又可以定义缺省的方法体,供子类直接使用或覆盖。另外,它还可以定义自己的实例变量,以供子类通过继承来使用。

(6) 接口中的抽象方法前不用也不能加 abstract 关键字,默认隐式就是抽象方法,也不能加 final 关键字来防止抽象方法的继承。而抽象类中抽象方法前则必须加上 abstract 表示显示声明为抽象方法。

(7) 接口中的抽象方法默认是 public 的,也只能是 public 的,不能用 private , protected 修饰符修饰。而抽象类中的抽象方法则可以用 public ,protected 来修饰,但不能用 private 

3. interface 的应用场合

(1) 类与类之间需要特定的接口进行协调,而不在乎其如何实现。

(2) 作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。

(3) 需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。

(4) 需要实现特定的多项功能,而这些功能之间可能完全没有任何联系。

4. abstract class 的应用场合

一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:

(1) 定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口。可以用 abstract class 定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。

(2) 某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。 abstract 的中介作用可以很好地满足这一点。

(3) 规范了一组相互协调的方法,其中一些方法是共同的,与状态无关的,可以共享的,无需子类分别实现;而另一些方法却需要各个子类根据自己特定的状态来实现特 定的功能 

form表单的两种提交方式,submit和button的用法

两种form表单的提交方式:submit和button

1:submit方法

js验证代码:

html:form表单

<form action=”check.php” method=”post” onsubmit = “return check();”>
<input type=”text” id=”userid” name=”username” value=”” />
<input type=”text” id=”passid” name=”password” value=”” />
<input type=”submit” value=”提交” />
</form>

2:button方法

js验证代码:

html:from表单

<form id=”formid” action=”/plus/search.php” method=”post”>
<input type=”text” id=”userid” name=”username” value=”” />
<input type=”text” id=”passid” name=”password” value=”” />
<input type=”button” onclick = “check();” value=”提交” />
</form>

中文url传参(get中文传参)编码问题

在做后台开发的时候由于数据需求,查询条件为“中文”汉字,在其中就出现了一个问题:ajax获取数据利用url传参,正常在谷歌浏览器下ok没问题(在这个浏览器下做的开发),但是换到ie下不行了,刚开始以为哪里出错了,找到最后原来是这个url传参在ie下传到php页面后变成了gbk编码,那么你在utf-8的页面用gbk编码格式的中文查询肯定返回空!

问题叙述:中文url传参或者说接收$_GET中文参数在不同浏览器产生编码格式是不一样的,导致接收页面的字符不同查询的数据结果就没了!

解决办法:形象点说比如我们在度娘上搜索后,看地址栏上一堆乱七八糟的码,那个其实就将中文转码后的编码,php有一对函数urlencode(转码)和urldecode(解码)。比如<a href=”a.php?<?php echo urlencode(‘小明’) ?>”> ,在查看源代码的时候就会显示为<a href=”a.php?name=%E5%B0%8F%E6%98%8E”> ,在a.php页面接收时要用urldecode解码,这样经过解码的中文汉子就是正常的编码了  

问题扩展:

  urlencode()不同编码转换后的样式:

  中文 -> GB2312的Encode -> %D6%D0%CE%C4

  中文 -> UTF-8的Encode -> %E4%B8%AD%E6%96%87

  注意:Firefox对GB2312的Encode的中文URL支持不好,因为它默认是UTF-8编码发送URL的,但是ftp://协议可以,我试过了,我认为这应该算是Firefox一个bug。

除了“-_.”之外的所有非字母数字字符都将被替换成百分号“%”后跟两位十六进制数。
urlencode和rawurlencode的区别:urlencode将空格编码为加号“+”,rawurlencode将空格编码为加号“%20”。
如果要使用UTF-8的Encode,有两种方法:

一、将文件存为UTF-8文件,直接使用urlencode、rawurlencode即可。

二、使用mb_convert_encoding函数:

实例:

JavaScript中的URLEncode:
如:%E4%B8%AD%E6%96%87-_.%20%E4%B8%AD%E6%96%87-_.%20
encodeURI不对下列字符进行编码:“:”、“/”、“;”、“?”、“@”等特殊字符。

 

php会话控制(COOKIE、SESSION)知识

会话控制的两种方式:

cookie:

  1. 一种维持状态的方式
  2. Cookie其实就是一个文件,他是保存在客户端当中
  3. 没访问一次服务器,客户端浏览器会带着这个cookie信息去访问,服务器对应读取cookie信息
  4. 第一次访问,服务器设置一个cookie,将cookie信息存入到客户端浏览器当中
  5. 第二次访问,客户端浏览器带着cookie信息去访问服务器,服务器通过读取cookie信息来获取上一次访问的设置的信息
  6. $_COOKIE没有办法直接修改数组信息
  7. Setcookie前不允许有任何输出
  8. Cookie的删除要通过setcookie来设置过期时间
  9. Setcookie可以设置路径,设置的路径代表可以在本路径下获取该cookie信息,上级或者平级无法访问
  10. 如果没有设定过期时间,代表的意思是关闭浏览器cookie失效
  11. 如果没有给定path路径,代表的意思是设置cookie的有效路径为当前文件的路径

session:

  1. Session的信息是存储在服务器当中的
  2. Session是基于cookie的
  3. 客户端第一次访问服务器,服务器设置session,将详细的资料存入到session文件当中,然后将此session文件对应的session_id号交给客户端浏览器存入到cookie当中
  4. 客户端浏览器带着cookie来访问服务器,此时服务器会通过cookie当中的session_id来寻找服务器的session文件当中的对应的资料

设置session的步骤:

  1. 开启session环境Session_start();
  2. Session_name()获取ini当中的session.name的值
  3. Session_id()获取当前session的id号
  4.  如果我们想维持登录状态
    1. Setcookie(session_name(),session_id(),time()+3600);
  5.  删除session
    1. 开启session_start()
    2. 设置session的值为空或者unset
    3. 设置cookie的值过期
    4. 删除session文件【可选】

Cookie和session的关系和区别:

  1. 区别:
    1. Cookie文件是保存在客户端浏览器的
    2. Session文件是保存在服务器端的
  2. 关系:
    1. Session默认情况下离不开cookie
    2. Session的id号会保存在cookie当中,然后通过cookie当中的id号来对应去找对应的session文件

如果cookie被禁用掉,session还能使用吗?

  1. 默认情况下,不能使用session
  2. 特殊情况:
    1. 我们可以通过get的方式将session_id传递下去,前提是use_only_cookies=0
    2. 通过?session_name().”=”.session_id()
  3. 或者使用?SID
  4. 推荐使用SID,因为如果浏览器禁用cookie,SID会有值,值为session_name().”=”.session_id(),如果浏览器没有禁用cookie,SID是空的
  5. 将session的信息存入到数据库当中,或者自定义写文件

php发送邮件

php邮件类

smtp.php

执行

send_email.php