0%

我一生没做坏事,为何这样?
不是我自身的,却是我需要的,都是我所依赖的。一切需要外部提供的,都是需要进行依赖注入的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
//女孩接口
interface Girl {

}
//第一个女孩
class LoliGril implements Girl
{
public function __construct()
{
echo "LoliGril girl friend";
}
public function make()
{
echo "love LoliGril ";
}
}
//第二个女孩
class Vixen implements Girl {
public function __construct()
{
echo "Vixen girl friend";
}
public function make()
{
echo "love Vixen ";
}
}
//男孩
class Boy {
protected $girl;

public function __construct(Girl $girl) {//这里Girl 请使用接口,而不是类,这样所有继承这个接口的类都可以注入
$this->girl = $girl;
}

public function yoyo()
{
$this->girl->make();
}
}

$loliGirl = new LoliGril();
//$vixen = new Vixen();

$boy = new Boy($loliGirl);
$boy->yoyo();

//$boy = new Boy($vixen);

我不断奔跑,就是为了追上那个曾被给予厚望的自己

关于网络

网络由下往上分为 物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用层,三者从本质上来说没有可比性,socket则是对TCP/IP协议的封装和应用(程序员层面上)。也可以说,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据。
关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:
“我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容。
如果想要使传输的数据有意义,则必须使用到应用层协议。
应用层协议有很多,比如HTTP、FTP、TELNET等,也可以自己定义应用层协议。
WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上。”

socket是什么

实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API)。通过Socket,我们才能使用TCP/IP协议。Socket跟TCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等等。

socket和TCP/IP协议关系

“TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。
这个就像操作系统会提供标准的编程接口,比如win32编程接口一样,
TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。”
关于TCP/IP协议的相关只是,用博大精深来讲我想也不为过,单单查一下网上关于此类只是的资料和书籍文献的数量就知道,
这个我打算会买一些经典的书籍(比如《TCP/IP详解:卷一、卷二、卷三》)进行学习,今天就先总结一些基于基于TCP/IP协议的应用和编程接口的知识,也就是刚才说了很多的HTTP和Socket。
CSDN上有个比较形象的描述:HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
实际上,传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket本身不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的接口。

什么是TCP连接的三次握手

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”

利用Socket建立网络连接的步骤

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

HTTP链接的特点

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

TCP和UDP的区别

1、TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上(实际上也很大程度上保证了)保证了连接的可靠性;而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。
2、也正由于1所说的特点,使得UDP的开销更小数据传输速率更高,因为不必进行收发数据的确认,所以UDP的实时性更好。知道了TCP和UDP的区别,就不难理解为何采用TCP传输协议的MSN比采用UDP的QQ传输文件慢了,但并不能说QQ的通信是不安全的,因为程序员可以手动对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证啊什么的,即使是这样,UDP因为在底层协议的封装上没有采用类似TCP的“三次握手”而实现了TCP所无法达到的传输效率。

https://www.zhihu.com/question/39541968

没有捷径,逼迫自己!推掉不必要的社交,戒掉浪费时间的爱好,让自己感受到孤独和清醒,一把枪指着头,三个月内必须达到预想的目标,一件事,一件可以让自己更上一个台阶的事,会比无数看似有趣的生活妙招更让你喜欢自己!

安装

说明本教程基于centos6.5配置

安装:

1
2
yum list |grep vsftp
yum install vsftpd.x86_64 -y

检查开机自启:

1
chkconfig vsftpd on

vsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
这里的0-6 指的是系统的启动级别,意思是 当 系统在 3 ,命令行界面的方式下会自动开启
设置自启动:

1
chkconfig vsftpd on

启动:

1
service vsftpd start

配置文件路径:

1
/etc/vsftpd/

创建用户

1
2
useradd ftpuser
passwd ftpuser

这样新创建的用户可以通过ssh 直接登录到我们的系统
禁止用户访问22端口

ssh 配置

配置文件路径 /etc/ssh

1
vi /etc/ssh/sshd_config

添加

1
DenyUsers ftpuser

这样 ftpuser 这个用户就无法通过ssh远程登录服务器了

同样我们可以在创建用户的时候就指定该用户不可以通过shh登录

1
useradd myftp -s /sbin/nologin

限制ftpuser的登录目录

我们使用刚才创建的帐号通过类似 winscp 这样的工具可以方便的登录到我们的ftp服务器,登录以后默认的目录是改用户的家目录, 但是该ftp用户可以切换到任何一目录, 非常的不安全, 我们就需要限制改ftp的访问目录, 比如我们限制的我们的网站跟目录下 /var/www/alidayu/:
修改用户默认登入时的目录:

1
usermod -d /var/www/alidayu myftp

修改

1
vi /etc/vsftpd/vsftpd.conf
1
chroot_local_user=YES

重启

1
service vsftpd restart

这样用户就被限制到自己的默认目录;

修改默认端口

ftp服务的默认端口: 21

编辑 /etc/vsftpd/vsftpd.conf 文件,在该配置文件中添加此行:

1
listen_port=801

编辑 /etc/services 文件,将其中的

1
2
ftp 21/tcp 改为 ftp 801/tcp
ftp 21/udp 改为 ftp 801/udp

执行

1
2
3
/etc/init.d/vsftpd restart 
//或者
service vsftpd restart

重新启动 vsftpd 服务

在centos 7.x 上的配置

配置

1
2
3
4
5
6
7
8
yum install -y vsftpd
#安装vsftpd
yum install -y psmisc net-tools systemd-devel libdb-devel perl-DBI
#安装vsftpd虚拟用户配置依赖包
systemctl start vsftpd.service
#启动
systemctl enable vsftpd.service
#设置vsftpd开机启动

错误无法启动

由于centos7中vsftp的配置文件默认将 listen_ipv6=YES 这一行没有注释掉,而我们目前的网络环境还不支持ipv6,从而导致出现错误无法启动,所以解决方法是将 listen_ipv6=YES更改为:listen_ipv6=NO,或将这一行注释掉

按上面的方法注释掉 listen_ipv6=YES后,成功启动vsftp

我努力的目的就是想让我妈妈给自己买东西的时候能像给我买东西的时候一样干脆。
### UV(Unique visitor) 是指通过互联网访问、浏览这个网页的自然人。访问您网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只被计算一次。 一天内同个访客多次访问仅计算一个UV。 ### IP(Internet Protocol) 独立IP是指访问过某站点的IP总数,以用户的IP地址作为统计依据。00:00-24:00内相同IP地址之被计算一次。 ### UV与IP区别 你和你的家人用各自的账号在同一台电脑上登录新浪微博,则IP数+1,UV数+2。由于使用的是同一台电脑,所以IP不变,但使用的不同账号,所以UV+2 ### PV(Page View) 即页面浏览量或点击量,用户每1次对网站中的每个网页访问均被记录1个PV。用户对同一页面的多次访问,访问量累计,用以衡量网站用户访问的网页数量。 ### VV(Visit View) 用以统计所有访客1天内访问网站的次数。当访客完成所有浏览并最终关掉该网站的所有页面时便完成了一次访问,同一访客1天内可能有多次访问行为,访问次数累计。 ### PV与VV区别 如:你今天10点钟打开了百度,访问了它的三个页面;11点钟又打开了百度,访问了它的两个页面,则PV数+5,VV数+2.是指页面的浏览次数,VV是指你访问网站的次数。 > https://www.zhihu.com/question/20448467

it's my turn to fuck you
### TTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。

如何理解HTTP协议是无状态的

HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。

什么是长连接、短连接

在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。

但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:

1
Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

1
2
3
4
5
// nginx设置
http {
keepalive_timeout 120s 120s;
keepalive_requests 10000;
}

长连接和短连接的优点和缺点

长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。不过这里存在一个问题,存活功能的探测周期太长,还有就是它只是探测TCP连接的存活,属于比较斯文的做法,遇到恶意的连接时,保活功能就不够使了。在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可 以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。

短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

长连接和短连接的产生在于client和server采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。

http://www.cnblogs.com/0201zcr/p/4694945.html

当你厌恶你身边的人,你表达厌恶最好的方式不是和他们争吵,而是自己勤快点儿,加把劲离开他们。那样,他们就永远从你的生活中消失,和死了差不多。

if语句的替代语法

1
2
3
4
5
6
7
<?php if ($a == 5): ?>
<div>等于5</div>
<?php elseif ($a == 6): ?>
<div>等于5</div>
<?php else: ?>
<div>不是5就是6</div>
<?php endif; ?>

while替代语法

1
2
3
<?php while (expr): ?>
<li>循环点什么</li>
<?php endwhile; ?>

for替代语法:

1
2
3
<?php for (expr1; expr2; expr3): ?>
<li>循环点什么</li>
<?php endfor; ?>
1
2
3
4
### foreach替代语法
<?php foreach (expr1): ?>
<li>循环点什么</li>
<?php endforeach; ?>

switch替代语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
switch ($i):
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
endswitch;
?>

天地不仁,以万物为刍狗

问题

一向用的很好的chrome采集插件今天突然不工作了, 通过chrome的控制台查看, 原来的ajax 的post请求都变成了get,我靠, 看了一下代码没有改过啊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.ajax({
type:"POST",
url:infoUrl,
data:data,
datatype: "json",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
beforeSend:function(){
$("#submit-info").html("loading");
},
success:function(data){
chrome.storage.local.set({'return_product_id': data.data.id});
$("#return_product_id").text(data.data.id);
alert('产品创建成功, 可以开始上传图片了');
$("#image-container").css("display","block");
},
complete: function(XMLHttpRequest, textStatus){
$("#submit-info").html("提交信息");
},
error: function(){
console.log('error');
alert('产品创建失败, 请联系开发者...');
}
});

依然是post啊, 怎么发出去的请求就变成了get, 各种谷歌, 始终没有找到合适的解决办法…

原因

最近网站从原来的http升级为现在的https, 而我的请求还是原来的http, 所以就发生了这样的错误.

你心中的完美爱情是怎么样的? 可以有不完美。
### 任何从客户端获得的资料都是不可信任的

$_SERVER['HTTP_CLIENT_IP']这个头是有的,但是很少,不一定服务器都实现了。客户端可以伪造。
$_SERVER['HTTP_X_FORWARDED_FOR'] 是有标准定义,用来识别经过HTTP代理后的客户端IP地址, 客户端可以伪造。
$_SERVER['REMOTE_ADDR'] 是可靠的, 它是最后一个跟你的服务器握手的IP,可能是用户的代理服务器,也可能是自己的反向代理。客户端不能伪造。

获取用户真实ip

没有套CDN,用户直连我们的PHP服务器
这种情况下用tcp层握手的ip,$_SERVER['REMOTE_ADDR']
自建集群用nginx实现负载均衡的时候
这种情况下,PHP应用服务器不能对外暴露,我们在nginx中实现获取真实IP再换发给PHP服务器。

1
2
3
location /{
proxy_set_header client-real-ip $remote_addr;
}

client-real-ip 可以随意自己命名,我们将tcp层中跟nginx握手的ip转发给PHP。
使用CDN,从PHP服务器取源的时候
CDN会转发客户端的握手ip过来,各家策略有差异,具体去查CDN的文档。
当然我们也可以把需要严格核查的业务绑一个二级域名,单独走我们自己的nginx服务器,避开CDN。

宽松获取用户ip

种情况比较简单,也是大部分开源程序使用的方式,因为他们要适应最广泛的部署环境,
依次获取和过滤,$_SERVER['HTTP_CLIENT_IP']$_SERVER['HTTP_X_FORWARDED_FOR']的第一个ip,$_SERVER['REMOTE_ADDR'],谁先有值先用谁。注意这种方式,客户端可以提交假ip来欺骗服务器。

PHP如何验证和过滤客户端提交过来的ip#

推荐使用PHP自带的过滤器,http://php.net/manual/zh/function.filter-var.php

$ip = filter_var($originIp, FILTER_VALIDATE_IP)

ip地址库

淘宝:
http://ip.taobao.com/instructions.php

国外:
http://freegeoip.net/json/'.$ip

生命中所有的灿烂 终究要用寂寞来偿还 -百年孤独
### ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000到11111111。 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。 ASCII码一共规定了128个字符的编码,比如空格"SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

bit(二进制位), 有0和1两种状态 byte(字节) 8个二进制位组成了一个字节

非ASCII编码

英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。
但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0–127表示的符号是一样的,不一样的只是128–255的这一段。
至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。
中文编码的问题需要专文讨论,这篇笔记不涉及。这里只指出,虽然都是用多个字节表示一个符号,但是GB类的汉字编码与后文的Unicode和UTF-8是毫无关系的。

Unicode

正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。
可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是Unicode,就像它的名字都表示的,这是一种所有符号的编码。
Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字”严”。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表。

Unicode的问题

需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字”严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。
2)Unicode在很长一段时间内无法推广,直到互联网的出现。

UTF-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

信息补充记忆

  • 小写字母的ASCII值要大于大写字母的ASCII值
  • 无论小写还是大写字母他们的ASCII值都是按照字母顺序从小到大的

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

那时候我总是能起的那么早,看到鸟儿在舞蹈...

使用require_once

文件位于同级目录下
class.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

index.php

1
2
3
4
5
6
7
<?php

require_once 'class.php';

$test = new Test();

echo $test->getName();

使用__autoload

Test.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

index.php

1
2
3
4
5
6
7
8
9
<?php

function __autoload($class_name) {
require_once $class_name . '.php';
}
// 这里要求类名和文件名保持一致,注意大小写;
$test = new Test();

echo $test->getName();

使用spl_autoload_register

第一种方式

Test.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

index.php

1
2
3
4
5
6
7
8
9
<?php

function my_autoload($class_name) {
require_once $class_name . '.php';
}
spl_autoload_register("my_autoload");
$test = new Test();

echo $test->getName();

第二种方式

Test.class.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

index.php

1
2
3
4
5
6
7
8
<?php

spl_autoload_extensions('.class.php');// 寻找扩展名
// 如果我们类的后缀名既有.class.php 还有.php, 可以这样 spl_autoload_extensions('.class.php,.php');
set_include_path(get_include_path().PATH_SEPARATOR."");// 这里的"" 指的是类文件的目录,这里是平级目录
spl_autoload_register();

echo (new Test())->getName();

第三种方式

Test.class.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

index.php

1
2
3
4
5
6
7
8
9
10
11
<?php

function my_autoload($class_name) {
spl_autoload_extensions('.class.php');
set_include_path(get_include_path().PATH_SEPARATOR."");
spl_autoload($class_name);
}

spl_autoload_register('my_autoload');

echo (new Test())->getName();

第四种方式

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php


class Index
{

public static function my_autoload($class_name) {
require_once $class_name . '.php';
}

public static function getLoader()
{
spl_autoload_register(['Index','my_autoload'], true, true);
}
}

Index::getLoader();
echo (new Test())->getName();

Test.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class Test
{
public $name = 'yangzie';

public function getName()
{
return $this->name;
}

}

PSR

PSR是由PHP Framework Interoperability Group(PHP通用性框架小组)发布的一系列标准/规范,目前包括了PSR-0~PSR-4共4个,而PSR-0就是其中的自动加载标准(其后的PSR-4称为改进的自动加载的标准,是PSR-0的补充。PSR-0使用更广泛)
PSR-4风格:

1
2
3
4
-|vendor
--|package
---|src
----|demo.php

如在我们的laravel项目下建立一个与app文件夹同级的目录;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 新建目录accmd, 与app目录同级
acmd\test\yangze\Yang.php

// Yang.php文件内容

<?php
namespace Acmd\Test\Yangzie;

class Yang
{
public function demo()
{
echo 'demo';
}
}

尝试在调用这个类

1
2
3
$yang = new \Acmd\Test\Yangzie\Yang();
$yang->demo();
// error not found

使用composer自动加载

1
2
3
4
5
6
7
8
9
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Acmd\\":"acmd/"
}
},

执行命令: composer dump-autoload 即可

laravel下的自动加载

入口文件public/index.php

1
require __DIR__.'/../bootstrap/autoload.php';

bootstrap/autoload.php

1
require __DIR__.'/../vendor/autoload.php';

vendor/autoload.php

1
2
3
4
5
6
7
<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer' . '/autoload_real.php';

return ComposerAutoloaderInit5205c428ce42c79967c9b7a7be4a7d82::getLoader();

这个文件包含了laravel对classmap,psr-0,psr-4,files的具体实现,主要只有这么一个方法 getLoader;

附录

composer 自动加载文件
文件位置: acmd和app同目录
acmd\test\commom.php
composer.json

1
2
3
4
5
6
7
8
9
10
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Acmd\\":"acmd/"
},
"files":["acmd/test/commom.php"]
},

执行命令: composer dump-autoload

我们自己的项目如何使用

在使用composer安装好相关的依赖包以后, 只要在我们的项目入口文件index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require_once 'vendor/autoload.php';

use Flc\Alidayu\Client;
use Flc\Alidayu\App;
use Flc\Alidayu\Requests\AlibabaAliqinFcSmsNumSend;

$config = [
'app_key' => '*****',
'app_secret' => '*****'
];

$client = new Client(new App($config));
$req = new AlibabaAliqinFcSmsNumSend;

$req->setRecNum('15829465509')
->setSmsParam([
'name' => '杨国奇',
'days' => rand(100000, 999999)
])
->setSmsFreeSignName('叶子坑')
->setSmsTemplateCode('SMS_87315128');

$resp = $client->execute($req);

// 返回结果
print_r($resp);

之后, 我们只要使用合适的命名空间就可以实现自动载入