You are here
Home > PHP

PHP 编程进阶导读(持续更新)

Contents

WEB 编程基础

Web工作方式 1

我们平时浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容。在这个看似简单的用户行为背后,到底隐藏了些什么呢?

对于普通的上网过程,系统其实是这样做的:浏览器本身是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接。

图3.1 用户访问一个Web站点的过程

一个Web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端通常指的是Web浏览器(其实手机端客户端内部也是浏览器实现的)。

Web服务器的工作原理可以简单地归纳为:

客户机通过TCP/IP协议建立到服务器的TCP连接
客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档
服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端
客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果

一个简单的HTTP事务就是这样实现的,看起来很复杂,原理其实是挺简单的。需要注意的是客户机与服务器之间的通信是非持久连接的,也就是当服务器发送了应答后就与客户机断开连接,等待下一次请求。

URL和DNS解析

我们浏览网页都是通过URL访问的,那么URL到底是怎么样的呢?

URL(Uniform Resource Locator)是“统一资源定位符”的英文缩写,用于描述一个网络上的资源, 基本格式如下

scheme://host[:port#]/path/.../[?query-string][#anchor]
scheme         指定低层使用的协议(例如:http, https, ftp)
host           HTTP服务器的IP地址或者域名
port#          HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
path           访问资源的路径
query-string   发送给http服务器的数据
anchor         锚

DNS(Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它从事将主机名或域名转换为实际IP地址的工作。DNS就是这样的一位“翻译官”,它的基本工作原理可用下图来表示。

图3.2 DNS工作原理

更详细的DNS解析的过程如下,这个过程有助于我们理解DNS的工作模式

  1. 在浏览器中输入www.qq.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。

  2. 如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。

  3. 如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。

  4. 如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。

  5. 如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至 “根DNS服务器”,“根DNS服务器”收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。

  6. 如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。

图3.3 DNS解析的整个流程

所谓 递归查询过程 就是 “查询的递交者” 更替, 而 迭代查询过程 则是 “查询的递交者”不变。
举个例子来说,你想知道某个一起上法律课的女孩的电话,并且你偷偷拍了她的照片,回到寝室告诉一个很仗义的哥们儿,这个哥们儿二话没说,拍着胸脯告诉你,甭急,我替你查(此处完成了一次递归查询,即,问询者的角色更替)。然后他拿着照片问了学院大四学长,学长告诉他,这姑娘是xx系的;然后这哥们儿马不停蹄又问了xx系的办公室主任助理同学,助理同学说是xx系yy班的,然后很仗义的哥们儿去xx系yy班的班长那里取到了该女孩儿电话。(此处完成若干次迭代查询,即,问询者角色不变,但反复更替问询对象)最后,他把号码交到了你手里。完成整个查询过程。

通过上面的步骤,我们最后获取的是IP地址,也就是浏览器最后发起请求的时候是基于IP来和服务器做信息交互的。

HTTP协议详解

HTTP协议是Web工作的核心,所以要了解清楚Web的工作方式就需要详细的了解清楚HTTP是怎么样工作的。

HTTP是一种让Web服务器与浏览器(客户端)通过Internet发送与接收数据的协议,它建立在TCP协议之上,一般采用TCP的80端口。它是一个请求、响应协议–客户端发出一个请求,服务器响应这个请求。在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回调连接。客户端与服务器端都可以提前中断一个连接。例如,当浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。

HTTP协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对HTTP服务器来说,它并不知道这两个请求是否来自同一个客户端。为了解决这个问题, Web程序引入了Cookie机制来维护连接的可持续状态。

HTTP协议是建立在TCP协议之上的,因此TCP攻击一样会影响HTTP的通讯,例如比较常见的一些攻击:SYN Flood是当前最流行的DoS(拒绝服务攻击)与DdoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。

HTTP请求包(浏览器信息)

我们先来看看Request包的结构, Request包分为3部分,第一部分叫Request line(请求行), 第二部分叫Request header(请求头),第三部分是body(主体)。header和body之间有个空行,请求包的例子所示:

GET /domains/example/ HTTP/1.1      //请求行: 请求方法 请求URI HTTP协议/协议版本
Host:www.iana.org               //服务端的主机名
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4          //浏览器信息
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  //客户端能接收的mine
Accept-Encoding:gzip,deflate,sdch       //是否支持流压缩
Accept-Charset:UTF-8,*;q=0.5        //客户端字符编码集
//空行,用于分割请求头和消息体
//消息体,请求资源参数,例如POST传递的参数

HTTP协议定义了很多与服务器交互的请求方法,最基本的有4种,分别是GET,POST,PUT,DELETE。一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

通过fiddler抓包可以看到如下请求信息:

图3.4 fiddler抓取的GET信息

图3.5 fiddler抓取的POST信息

我们看看GET和POST的区别:

  1. 我们可以看到GET请求消息体为空,POST请求带有消息体。
  2. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456。POST方法是把提交的数据放在HTTP包的body中。
  3. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
  4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。

HTTP响应包(服务器信息)

我们再来看看HTTP的response包,他的结构如下:

HTTP/1.1 200 OK                     //状态行
Server: nginx/1.0.8                 //服务器使用的WEB软件名及版本
Date:Date: Tue, 30 Oct 2012 04:14:25 GMT        //发送时间
Content-Type: text/html             //服务器发送信息的类型
Transfer-Encoding: chunked          //表示发送HTTP包是分段发的
Connection: keep-alive              //保持连接状态
Content-Length: 90                  //主体内容长度
//空行 用来分割消息头和主体
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... //消息体

Response包中的第一行叫做状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。

状态码用来告诉HTTP客户端,HTTP服务器是否产生了预期的Response。HTTP/1.1协议中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别

  • 1XX 提示信息 – 表示请求已被成功接收,继续处理
  • 2XX 成功 – 表示请求已被成功接收,理解,接受
  • 3XX 重定向 – 要完成请求必须进行更进一步的处理
  • 4XX 客户端错误 – 请求有语法错误或请求无法实现
  • 5XX 服务器端错误 – 服务器未能实现合法的请求

我们看下面这个图展示了详细的返回信息,左边可以看到有很多的资源返回码,200是常用的,表示正常信息,302表示跳转。response header里面展示了详细的信息。

图3.6 访问一次网站的全部请求信息

HTTP协议是无状态的和Connection: keep-alive的区别

无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。

HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(面对无连接)。

从HTTP/1.1起,默认都开启了Keep-Alive保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的TCP连接。

Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同服务器软件(如Apache)中设置这个时间。

请求实例

图3.7 一次请求的request和response

上面这张图我们可以了解到整个的通讯过程,同时细心的读者是否注意到了一点,一个URL请求但是左边栏里面为什么会有那么多的资源请求(这些都是静态文件,go对于静态文件有专门的处理方式)。

这个就是浏览器的一个功能,第一次请求url,服务器端返回的是html页面,然后浏览器开始渲染HTML:当解析到HTML DOM里面的图片连接,css脚本和js脚本的链接,浏览器就会自动发起一个请求静态资源的HTTP请求,获取相对应的静态资源,然后浏览器就会渲染出来,最终将所有资源整合、渲染,完整展现在我们面前的屏幕上。

网页优化方面有一项措施是减少HTTP请求次数,就是把尽量多的css和js资源合并在一起,目的是尽量减少网页请求静态资源的次数,提高网页加载速度,同时减缓服务器的压力。

3.3 Go如何使得Web工作 – Go Web 编程 – 极客学院Wiki

SSL的链接过程 – leaf志良个人页面

http/udp

tcp/ip

会话技术

计算机存储单位

计算机存储单位:bit, Byte, KB, MB, GB, TB, PB, EB, ZB, BB

一、计算机的存储单位有哪些呢?

  计算机存储单位一般用 bit, Byte, KB, MB, GB, TB, PB, EB, ZB, BB来表示,
我们经常将Byte简称为B,将KB简称问K。什么几K了,什么几B了。。

二、他们换算关系是怎样的呢?

   1、计算机存储信息的最小单位:  
位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位。
2、计算机存储容量基本单位是字节
   字节 byte:8个二进制位(bit)为一个字节(B),最常用的单位。 (我也常说一个字节占8位)
一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。
英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节大小。

3、他们的换算关系如下:

 1B(Byte 字节)=8bit,

   1KB (Kilobyte 千字节)=1024B,
   1MB (Megabyte 兆字节 简称“兆”)=1024KB,
   1GB (Gigabyte 吉字节 又称“千兆”)=1024MB,
   1TB (Terabytebyte 万亿字节 太字节)=1024GB,其中1024=2^10 ( 2 的10次方),
   1PB(Petabyte 千万亿字节 拍字节)=1024TB,
   1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
   1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
   1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
   1BB (Brontobyte 一千亿亿亿字节)= 1024 YB.

   注:“兆”为百万级数量单位。
   附:进制单位全称及译音
   yotta, [尧]它, Y. 10^21,
   zetta, [泽]它, Z. 10^18,
   exa, [艾]可萨, E. 10^15,
   peta, [拍]它, P. 10^12,
   tera, [太]拉, T. 10^9,
   giga, [级]咖, G. 10^6,
   mega, [兆],M. 10^3

三、为什么计算机储存单位的进率是1024而不是1000

   因为目前计算机都是二进制的,让它们计算单位,只有2的整数幂时才能非常方便计算机计算,因为电脑内部的电路工作有高电平和低电平两种状态.所以就用二进制来表示信号,(控制信号和数据),以便计算机识别。而人习惯于使用10进制,所以存储器厂商们才用1000作进率。这样导致的后果就是实际容量要比标称容量少,不过这是合法的。1024是2的10次方,因为如果取大了,不接近10的整数次方,不方便人们计算;取小了,进率太低,单位要更多才能满足需求。所以取2的10次方正好。
  计算实例:标称100GB的硬盘,其实际容量为100×1000×1000×1000字节/1024×1024×1024≈93.1GB
  可见产品容量缩水只要满足计算的实际容量结果(上下误差应该在1%内),你买的就是正品,没被骗。

fastcgi与cgi的区别

  • 前言

    现在基本没人使用CGI,不安全、性能极其低下,越来越多的使用web内置扩展(例如微软iis的ISAPI,apache的php模块,nginx的php-cgi)、fastCGI。

    CGI、内置模块、fastcgi这三种性能最好的要属于fast_cgi速度最快,但是需要额外的进程。 解析来看看CGI和FASTCGI有什么不同。

  • CGI方式介绍:

    cgi在2000年或更早的时候用得比较多,以前web服务器一般只处理静态的请求,如果碰到一个动态请求怎么办呢?web服务器会根据这次请求的内容,然后会fork一个新进程来运行外部c程序(或perl脚本…), 这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出。 如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新进程,周而复始的进行。

  • web内置模块介绍:

    后来出现了一种更高级的方式是, web服务器可以内置perl解释器或php解释器。 也就是说这些解释器做成模块的方式,web服务器会在启动的时候就启动这些解释器。 当有新的动态请求进来时,web服务器就是自己解析这些perl或php脚本,省得重新fork一个进程,效率提高了。

  • fastcgi方式介绍:

    fastcgi的方式是,web服务器收到一个请求时,他不会重新fork一个进程(因为这个进程在web服务器启动时就开启了,而且不会退出),web服务器直接把内容传递给这个进程(进程间通信,但fastcgi使用了别的方式,tcp方式通信),这个进程收到请求后进行处理,把结果返回给web服务器,最后自己接着等待下一个请求的到来,而不是退出.

  • fastcgi跟cgi的区别表格:

名称 在web服务器方面 在对数据进行处理的进程方面
cgi fork一个新的进程进行处理 读取参数,处理数据,然后就结束生命期
fastcgi 用tcp方式跟远程机子上的进程或本地进程建立连接 要开启tcp端口,进入循环,等待数据的到来,处理数据

举个例子:

服务端现在有个10万个字单词, 客户每次会发来一个字符串,问以这个字符串为前缀的单词有多少个。 那么可以写一个程序,这个程序会建一棵trie树,然后每次用户请求过来时可以直接到这个trie去查找。 但是如果以cgi的方式的话,这次请求结束后这课trie也就没了,等下次再启动该进程时,又要新建一棵trie树,这样的效率就太低下了。 而用fastcgi的方式的话,这课trie树在进程启动时建立,以后就可以直接在trie树上查询指定的前缀了。

有网友对cgi,mod,fastcgi这三种方式的性能做了一次测试,他们的测试情况请看文章

PHP发送HTTP请求的几种方式

PHP发送HTTP请求的几种方式|cURL库和Guzzle HTTP客户端区别|stream

PHP 开发中我们常用 cURL 方式封装 HTTP 请求,什么是 cURL?

cURL 是一个用来传输数据的工具,支持多种协议,如在 Linux 下用 curl 命令行可以发送各种 HTTP 请求。PHP 的 cURL 是一个底层的库,它能根据不同协议跟各种服务器通讯,HTTP 协议是其中一种。

现代化的 PHP 开发框架中经常会用到一个包,叫做 GuzzleHttp,它是一个 HTTP 客户端,也可以用来发送各种 HTTP 请求,那么它的实现原理是什么,与 cURL 有何不同呢?

Does Guzzle require cURL?

No. Guzzle can use any HTTP handler to send requests. This means that Guzzle can be used with cURL, PHP’s stream wrapper, sockets, and non-blocking libraries like React. You just need to configure an HTTP handler to use a different method of sending requests.

这是 GuzzleHttp 文档 FAQ 中的一个 Question,可见 GuzzleHttp 并不依赖 cURL 库,而支持多种发送 HTTP 请求的方式。

PHP 发送 HTTP 请求的方式

那么这里整理一下除了使用 cURL 外 PHP 发送 HTTP 请求的方式。

  • 1.cURL
$ch = curl_init();

curl_setopt($ch,CURLOPT_URL,"https://blog.tanteng.me/2017/07/php-curl-guzzlehttp/");
curl_setopt($ch,CURLOPT_HEADER,false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

$res = curl_exec($ch);

curl_close($ch);
  • 2.stream流的方式

stream_context_create 作用:创建并返回一个文本数据流并应用各种选项,可用于 fopen(), file_get_contents() 等过程的超时设置、代理服务器、请求方式、头信息设置的特殊过程。

以一个 POST 请求为例:

$data = array("uid" => $userid, "coin" => $stamps, "sign" => $sign, "type" => 'vip_act_chaihongbao');
$data = http_build_query($data);
$opts = array(
    'http' => array(
        'method'  => "POST",
        'header'  => "Content-type: application/x-www-form-urlencoded\r\nContent-length:" . strlen($data) . "\r\n",
        'content' => $data,
    )
);
$context = stream_context_create($opts);
$result = file_get_contents("http://api.example.com/user/addCoin", false, $context);
$result = json_decode($result, true);
if (isset($result['ret']) && $result['ret'] == 0) {
    return true;
}

关于 PHP stream 的介绍文章

  • 3.socket方式

使用套接字建立连接,拼接 HTTP 报文发送数据进行 HTTP 请求。

一个 GET 方式的例子:

<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?>

本文介绍了发送 HTTP 请求的几种不同的方式。

算法

八大排序算法的 PHP 实现 和 效率测试

八大排序算法图解详细 | 言曌博客

梅氏砝码(2014腾讯实习笔试附加题) – leaf志良个人页面

PHP通过读取DOM抓取信息 – leaf志良个人页面

安全

HTTP & HTTPS

$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'?'https':'http';

$protocol = isset($_SERVER["HTTPS"]) ? 'https' : 'http';
 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { //HTTPS } 
下面是利用Curl封装的一个能访问HTTPS内容的函数:

function getHTTPS($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

通过phpmyadmin各种技巧拿webshell – 吕滔博客

利用iptables防止php-ddos对外发包 | LinuxVPS学习者 – CentOS(Linux)VPS教程、环境搭建、基础应用资源站。

环境准备

svn

yum install -y subversion >> ~/svn_install_log.log

mkdir -p /var/svn

svnadmin create /var/svn/lblog

vim  /var/svn/lblog/conf/authz
[groups]
alliance = store,wholesaler, logistics,platform

[lblog:/]
@alliance = rw
vim /var/svn/lblog/conf/passwd

[users]
store = store
wholesaler = wholesaler
logistics = logistics
platform = platform
vim /var/svn/lblog/conf/svnserve.conf

# anon-access = none  //匿名用户访问权限:无
anon-access = read // 改为 anon-access = none

# auth-access = write     //普通用户访问权限:读、写
auth-access = write  // 改为  auth-access = write

# password-db = passwd        //密码文件
password-db = passwd  // 改为  /password-db = passwd

# authz-db = authz        //权限配置文件
authz-db = authz  // 改为  authz-db = authz

# realm = /var/svn/project    //版本库所在1
realm = My First reposity   // 改为  realm = /var/svn/lblog 

killall svnserve
svnserve -d -r /var/svn
svn co svn://10.211.55.19/lblog   --username wholesaler --password wholesaler

vim /root/.subversion/servers

svn add database

svn ci -m 'lblog initialization'

Git

Vagrant

Docker

LINUX 机器上建立 IP 隧道

xdebug

可以提取 phpinfo 获取相应的版本,但实际上这里也可以使用 pecl 来安装

pecl install xdebug

ps: 这里如果安装完成,成功后,会显示 xdebug.so 的位置,记住,后面会用;

然后,修改 php.ini,添加 [Xdebug] 配置组

[Xdebug]
zend_extension="/usr/local/php/modules/xdebug.so"  // 上面 xdebug.so 的位置

PhpStorm Xdebug远程调试环境搭建原理分析及问题排查 | 绿盟科技博客

PhpStorm Xdebug远程调试环境搭建原理分析及问题排查

XDebug安装配置教程 – 歪麦博客

Xdebug: Documentation

PHPunit TDD

安装 PHPunit

前提:先安装 composer

mkdir -p /usr/local/lib/phpunit
cd  /usr/local/lib/phpunit
vim composer.json 

composer.json 的内容大致如下:

 {
         "name": "phpunit",
         "description": "PHPUnit Composer Package",
         "require": {
                 "phpunit/phpunit": "3.7.*"
         },
         "config": {
                 "bin-dir": "/usr/local/bin/"
         }
 }

然后执行 composer 安装

composer install

使用PHPunit 2

  • 最终的目录结构如下:
项目的目录结构如下:

├── phpunit.xml
├── src
│   ├── autoload.php
│   └── Money.php
└── tests
    └── MoneyTest.php
  • 第一个文件是项目代码src/Money.php,内容如下:
<?php

class Money
{
    private $amount;

    public function __construct($amount)
    {
        $this->amount = $amount;
    }

    public function getAmount()
    {
        return $this->amount;
    }

    public function negate()
    {
        return new Money(-1*$this->amount);
    }
}
  • 与之对应的单元测试是tests目录下的MoneyTest.php,注意单元测试文件名最好是*Test.php,这样以后指定tests目录便可以执行目录下的所有测试。
<?php

class MoneyTest extends PHPUnit_Framework_TestCase
{
    public function testCanBeNegated()
    {
        $a = new Money(1);

        $b = $a->negate();

        $this->assertEquals(-1, $b->getAmount());
    }
}

代码很简单,$this->assertEquals(-1, $b->getAmount());即断言后一个参数的执行结果与前一个参数相等,其他不解释了。

现在,如果在MoneyTest.php里加一行include_once(‘../src/Money.php’);。然后在项目根目录下执行phpunit tests/MoneyTest,就可以看到执行结果了。

  • 自动载入

    但是,逐个添加include的方式太不方便,最好是能自动include所需的文件,PHPUnit提供了一个参数–bootstrap,可以使用项目的autoload文件。这里我自己写了一个最简单的autoload.php,只要4行。这个文件并不是PHPUnit专用的,应该放在src目录下。

<?php

function __autoload($class){
    include $class.'.php';
}

spl_autoload_register('__autoload');

当需要Money类时,就去include Money.php。写完__autoload()函数之后要用spl_autoload_register()注册上。

现在就可以去掉MoneyTest.php中的include语句,使用phpunit –bootstrap src/autoload.php tests/MoneyTest来执行测试了。

  • 配置文件phpunit.xml

虽然可以自动载入,但是要执行的命令更长了。我们还可以写一个配置文件来为项目指定bootstrap,这样就不用每次都写在命令里了。

配置文件phpunit.xml放在项目根目录下。

<phpunit bootstrap="src/autoload.php">
</phpunit>

如果要执行MoneyTest,在项目根目录下执行:phpunit tests/MoneyTest
如果要执行tests目录下的所有测试,在项目根目录下执行:phpunit tests

PHP机器学习

PHP机器学习库php-ml的简单测试和使用 – PHP 中文社区

LNMP环境搭建与wordpress的安装 – CSDN博客

禅道

禅道9.8.3版本发布,主要优化细节,修复Bug – 禅道下载 – 禅道开源项目管理软件

http://sourceforge.net/projects/zentao/files/9.8.3/ZenTaoPMS.9.8.3.zip/download

http://dl.cnezsoft.com/zentao/9.8.3/ZenTaoPMS.9.8.3.zip

Windows下 右键电脑属性 左侧高级系统设置 环境变量 编辑底部path变量,光标移动到最后,添加英文分号,把自己php的目录复制到最后即可,在进入msg目录,运行.bat文件

LNMP

IDE

vim

sublime text

在 Sublime 中配置 Markdown 环境 – Blog of 太极儒

Sublime Text 3 + Markdown 配置步骤 – CSDN博客

markdown

前端

HTML5

html5 音/视频

app web ui

跟大家分享一下 | 目前最流行的移动Web前端UI框架

Hello MUI

DCloud – HBuilder、5+、mui、流应用、快应用开发工具、HTML5专家

MUI – DCloud

WeUI

JS

JavaScript监听手机物理返回键 – CSDN博客

JavaScript监听手机上的回退键的事件? – 知乎

点击浏览器或者手机返回按钮,刷新历史页面解决方案

iView介绍 – iView

PHP 原理

PHP MysqlND 简介 – 博学无忧

PHP 5.3.0以上推荐使用mysqlnd驱动 – 老张的自言自语 – ITeye博客

PHP内核了解:生命周期及运行模式 · PHPer进阶 · 看云

PHP底层那点事 – leaf志良个人页面

php运行机制以及底层原理 – 简书

项目

项目 规模 训练目标
二次开发 7 day 对 ec 理解,了解各种开源系统
商城系统 20 day 了解项目开发流程,深度理解电商业务,了解各类常用接口

二次开发

流程 工作内容 训练目标
业务分析 了解目录,剖析运行机制,了解数据字典 掌握 UML CASE CLASS 等工具,了解ER,PRD;学会如何剖析开源系统
模板设计 设计、切分页面;仿站;主题下载 了解前端设计、实现流程(包括如何快速仿站)
了解开发流程 参照文档实现相关功能 了解ec开发流程及相关技巧;深入了解ec运行机制

商城系统

B2C – 标签 – 颜超敏 – 博客园

商城案例 主要模块

模块 子模块
用户 帐号/充值 个人信息 消息/通知 地址 订单 活动 积分 劵 收藏/关注 申请开店
商品 列表 推荐/热销/新品 分类/楼层 商家店铺
搜索 全文检索 缓存
购物车 购物车类 session 持久化 结算/支付
商家 店铺信息 导航管理 分类管理 商品管理 咨询信息 支付方式
管理平台 会员管理 消息/通知 交易查询/管理 店铺 物流管理 财务管理 回访管理 订单管理 类型管理 系统管理 平台信息

商城案例 子级模块

模块 所在父级模块 子级模块
个人信息 用户 注册 登录 退出 修改 安全 好友@
消息/通知 用户 站内消息 通知 好友消息 提醒(好友、纪念日) 好友推荐 推荐返利 拼单 咨询/回复
订单 用户 评论 商品咨询 取消 确认收货 物流状态
活动 用户 积分 劵
订单 商家 合并订单 未支付 已支付 支付记录 订单检索
物流 商家 配送方式 合作伙伴
活动/专题 商家 导航/页面/关联商品/返利/折扣/拆单
店铺 管理平台 商家管理,开户管理(审核,关闭),对帐管理,活动/促销管理,商品管理
物流管理 管理平台 配货管理,出入库管理
财务管理 管理平台 清分管理,报表管理
系统管理 管理平台 日志管理,权限管理(RBAC)
平台信息 管理平台 系统性能/重要参数

sku 货号

B2C电子商务系统研发——商品SKU分析和设计(一) – 颜超敏 – 博客园
B2C电子商务系统研发——商品SKU分析和设计(二) – 颜超敏 – 博客园

isbn 国际标准书号(ISBN) – 阮一峰的网络日志

考试系统

模块 二级模块 三级模块 四级模块 五级模块
业务分析
教研平台 专业 课程体系 知识点 习题库
教师平台 备课
授课
作业
批卷
开班 排课 组卷
学生平台 学生信息
学习
复习
练习
考试
班务

搜索引擎

oop

面向对象 3p 与777 相似但有区别,3p与777组相似,但组不分读写;

也说说几种让程序员快速提高能力的方法 – CSDN博客

  1. 多去敲代码
  2. 拒绝Copy & Paste
  3. 时刻更新知识储备
  4. 少用某度,多用谷歌

设计模式

uml

uml 工具

UML相关工具一览

PHP 常见设计模式

PHP命名空间

可以更好地组织代码,与Java中的包类似。

Test1.php
<?php
namespace Test1;//命名空间Test1
function test(){
    echo __FILE__;
}
Test2.php
<?php
namespace Test2; //命名空间Test2
function test(){
    echo __FILE__;//打印当前文件所在的绝对路径。
}
Test.php
<?php
require 'Test1.php';
require 'Test2.php';
Test1\test();//通过这种方式,使用命名空间下的方法或者类。Test1表示命名空间,test()表示该命名空间下的一个方法。
echo "<br>";
Test2\test();

类自动载入

总结:通过以上代码,可以看到,在不同的命名空间下,可以有相同的类名或者方法名。

随着PHP项目的变大,会导致一个PHP文件的前面有很多的require去包含各种依赖的PHP文件。如果某个类删除,但是在别的文件里有导入的情况,就会导致致命错误。解决以上问题的方法,就是__autoload()函数。

Test1.php
<?php
class Test1{
    static function test(){
        echo __FILE__;
    }
}
Test2.php
<?php
class Test2
{
    static function test(){
        echo __FILE__;
    }
}
Test.php
<?php
Test1::test();
Test2::test();

function __autoload($class){
    $dir  = __DIR__;
    $requireFile = $dir."\\".$class.".php";
    require $requireFile;
}

PHP就是用这段代码,去动态的载入需要包含的文件。当使用某个类,而这个类没有包含到文件中时,就会调用__autoload()函数,去动态的加载这个文件。但是,当使用多个框架时,每个框架都会有自己的__autoload()实现,所以,会导致文件重复导入。

<?php
spl_autoload_register('autoload1');
spl_autoload_register('autoload2');
//将实现自动导入的函数,以字符串的形式传入该函数中,即可解决重复导入文件导致的错误问题。
Test1::test();
Test2::test();

function autoload1($class){
    $dir  = __DIR__;
    $requireFile = $dir."\\".$class.".php";
    require $requireFile;
}
function autoload2($class){
    $dir  = __DIR__;
    $requireFile = $dir."\\".$class.".php";
    require $requireFile;
}

PSR-0/4

  1. PHP的命名空间必须与绝对路径一致。
  2. 类名首字母大写。
  3. 除了入口文件之外,其他的PHP文件必须是一个类,不能有执行的代码。

概要PHP设计模式 3

  • 看懂UML类图和时序图
    1. 从一个示例开始
    2. 类之间的关系
    3. 时序图
    4. 附录
    
  • 创建型模式
    1. 简单工厂模式( Simple Factory Pattern )
    2. 工厂方法模式(Factory Method Pattern)
    3. 抽象工厂模式(Abstract Factory)
    4. 建造者模式
    5. 单例模式
    
  • 结构型模式
    1. 适配器模式
    2. 桥接模式
    3. 装饰模式
    4. 外观模式
    5. 享元模式
    6. 代理模式
    
  • 行为型模式
    1. 命令模式
    2. 中介者模式
    3. 观察者模式
    4. 状态模式
    5. 策略模式
    

简单工厂类

<?php
/**
 *又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根
 *据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例>通常都具有共同的父类。
 */
class Cat 
{
    function __construct($name=''){
        echo 'hi,',$name,"this is a cat\n";
    }   
}


class Dog 
{
    function __construct($name=''){
        echo 'hi,',$name,"this is a dog\n";
    }   
}

class Factory
{
    public static function CreateAnimal($name){
// 用if else实现
//      if('cat'==$name){
//              return new Cat();       
//      }elseif('dog'==$name){
//              return new Dog();       
//      }
// 用可变函数实现
//      $cls = $name;
//      $animal = new $cls();
// 用不带参数反射实现   
//      $cls = new ReflectionClass();
//      $cls->newInstance();
// 用带参数反射实现     
        $cls = new ReflectionClass($name);
        $animal = $cls->newInstanceArgs(['zhangsan']);
    }
}


$cat = Factory::CreateAnimal('cat');
$dog = Factory::CreateAnimal('dog');

PHP单例模式的三私一公

单例模式:即一个类只被实例化一次,当其他人对其再次实例化时,便返回第一次实例化的对象。这种模式可以极大地节约资源。典型应用于数据库类的实例化。
以实例化一个Mysql数据库类为例:
要实现一个类只实例化一次,就必须堵住其他实例化的入口。

  1. $_instance必须声明为静态的私有变量
  2. 构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义
  3. getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用
  4. ::操作符只能访问静态变量和静态函数
  5. new对象都会消耗内存
  6. 使用场景:最常用的地方是数据库连接。
  7. 使用单例模式生成一个对象后, 该对象可以被其它众多对象所使用。
  8. 私有的__clone()方法防止克隆对象

单例模式,使某个类的对象仅允许创建一个。构造函数private修饰,
申明一个static getInstance方法,在该方法里创建该对象的实例。如果该实例已经存在,则不创建。比如只需要创建一个数据库连接。

  • 1.实例化类时,会自动调用类的构造方法,因为将构造方法设置为private属性,限制为只能在类内部实例化
     private function __construct(){

     }  
  • 2.定义一个静态方法,在类内部实例化对象。实例化前先判断该类是否已被实例化了,若已被实例化,就返回该实例化对象;若没被实例化,便实例化一个对象并将该对象保存在类的静态属性中
     private static $self = null;  
     public static function create(){  
      if (self::$self === null) {  
       self::$self = new self();  
      }  
      return self::$self;  
     }  
  • 3.禁止克隆,对象之间进行克隆可生成不同的对象。而克隆时会自动调用类的__conle方法,因此将克隆方法设置为private属性
     private function __clone(){

     }  

综上,三私一公(三个私有属性和一个公共方法)单例模式的代码如下:

    class Mysql {  
     private static $self = null;  
     public static function create(){  
      if (self::$self === null) {  
       self::$self = new self();  
      }  
      return self::$self;  
     }  
     private function __construct(){  
     }  
     private function __clone(){  
     }  
    }  

    $a = Mysql::create();  
    $b = Mysql::create();  
    /*判断两个类是否为同一个类*/  
    echo $a===$b ? 1 : 0;  

单例模式解决的是如何在整个项目中创建唯一对象实例的问题。

设计模式

PHP生成对象之设计模式—单例模式 · PHPer进阶 · 看云
16个PHP设计模式详解 – 简书

设计模式讲解(一) – 实验楼

Resource Reference

并发

- php + redis

[阿里云Redis开发规范](https://mp.weixin.qq.com/s/6M9qNZ0AgC7S6NnGd9qMvg)

socket

  • server 端代码:
//确保在连接客户端时不会超时
set_time_limit(0);

$ip = '10.211.55.19';
$port = 1935;

/*
 +-------------------------------
 *    @socket通信整个过程
 +-------------------------------
 *    @socket_create
 *    @socket_bind
 *    @socket_listen
 *    @socket_accept
 *    @socket_read
 *    @socket_write
 *    @socket_close
 +--------------------------------
 */

/*----------------    以下操作都是手册上的    -------------------*/
if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
    echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";
}

if(($ret = socket_bind($sock,$ip,$port)) < 0) {
    echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";
}

if(($ret = socket_listen($sock,4)) < 0) {
    echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";
}

$count = 0;

do {
    if (($msgsock = socket_accept($sock)) < 0) {
        echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
        break;
    } else {

        //发到客户端
        $msg ="测试成功!\n";
        socket_write($msgsock, $msg, strlen($msg));

        echo "测试成功了啊\n";
        $buf = socket_read($msgsock,8192);


        $talkback = "收到的信息:$buf\n";
        echo $talkback;

        if(++$count >= 5){
            break;
        };


    }
    //echo $buf;
    socket_close($msgsock);

} while (true);

socket_close($sock);
  • client 端代码:
error_reporting(E_ALL);
set_time_limit(0);
echo "<h2>TCP/IP Connection</h2>\n";

$port = 1935;
$ip = "10.211.55.19";

/*
 +-------------------------------
 *    @socket连接整个过程
 +-------------------------------
 *    @socket_create
 *    @socket_connect
 *    @socket_write
 *    @socket_read
 *    @socket_close
 +--------------------------------
 */

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
    echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
}else {
    echo "OK.\n";
}

echo "试图连接 '$ip' 端口 '$port'...\n";
$result = socket_connect($socket, $ip, $port);
if ($result < 0) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
}else {
    echo "连接OK\n";
}

$in = "Ho\r\n";
$in .= "first blood\r\n";
$out = '';

if(!socket_write($socket, $in, strlen($in))) {
    echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";
}else {
    echo "发送到服务器信息成功!\n";
    echo "发送的内容为:<font color='red'>$in</font> <br>";
}

while($out = socket_read($socket, 8192)) {
    echo "接收服务器回传信息成功!\n";
    echo "接受的内容为:",$out;
}


echo "关闭SOCKET...\n";
socket_close($socket);
echo "关闭OK\n";

mvc

框架

Laravel

Packagist / Composer 中国全量镜像

Packagist / Composer 中国全量镜像

Composer 中文文档 | Composer 中文网

Asset Packagist

Call to undefined function openssl_encrypt()
laravel安装时openssl_encrypt() 的问题 :Call to undefined function openssl_decrypt() 打开 php.ini ,把 php_openssl.dll 及extension=php_mcrypt.dll 前面的分号【;】去掉,重启 apache,如果不能解决,从php安装根目录中拷贝 libeay32.dll 和 ssleay32.dll 覆盖掉apache/bin 下的对应文件(注意需要将httpd关闭)最后重启apache即可;如果以上方法还是解决不了,看下apache 2.4的httpd.conf,里面面的LoadModule php5_module D:/php-5.6.25/php5apache2_4.dll 和PHPIniDir “D:/php-5.6.25”是不是对应的版本,且都在5.6以上

[Symfony\Component\Process\Exception\RuntimeException]
The Process class relies on proc_open, which is not available on your PHP installation.

fastcgi_param PHP_ADMIN_VALUE “open_basedir=NULL”;

Angular、React、Vue

[译] 2017 年比较 Angular、React、Vue 三剑客 – 掘金

vue.js

Vue.js最佳实践(五招让你成为Vue.js大师) – 一看就懂一学就会的前端技术 – SegmentFault 思否

symfony 2

业内

区块链

新零售

ai

接口

phpexcel

PHPOffice/PHPExcel: DEPRECATED
PhpSpreadsheet Documentation
PHP操作Excel – 简书
php基础 — PHPExcel的使用总结 | 程序媛

邮件

hightcharts

Medoo – 高效的轻量级PHP数据库框架, 提高开发效率!

接口

存储/云盘

PHP SDK – 七牛开发者中心

金融/支付

支付宝

蚂蚁金服开放平台

开放平台文档中心

沙箱环境

开放平台文档中心

API_API接口平台_API数据【最新】API接口大全_API认证 – 阿里云

目前包含了支付宝pc版、支付宝wap版、palpay、yeepay、unionpay、kuaiqian、财付通tenpay等,这几个常用的支付平台,支付方式均为即时到账,不包含担保支付。

微信支付

【微信支付】APP支付开发者文档

【微信支付】公众号支付开发者文档

物流/快递

常用快递数据接口_免费API接口调用-聚合数据

快递鸟API官网全球物流接口服务商智选物流电子面单轨迹查询

快递查询API介绍-快递查询接口API-快递查询API-爱查快递

运单查询API – 快递100

视频直播平台

文档

phpdocument

数据库

NoSQL

mongodb

SQL

一道面试题

问题描述:两张表 city,province ;分别为城市与省份的关系表。

结构如下:

  • city:
id city province
1 虎山 1
2 东莞 1
3 上海 3
4 珠海市 1
5 汕头市 1
6 韶关市 1
  • province:
id province
1 广东
2 北京
3 上海
  • 问题一:

写一条 sql语句关联两个表,实现:显示城市的基本信息,显示字段(城市id,城市名称,所属省份)

select c.`id`, c.`city`,p.`province` from city c left join province p on c.`p_id`=p.`id`;

统计每个省份有多少个城市,请用 group by 查询出来,显示字段,省份id,省份名,包含多少个城市;

select p.id, p.`province`, count(c.p_id) as city_count 
from `province` p 
left join city c 
on p.id=c.`p_id` 
group by c.`p_id` ;

mysql

mysql主从复制(超简单)-系统网络运维-51CTO博客

MySql 主从复制及配置实现 – Kevin的编程之路 – SegmentFault 思否

基于semisync实现MySQL的主从半同步复制-Free Linux, Share Linux-51CTO博客

更改远程连接的设置

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;

// 使用“flush privileges;”命令刷新刚才修改的权限,使其生效。

flush privileges;

查看修改是否成功。

select host,user from user;

MySQL 忘记密码修改

1.停止MySQL服务
在‘运行’对话框中
输入 net stop mysql

2.进入mysql安全模式
即当mysql起来后,不用输入密码就能进入数据库。使用 --skip-grant-tables启动MySQL服务
注意需要将my.ini中[mysqld]下添加skip-grant-tables,然后保存重启。

3.打开cmd
输入mysql -uroot
无密码登录,登录后可以修改密码。
UPDATE user SET Password=PASSWORD('newpassword') where USER='root' and host='root' or host='localhost';

mysql 下执行 linux 命令

system + 系统shell命令

ps: 如果想查看更多命令,可以使用 \help 或者 \? 查询

sqlite

pgsql

专题

什么是接口?怎么写接口?怎么测试?

开源系统类型

就算是开源项目, 如果不是强可控仍然不能上线

cms

CMS是Content Management System的缩写,意为“内容管理系统”。

  • 国内的内容管理系统
    • DEDECMS

      DEDE -这是一款国内开源的cms,作者是一个个人,能做出如此功能的cms,是相当不错的。2007版功能十分强大,希望能改善之前数据量一大,更新静态页就很慢的缺点。因为开源,有较多的玩家和拥护者。非常适合有一定编程基础的站长。

    • PHPCMS

      phpcms-一个综合的网站管理系统,由PHP+MYSQL构架全站生成html,能够快速高效地应用于LINUX和WINDOWS服务器平台,是目前中国LINUX环境下最佳的网站管理应用解决方案之一。据传被酷6收购。

    • Empire CMS

      帝国网站管理系统-Ecms全称为"帝国网站管理系统",英文译为"Empire CMS"简称"Ecms".Ecms是基于B/S结构,且功能强大而易用的网站管理系统.是一个经过完善设计的适用于Linux/windows/Unix等环境下高效的网站解决方案。官方:http://www.phome.net

    • PHP168

      php168 -PHP168整站系统,代码全部开源,可方便的进行二次开发,功能模块可以自由安装与删除,个人用户免费使用。系统频道模块很多,适合作个人门户网站。较多页面没有生成静态页。如果你想建站,就义无反顾的选择它吧!!!官方:http://www.php168.com

      织梦cms PHPcms 帝国cms比较 – jshaibozhong – 博客园

      帝国、PHPCMS及织梦对比(一):自定义模型功能分析帝国CMS教程西部e网

  • 国外

    1. Joomla!逐浪

    2. Drupal

    3. Plone

    4. 曼波-MAMBO,

    5. WordPress

sns

1:UCenter Home 
2:SpaceBuilder 
3:ThinkSNS 
4:NetSNS 
5:BoonEx(国外的) 
6:openpne 
7:Community Server
8:PHPizabi(小众SNS社区) 
facebook

shop

1. ECSHOP(php+mysql) 
2. ECMall(php+mysql) 
3. Destoon
4. MvMmall
5. [eCommerce Platforms | Best eCommerce Software for Selling Online | Magento](https://magento.com/)
6. OSCOMMERCE SHOPPING CART http://www.oscommerce.com/ 
7. OSCMAX http://www.oscmax.com/ 
8. AGORA CART http://www.agoracart.com/ 

此楼是点评、DIGG、RSS、分类信息、WIKI开源

rss

什么是RSS?

RSS(Really Simple Syndication,简易信息聚合)是一种描述和同步网站内容的格式。 你可以认为是一种定制个性化推送信息的服务。它能解决你漫无目的浏览网页的问题。 它不会过时,信息越是过剩,它的意义也越加彰显。

为什么需要RSS?

网络上充斥着大量的信息垃圾,我的体会是:每天摄入了太多我根本不关心的信息。
我希望让我关注的信息主动来找我 ,且这些信息都是我需要的,这就是RSS的意义。

erp

oa

crm

AJAX 那些事儿

AJAX:Asynchronous JavaScript and XML Ajax的概念由傑西·詹姆士·賈瑞特(Jesse James Garrett4)所提出。

ajax 概念

AJAX的工作原理

Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。

Ajax其核心有JavaScript、XMLHTTPRequest、DOM对象组成,通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。让我们来了解这几个对象。

XMLHTTPRequest对象

Ajax的一个最大的特点是无需刷新页面便可向服务器传输或读写数据(又称无刷新更新页面),这一特点主要得益于XMLHTTP组件XMLHTTPRequest对象。

  • XMLHttpRequest 对象方法描述
方 法 描 述
abort() 停止当前请求
getAllResponseHeaders() 把HTTP请求的所有响应首部作为键/值对返回
getResponseHeader(“header”) 返回指定首部的串值
open(“method”,”URL”,[asyncFlag],[“userName”],[“password”]) 建立对服务器的调用。method参数可以是GET、
POST或PUT。url参数可以是相对URL或绝对URL。
这个方法还包括3个可选的参数,是否异步,
用户名,密码
send(content) 向服务器发送请求
setRequestHeader(“header”, “value”) 把指定首部设置为所提供的值。在设置任何首部之前必须先
调用open()。设置header并和请求一起发送 (‘post’方法一定要 )
  • XMLHttpRequest 对象属性描述
属 性 描 述
onreadystatechange 状态改变的事件触发器,每个状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数
readyState 请求的状态。有5个可取值:0 = 未初始化,1 = 正在加载,2 = 已加载,3 = 交互中,4 = 完成
responseText 服务器的响应,返回数据的文本。
responseXML 服务器的响应,返回数据的兼容DOM的XML文档对象 ,这个对象可以解析为一个DOM对象。
responseBody 服务器返回的主题(非文本格式)
responseStream 服务器返回的数据流
status 服务器的HTTP状态码(如:404 = “文件末找到” 、200 =”成功” ,等等)
statusText 服务器返回的状态文本信息 ,HTTP状态码的相应文本(OK或Not Found(未找到)等等)

JavaScript

JavaScript是一在浏览器中大量使用的编程语言。

DOM Document Object Model

DOM是给HTML和XML文件使用的一组API。它提供了文件的结构表述,让你可以改变其中的內容及可见物。其本质是建立网页与Script或程序语言沟通的桥梁。所有WEB开发人员可操作及建立文件的属性、方法及事件都以对象来展现(例如,document就代表“文件本身“这个对像,table对象则代表HTML的表格对象等等)。这些对象可以由当今大多数的浏览器以Script来取用。一个用HTML或XHTML构建的网页也可以看作是一组结构化的数据,这些数据被封在DOM(Document Object Model)中,DOM提供了网页中各个对象的读写的支持。

XML

可扩展的标记语言(Extensible Markup Language)具有一种开放的、可扩展的、可自描述的语言结构,它已经成为网上数据和文档传输的标准,用于其他应用程序交换数据 。

综合

Ajax引擎,实际上是一个比较复杂的JavaScript应用程序,用来处理用户请求,读写服务器和更改DOM内容。JavaScript的Ajax引擎读取信息,并且互动地重写DOM,这使网页能无缝化重构,也就是在页面已经下载完毕后改变页面内容,这是我们一直在通过JavaScript和DOM在广泛使用的方法,但要使网页真正动态起来,不仅要内部的互动,还需要从外部获取数据,在以前,我们是让用户来输入数据并通过DOM来改变网页内容的,但现在,XMLHTTPRequest,可以让我们在不重载页面的情况下读写服务器上的数据,使用户的输入达到最少。

Ajax使WEB中的界面与应用分离(也可以说是数据与呈现分离),而在以前两者是没有清晰的界限的,数据与呈现分离的分离,有利于分工合作、减少非技术人员对页面的修改造成的WEB应用程序错误、提高效率、也更加适用于现在的发布系统。也可以把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理。

jQuery ajax 五种形式

jQuery ajax 完整形式

阿虎买凉皮的故事 (一)

  • 参数意义

– 返回形式

  • $(“form”).serialize()
  • jQuery.parseJSON()方法

with()
$.each()

同步 异步 阻塞 非阻塞

阿虎买凉皮的故事 (二)

返回值调用

拿到返回值

莫名的跳转

全局变量借值

跨域请求 JSONP

AJAX的优缺点

AJAX的优点

  1. 无刷新更新数据。
  2. 异步与服务器通信。
  3. 前端和后端负载平衡。
  4. 基于标准被广泛支持。
  5. 界面与应用分离。

AJAX的缺点

  1. AJAX干掉了Back和History功能,即对浏览器机制的破坏。
  2. AJAX的安全问题。
  3. 对搜索引擎支持较弱。
  4. 破坏程序的异常处理机制。
  5. 违背URL和资源定位的初衷。
  6. AJAX不能很好支持移动设备。
  7. 客户端过肥,太多客户端代码造成开发上的成本。

AJAX注意点及适用和不适用场景

注意点

Ajax开发时,网络延迟——即用户发出请求到服务器发出响应之间的间隔——需要慎重考虑。不给予用户明确的回应,没有恰当的预读数据,或者对XMLHttpRequest的不恰当处理,都会使用户感到延迟,这是用户不希望看到的,也是他们无法理解的。通常的解决方案是,使用一个可视化的组件来告诉用户系统正在进行后台操作并且正在读取数据和内容。

Ajax适用场景

  1. 表单驱动的交互
  2. 深层次的树的导航
  3. 快速的用户与用户间的交流响应
  4. 类似投票、yes/no等无关痛痒的场景
  5. 对数据进行过滤和操纵相关数据的场景
  6. 普通的文本输入提示和自动完成的场景

Ajax不适用场景

  1. 部分简单的表单
  2. 搜索
  3. 基本的导航
  4. 替换大量的文本
  5. 对呈现的操纵

http 状态

http 状态码

PHP 发送 HTTP 报文头(header)

布局

10个值得深思的PHP面试问题

秒杀

URL/URI/URN

URI:Uniform Resource Identifier,统一资源标识符;
URL:Uniform Resource Locator,统一资源定位符;
URN:Uniform Resource Name,统一资源名称。

  • URL的格式由下列三部分组成:
    协议(或称为服务方式);

    存有该资源的主机IP地址(有时也包括端口号);

    主机资源的具体地址。如目录和文件名等。
  • URI是以某种统一的(标准化的)方式标识资源的简单字符串,一般由三部分组成:
    访问资源的命名机制。
    存放资源的主机名。
    资源自身的名称,由路径表示。

URL和URN都是URI

我们一起来看下面这个虚构的例子。这是一个URI:

http://bitpoetry.io/posts/hello.html#intro

我们开始分析

http://

scheme 是定义如何访问资源的方式。另外

bitpoetry.io/posts/hello.html

是资源存放的位置,那么,在这个例子中,

#intro

是资源。

URL是URI的一个子集,告诉我们访问网络位置的方式。在我们的例子中,URL应该如下所示:

http://bitpoetry.io/posts/hello.html

URN是URI的子集,包括名字(给定的命名空间内),但是不包括访问方式,如下所示:

bitpoetry.io/posts/hello.html#intro

就是这样。现在你应该能够辨别出URL和URN之间的不同。

zip

IM xmpp协议详解一:xmpp基本概念 – 简书

seo

主题

多语言

rbac

使用PHP生成二维码的两种方法(带logo图像) php实例_脚本之家

PHP实现发送与接收流文件(StreamFile)的方法 – 为程序员服务

SESSION

对 PHP SESSION 的深刻认识(一) – CSDN博客

对 PHP SESSION 的深刻认识(二) – CSDN博客

对 PHP SESSION 的深刻认识(三)—- 数据库存储session – CSDN博客

最佳编码践

正则

[php中正则表达式详解 - helloworldlee - 博客园](https://www.cnblogs.com/hellohell/p/5718319.html)

[身份证号码的正则表达式及验证详解(JavaScript,Regex)](https://mp.weixin.qq.com/s/0-5vPRnb5_-O3uiAovxsrQ)

理解OAuth 2.0 – 阮一峰的网络日志

知识体系结构

强制下载

$file_name = 'myfile.txt';
header ( 'Content-Description: File Transfer' );
header ( 'Content-Type: application/octet-stream' );
header ( 'Content-Disposition: attachment; filename=' . basename($file_name) );  #可自定义文件名
header ( 'Content-Transfer-Encoding: binary' );
header ( 'Expires: 0' );
header ( 'Cache-Control: must-revalidate' );
header ( 'Pragma: public' );
header ( 'Content-Length: '  .  filesize ( $file_name )); 
ob_clean (); 
flush (); 
readfile ( $file_name ); exit;

OSI和TCP/IP模型

VPN

业务类型/领域

PHPCMS、织梦DEDECMS、帝国CMS的选择与比较 HTML5+CSS3, wordpress, 网站制作, 网站建设, 网站设计 厦门网站建设

三大主流CMS的优缺点_百度文库

帝国、PHPCMS及织梦三款CMS比较 – CSDN博客

special reference

服务器

不要一直使用 root 帐户

一般用户 home 目录与 root home 目录有区别

linux 基本原则:

  • Linux严格区分大小写
  • 由目的单元的小程序组成;组合小程序完成复杂任务
  • 一切皆文件
  • 尽量避免捕获用户接口
  • 配置文件保存为纯文本格式

linux 操作接口

GUI接口:可视化操作

Gnome:C语音开发

KDE:C++语音开发

XFace:简洁的适合用于嵌入式系统的桌面

CLI接口:

命令提示符,prompt,bash(shell)

    #:root(超级用户)

    $:普通用户

命令:

    命令格式:

        命令  选项  参数

                选项:

                    短选项:-

                        多个选项可以组合: -a -b = -ab

                    长选项:--

                参数:命令的作用对象

Linux 中用户切换:

su: switch user

$ su [-l] 用户名  切换用户 su 命令 -l 选项[]选填 用户名 要切换的用户名

$ exit 命令

$ passwd 修改当前登录者的密码
  • 删除目录下所有exe文件
find . -name ‘*.exe’ -type f -print -exec rm -rf {} ;

linux命令看文件或文件夹个数

ls -l|grep "^-"| wc -l     查看某个文件夹下文件的个数。
ls -lR|grep "^-"| wc -l    查看某个文件夹下文件的个数,包括子文件夹下的文件个数。
ls -l|grep "^d"| wc -l     查看某个文件夹下文件夹的个数。
ls -lR|grep "^d"| wc -l    查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。
ls -l| wc -l               查看文件夹下所有的文件和文件夹。也就是统计ls -l命令所输出的行数。

lsof

sudo lsof -i :端口号

shell

月薪上万才会考的 24 道Linux Shell 脚本面试题

配置

php.ini 中文英文对照详细配置手册-php程序员的笔记

Redis 配置文件 redis.conf 中文对照 – CSDN博客

Nginx 配置文件nginx.conf中文详解_w3cschool

Apache配置文件httpd.conf 中文版详解/以Apache2为例讲解 | 点滴之间 聚沙成金

Apache配置httpd.conf参数中文版(很实用的文章) -我的技术梦想之路-51CTO博客

Apache配置中文域名 – 亚原子技术博客

Apache中文乱码解决办法 | 运维之美

Apache HTTP 服务器 2.4 文档 – Apache HTTP 服务器 版本 2.4

linux resource

微信

公众号

简易教程 · 小程序

入门示例:

小程序与后台数据沟通

.//Downloads/PHP/libaotong.cn/public/wx_sample.php

沙箱测试号1,开发者工具2,技术文档3,公众号申请入口4

软件开发过程

面试

面试申请表

面试评估表

PHP 面试知识梳理

面试中常见问题——非技术

PHP 经典面试题集

最全最详细的PHP面试题(带有答案) 百度文库

php面试题汇总四(基础篇附答案) – 唐世光 – 博客园

2017最新PHP经典面试题目汇总(上篇) – 赵公子 – 博客园

2017php经典面试题 – 一步踏尽一树白 – 博客园

公司承接的一个全品类的电子商务网站(B2C)业务,包括:

        分类管理,商品管理,会员管理,购物车,结算(支持在线支付,COD[^interview_01]等多种支付方式),
        在线客服(即时通讯workman),评论管理(商品评论,打分),活动管理,秒杀(可伸缩性,实时性要求)
        等功能,并采用日志记录用户操作、监控应用性能,主要开发语言为PHP,使用workman,SMS API , Ajax , CURL , Restful等技术。

        公司承接的一个全品类的电子商务网站(B2C)业务,包括
        分类管理,商品管理,会员管理,购物车,结算(支持在线支付,COD等多种支付方式),
        在线客服(即时通讯workman),评论管理(商品评论,打分),活动管理,秒杀(可伸缩性,实时性要求)等功能,
        分层日志(服务层监控Apache、PHP、Nginx,应用层监控性能、用户操作、异常,服务器监控网管、节点、网络设置,系统监控IO、网络异常),
        采用PHP语言进行开发,使用workman,SMS API , Ajax , CURL , Restful等技术。

        公司承接的一个全品类的电子商务网站(B2C)业务,包括分类管理,商品管
        理,会员管理,购物车,结算,在线客服,评论管理,活动管理,秒杀等功能,使用
        集群对应用服务器进行冗余,实现高可用;通过业务拆分,应用集群部署(分布式部
        署,集群部署和负载均衡),多级缓存,单点登录(分布式Session),数据库集群(读
        写分离,分库分表),服务化,消息队列以及CDN,反向代理,分布式文件系统,大数据
        处理实现架构优化。

        项目描述:借鉴与分布式大型网站架构,基于客户要求:能够支持3~5年业务发展的全品类电子商务网站(B2C),
        划分需求功能矩阵进行需求分析,采用集群的方式,进行高可用设计,使用应用集群,多级缓存,单点登录,
        消息队列外、CDN,反向代理等技术实现用户在线购买、在线支付或COD(货到付款)、在线客服、商品评论、
        对接进销存、秒杀等核心功能需求。

实现难点:
1、根据分布式Session进行会话管理;
2、海量的数据进行读写分离;
3、使用消息队列解决子系统/模块之间的耦合;
4、URI拦截、唯一token,防止用户重复请求;

库存、支付、拆分订单、退款、费用核算
ISBN编码
QR生成二维码、条形码
workman
导出是为了对账和备份,导入是为了方便添加商品
SMS短信验证(6分/条)
验证码问题
项目描述

禅道、前任、需求变更、
bug 200-300/月(300个左右)
5种类型

行为日志
登录日志


http状态

名角

图书推荐

PHP 之道 | PHP The Right Way 中文版

图解http 上野宣

数据备份与恢复

调试

Parse error: syntax error, unexpected end of file 意外的文件结尾,遇到这种情况一般是?>多了或少了,或者是多了,少了某个符号,比如 class { }结构后面的这个花括号

[Symfony\Component\Debug\Exception\FatalThrowableError]
Parse error: syntax error, unexpected end of file

syntax error, unexpected ‘

性能优化

mysql

  • 写在前面的话:6

总是在灾难发生后,才想起容灾的重要性

  • 概述

其实数据库优化有很多种方式,不过只有在具体的场景中才会发挥它的最大价值,这是我对前人的优化做的一些总结,希望对你有帮助,以下优化针对mysql

设计原则

  1. 不在数据库做运算:cpu计算务必移至业务层


  2. 控制单表数据量:单表记录控制在1000w


  3. 控制列数量:字段数控制在20以内


  4. 平衡范式与冗余:为提高效率牺牲范式设计,冗余数据


  5. 拒绝3B:拒绝大sql,大事务,大批量


  6. 表字符集使用UTF8


  7. 使用INNODB存储引擎

数据表设计

  1. 尽可能地使用最有效(最小)的数据类型

    tinyint(1Byte)
    
    smallint(2Byte)
    
    mediumint(3Byte)
    
    int(4Byte)
    
    bigint(8Byte)
    
    bad case:int(1)/int(11)
    
  2. 不要将数字存储为字符串,字符转化为数字,用int存储ip而非char(15)


  3. 优先使用enum或set,sex enum (‘F’, ‘M’)
4,避免使用NULL字段

    NULL字段很难查询优化
    
    NULL字段的索引需要额外空间
    
    NULL字段的复合索引无效
    
    bad case:`name` char(32) default null`age` int not null
    
    good case:`age` int not null default 0
    
  4. 少用text/blob,varchar的性能会比text高很多;实在避免不了blob,请拆表

  5. 不在数据库里存图片

  6. 对于MyISAM表,如果没有任何变长列(VARCHAR、TEXT或BLOB列),使用固定尺寸的记录格式。这比较快但是不幸地可能会浪费一些空间。即使你已经用CREATE选项让VARCHAR列ROW_FORMAT=fixed,也可以提示想使用固定长度的行

  7. 使用sample character set,例如latin1。尽量少使用utf-8,因为utf-8占用的空间是latin1的3倍。可以在不需要使用utf-8的字段上面使用latin1,例如mail,url等

  8. 精确度与空间的转换。在存储相同数值范围的数据时,浮点数类型通常都会比DECIMAL类型使用更少的空间。FLOAT字段使用4 字节存储 数据。DOUBLE类型需要8 个字节并拥有更高的精确度和更大的数值范围,DECIMAL类型的数据将会转换成DOUBLE类型

  9. 库名表名字段名必须有固定的命名长度,12个字符以内;库名、表名、字段名禁⽌止超过32个字符。须见名之意;库名、表名、字段名禁⽌止使⽤用MySQL保留字;临时库、表名必须以tmp为前缀,并以⽇日期为后缀; 备份库、表必须以bak为前缀,并以日期为后缀

  10. InnoDB表行记录物理长度不超过8KB,InnoDB的data page默认是16KB,基于B+Tree的特点,一个data page中需要至少存储2条记录。因此,当实际存储长度超过8KB(尤其是TEXT/BLOB列)的大列(large column)时会引起“page-overflow存储”,类似ORACLE中的“行迁移”,因此,如果必须使用大列(尤其是TEXT/BLOB类型)且读写频繁的话,则最好把这些列拆分到子表中,不要和主表放在一起存储,如果不太频繁,可以考虑继续保留在主表中,如果将 innodbpagesize 选项修改成 8KB,那么行记录物理长度建议不超过4KB

索引类

  1. 谨慎合理使用索引

    改善查询、减慢更新
    索引一定不是越多越好(能不加就不加,要加的一定得加)
    覆盖记录条数过多不适合建索引,例如“性别”
    
  2. 字符字段必须建前缀索引

  3. 不在索引做列运算,bad case:select id where age +1 = 10;

  4. innodb主键推荐使用自增列

    主键建立聚簇索引
    主键不应该被修改
    字符串不应该做主键
    如果不指定主键,innodb会使用唯一且非空值索引代替
    
  5. 不用外键,请由程序保证约束

  6. 避免在已有索引的前缀上建立索引。例如:如果存在index(a,b)则去掉index(a)

  7. 控制单个索引的长度。使用key(name(8))在数据的前面几个字符建立索引

  8. 要选择性的使用索引。在变化很少的列上使用索引并不是很好,例如性别列

  9. Optimize table可以压缩和排序index,注意不要频繁运行

  10. Analyze table可以更新数据

  11. 索引选择性是不重复的索引值也叫基数(cardinality)表中数据行数的比值,索引选择性=基数/数据行,count(distinct(username))/count(*) 就是索引选择性,高索引选择性的好处就是mysql查找匹配的时候可以过滤更多的行,唯一索引的选择性最佳,值为1

  12. 不要用重复或多余索引,对于INNODB引擎的索引来说,每次修改数据都要把主键索引,辅助索引中相应索引值修改,这可能会出现大量数 据迁移,分页,以及碎片的出现

  13. 超过20个长度的字符串列,最好创建前缀索引而非整列索引(例如:ALTER TABLE t1 ADD INDEX(user(20))),可以有效提高索引利用率,不过它的缺点是对这个列排序时用不到前缀索引。前缀索引的长度可以基于对该字段的统计得出, 一般略大于平均长度一点就可以了

  14. 定期用 pt-duplicate-key-checker 工具检查并删除重复的索引。比如 index idx1(a, b) 索引已经涵盖了 index idx2(a),就可以删除 idx2 索引了

sql语句设计类

  1. sql语句尽可能简单,一条sql只能在一个cpu运算,大语句拆小语句,减少锁时间,一条大sql可以堵死整个库(充分利用QUERY CACHE7和充分利用多核CPU)

  2. 简单的事务,事务时间尽可能短,bad case:上传图片事务

  3. 避免使用trig/func,触发器、函数不用,客户端程序取而代之

  4. 不用select *,消耗cpu,io,内存,带宽,这种程序不具有扩展性

  5. OR改写为IN()

    or的效率是n级别
    in的消息时log(n)级别
    in的个数建议控制在200以内
    select id from t where phone=’159′ or phone=’136′ =>select id from t where phone in (’159′, ’136′);
    
  6. OR改写为UNION
    mysql的索引合并很弱智
    select id from t where phone = '159' or name = 'john';
    =>
    select id from t where phone='159' union  select id from t where name='jonh';
    
  7. 避免负向%,如not in/like

  8. 慎用count(*)

  9. limit高效分页

    limit越大,效率越低
    select id from t limit 10000, 10;
    =>
    select id from t where id > 10000 limit 10;
    
  10. 使用union all替代union,union有去重开销

  11. 少用连接join

  12. 使用group by,分组、自动排序

  13. 请使用同类型比较

  14. 使用load data导数据,load data比insert快约20倍

  15. 对数据的更新要打散后批量更新,不要一次更新太多数据

  16. 使用性能分析工具

    Sql explain / showprofile / mysqlsla
    
  17. 使用–log-slow-queries –long-query-time=2查看查询比较慢的语句。然后使用explain分析查询,做出优化
    show profile;
    mysqlsla;
    mysqldumpslow;
    explain;
    show slow log;
    show processlist;
    show query_response_time(percona)
    
    optimize 数据在插入,更新,删除的时候难免一些数据迁移,
    分页,之后就出现一些碎片,久而久之碎片积累起来影响性能, 这就需要DBA定期的优化数据库减少碎片,这就通过optimize命令。
    如对MyISAM表操作:optimize table 表名
    
  18. 禁止在数据库中跑大查询

  19. 使⽤预编译语句,只传参数,比传递SQL语句更高效;一次解析,多次使用;降低SQL注入概率

  20. 禁止使⽤order by rand()

  21. 禁⽌单条SQL语句同时更新多个表

  22. 避免在数据库中进⾏数学运算(MySQL不擅长数学运算和逻辑判断)

  23. SQL语句要求所有研发,SQL关键字全部是大写,每个词只允许有一个空格

  24. 能不用NOT IN就不用NOTIN,坑太多了。。会把空和NULL给查出来

预编译语句

mysql 预编译语句:

mysql>  CREATE TABLE `t` (
     >   `a` int(11) DEFAULT NULL,
     >   `b` varchar(20) DEFAULT NULL,
     >   UNIQUE KEY `ab` (`a`,`b`)
     > ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> prepare ins from 'insert into t select ?,?';


mysql> set @a=999,@b='hello';

mysql> execute ins using @a,@b;

php mysql 预编译语句:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // 设置 PDO 错误模式为异常
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 预处理 SQL 并绑定参数
    $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) 
    VALUES (:firstname, :lastname, :email)");
    $stmt->bindParam(':firstname', $firstname);
    $stmt->bindParam(':lastname', $lastname);
    $stmt->bindParam(':email', $email);

    // 插入行
    $firstname = "John";
    $lastname = "Doe";
    $email = "john@example.com";
    $stmt->execute();

    // 插入其他行
    $firstname = "Mary";
    $lastname = "Moe";
    $email = "mary@example.com";
    $stmt->execute();

    // 插入其他行
    $firstname = "Julie";
    $lastname = "Dooley";
    $email = "julie@example.com";
    $stmt->execute();

    echo "新记录插入成功";
}
catch(PDOException $e)
{
    echo "Error: " . $e->getMessage();
}
$conn = null;
mysql> CREATE TABLE `tb` (
    -> `id` int(10) unsigned NOT NULL auto_increment PRIMARY KEY,
    -> `name` varchar(20) NOT NULL,
    -> `age` tinyint(4)  NOT NULL
    -> ) ENGINE=InnoDB  auto_increment=0  DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE prod FROM "INSERT INTO tb VALUES(?,?,?)";
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> PREPARE prod FROM "INSERT INTO tb(name,age) VALUES(?,?)";
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> set @p='tejevo';
Query OK, 0 rows affected (0.00 sec)

mysql>  set @q=20;
Query OK, 0 rows affected (0.00 sec)

mysql> execute prod using @p, @q;
Query OK, 1 row affected (0.00 sec)

留一个思考题吧,性能状态关键指标该怎么计算?

QPS,Queries Per Second:每秒查询数,一台数据库每秒能够处理的查询次数
TPS,Transactions Per Second:每秒处理事务数

注意

  1. 哪怕是基于索引的条件过滤,如果优化器意识到总共需要扫描的数据量超过30%时(ORACLE里貌似是20%,MySQL目前是30%,没准以后会调整),就会直接改变执行计划为全表扫描,不再使用索引

  2. 多表JOIN时,要把过滤性最大(不一定是数据量最小哦,而是只加了WHERE条件后过滤性最大的那个)的表选为驱动表。此外,如果JOIN之后有排序,排序字段一定要属于驱动表,才能利用驱动表上的索引完成排序

  3. 绝大多数情况下,排序的代价通常要来的更高,因此如果看到执行计划中有 Using filesort,优先创建排序索引吧

  4. 利用 pt-query-digest 定期分析slow query log,并结合 Box Anemometer 构建slow query log分析及优化系统

综结

优化大致可以分为以下方面,按照执行难易程度和对当前项目影响排序:

  1. MySQL参数优化:可以通过show variables;命令和show status;命令组合来综合分析,可调整的项目根据使用的存储引擎和项目瓶颈具体情况千差万别,需要具体问题具体分析,如果想从这方面入手,建议把问题提得更具体一点;

  2. SQL查询优化和索引优化:你可以打开慢日志记录,将需要消耗太多时间的查询记录下来,然后分析相应的SQL语句是否写的不合理,不合理就改了;再到数据库中查表结构,看是否索引设置不合理(一般where语句中的常用字段和排序字段应该加上合适的索引);

  3. 增加缓存层:可考虑在MySQL与应用层中间加一个缓存层,如APC、Memcached、Redis等等,将经常使用而更新较少的数据放到缓存层中,可以很好的减轻数据库压力;

  4. 优化表结构:首先这个代价稍大,可能要重新灌数据之类的,代码修改可能也会比较多,看之前的封装性好不好了。主要是根据业务需要,看是否之前的表结构有不合理的地方,比如你使用了很多但是又无法排除的join查询;

  5. 分库、分表、主从分离:分库是把数据库从1个逻辑库拆分到多个逻辑库,或从1个服务器拆分到多个服务器,分表是将一个表拆分为多个表,甚至是多个物理服务器的不同表;主从分离是将读、写完全分离到不同的数据库服务器;这个方案跟4一样,也是代价比较大,但是可持续性很好,项目到达一定的数量级,必须走这一步;

  6. 自己定制MySQL:开源的,可以根据自己特殊业务需要定制,太高端了点点,总之有这种可能,没搞过…

工具专题:explain

  • 一,为什么要开启这个查询呢?

数据库是很容易产生瓶颈的地方,现在Nosql大家讨论这么热,估计都被数据库搞郁闷了。mysql中最影响速度的就是那些查询非常慢的语句,这些慢的语句,可能是写的不够合理或者是大数据下多表的联合查询等等,所以我们要找出这些语句,分析原因,加以优化。这也是发这篇博文的原因

  • 二,开启mysql的慢查询
    • 方法1,用命令开启慢查询
      mysql> show variables like "%long%";         //查看一下默认为慢查询的时间10秒
      +-----------------+-----------+
      | Variable_name   | Value     |
      +-----------------+-----------+
      | long_query_time | 10.000000 |
      +-----------------+-----------+
      1 row in set (0.00 sec)
      
      mysql> set global long_query_time=2;          //设置成2秒,加上global,下次进mysql已然生效
      Query OK, 0 rows affected (0.00 sec)
      
      mysql> show variables like "%slow%";          //查看一下慢查询是不是已经开启
      +---------------------+---------------------------------+
      | Variable_name       | Value                           |
      +---------------------+---------------------------------+
      | log_slow_queries    | OFF                             |
      | slow_launch_time    | 2                               |
      | slow_query_log      | OFF                             |
      | slow_query_log_file | /usr/local/mysql/mysql-slow.log |
      +---------------------+---------------------------------+
      4 rows in set (0.00 sec)
      
      mysql> set slow_query_log='ON';                        //加上global,不然会报错的。
      ERROR 1229 (HY000): Variable 'slow_query_log' is a GLOBAL variable and should be set with SET GLOBAL
      mysql> set global slow_query_log='ON';            //启用慢查询
      Query OK, 0 rows affected (0.28 sec)
      
      mysql> show variables like "%slow%";              //查看是否已经开启
      +---------------------+---------------------------------+
      | Variable_name       | Value                           |
      +---------------------+---------------------------------+
      | log_slow_queries    | ON                              |
      | slow_launch_time    | 2                               |
      | slow_query_log      | ON                              |
      | slow_query_log_file | /usr/local/mysql/mysql-slow.log |
      +---------------------+---------------------------------+
      4 rows in set (0.00 sec)
      
    • 方法2,修改mysql的配置文件my.cnf

      在[mysqld]里面加上以下内容

      long_query_time = 2  
      log-slow-queries = /usr/local/mysql/mysql-slow.log  
      

      重起一下
      /usr/local/mysql/libexec/mysqld restart

  • 分析工具

    分析工具干什么事的呢,其实就是把mysql-slow.log里面记录下来的数据,分析一下显示出来。其实自己写一个shell脚本也是可以把要的信息取出来的。我们来看一下mysql-slow.log里面到底是什么东西

    [root@BlackGhost mysql]# cat mysql-slow.log     //查看命令
    /usr/local/mysql/libexec/mysqld, Version: 5.1.26-rc-log (Source distribution). started with:
    Tcp port: 3306  Unix socket: /tmp/mysql.sock
    Time                 Id Command    Argument
    # Time: 100814 13:28:30
    # User@Host: root[root] @ localhost []
    # Query_time: 10.096500  Lock_time: 0.045791 Rows_sent: 1  Rows_examined: 2374192
    SET timestamp=1281763710;
    select count(distinct ad_code) as x from ad_visit_history where ad_code in (select ad_code from ad_list where media_id=15);
    # Time: 100814 13:37:02
    # User@Host: root[root] @ localhost []
    # Query_time: 10.394134  Lock_time: 0.000091 Rows_sent: 1  Rows_examined: 2374192
    SET timestamp=1281764222;
    select count(distinct ad_code) as x from ad_visit_history where ad_code in (select ad_code from ad_list where media_id=15);
    # Time: 100814 13:37:16
    # User@Host: root[root] @ localhost []
    # Query_time: 4.608920  Lock_time: 0.000078 Rows_sent: 1  Rows_examined: 1260544
    SET timestamp=1281764236;
    select count(*) as cou  from ad_visit_history where ad_code in (select ad_code from ad_list where id=41) order by id desc;
    

    看到了,就是记录一下sql语句的执行情况,包括执行时间,锁定时间等,所以要不要分析工具看个人情况,分析工具很多,在这儿只说一下mysql自带的慢查询分析工具mysqldumpslow的使用方法。

    [root@BlackGhost bin]# mysqldumpslow -h
    Option h requires an argument
    ERROR: bad option
    
    Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
    
    Parse and summarize the MySQL slow query log. Options are
    
     --verbose    verbose
     --debug      debug
     --help       write this text to standard output
    
     -v           verbose
     -d           debug          //查错
     -s ORDER     what to sort by (t, at, l, al, r, ar etc), 'at' is default     //排序方式query次数,时间,lock的时间和返回的记录数来排序
     -r           reverse the sort order (largest last instead of first)       //倒排序
     -t NUM       just show the top n queries                                       //显示前N多个
     -a           don't abstract all numbers to N and strings to 'S'
     -n NUM       abstract numbers with at least n digits within names   //抽象的数字,至 少有n位内的名称
     -g PATTERN   grep: only consider stmts that include this string      //配置模式
     -h HOSTNAME  hostname of db server for *-slow.log filename (can be wildcard),     //mysql所以机器名或者IP
     default is '*', i.e. match all
     -i NAME      name of server instance (if using mysql.server startup script)
     -l           don't subtract lock time from total time           //总时间中不减去锁定时间
    

linux下开启mysql慢查询,分析查询语句

MySQL Effective Reference

MySQL性能优化的最佳20+条经验 | | 酷 壳 – CoolShell

php

PHP的性能优化方法总结

什么情况之下,会遇到PHP性能问题?

1:PHP语法使用不恰当。
2:使用PHP语言做了它不擅长的事情。
3:使用PHP语言连接的服务不给力。
4:PHP自身的短板(PHP自身做不了的事情)。
5:我们也不知道的问题?(去探索、分析找到解决办法,提升开发境界)。

ab 压力测试

对线上站点做压力测试的时候,我们一定要将请求数和并发数,特别是并发数要设置的比较低,我们不能对线上的网站造成压力问题,不管是自己的还是别人的。

PHP性能问题一般不会超过占整个项目性能的50%,一般在30%~40%。

PHP性能问题的解决方向,三个层级。

PHP语言级的性能优化

PHP语言级的性能优化,指的是PHP语法基本功能,这部分优化比较简单易见、快速可行,比较快速看到效果。

多用PHP自身能力。

优化原则: 少写PHP的代码,多用PHP自身能力解决问题。

  • 性能问题:

自写代码冗余较多,可读性不佳,并且性能低,如代码很长很长…PHP代码越长PHP的执行效率越慢。为什么性能低?

PHP代码需要解析编译为C语言,底层C语言又要编译成汇编语言机器语言才能执行,这个过程在每次请求过来之后都要处理一遍,所以开销很大(项目变大的话…)。

  • 解决方法:

多使用PHP内置的变量、常量、函数。我们用PHP代码实现的功能和使用PHP内置的函数实现的同样功能差别是有的。

PHP内置函数的性能优劣。

  • 情况描述

PHP内置函数之间依然存在快慢差别;少用PHP魔术方法;

  • 建议:

多去了解PHP内置函数的执行实现复杂度。

  • 测试方法:比较效率测试,如用microtime()函数,取差值,精确到毫秒级别;Linux的time命令可以查看开销。

避免错误抑制符号“@”。

优化原则: 产生额外开销的错误抑制符号“@”,最好别用(不管是性能优化和项目的健壮性等方面)

@的逻辑是在代码前和代码结束后增加了Opcode,Opcode的作用就是忽略报错,其实就是相当于增加了error_reporting设置,等级报错为忽略(vld扩展可以查看被隐藏的Opcode);

合理使用内存。

  • 情况描述:

PHP有内存回收机制保底,但是也小心使用内存;

  • 建议:

利用unset()及时释放不使用的内存,比如一些数据库多余字段(注意:unset()有时会出现注销不掉的情况)

尽量少用正则表达式。

  • 情况描述:

正则表达式的开销大,使用起来简单,但是性能低因为,正则表达式需要回溯;正则表达式越长,回溯的开销越大,优化正则表达式是需要技术水平的,正则技术不达标,不要乱用正则。

避免在循环内做运算。

  • 情况描述:

循环内的计算式将被重复计算(我们在for循环或者while循环,会有重复计算,影响性能问题)。

  • 举例:

错误用法:

$str = "hello world";

for($i = 0; $i < strlen($str); $i ++){

    ...

}

PHP代码优化最佳实践

编写好的PHP代码是创建快速稳定Web应用的关键一步。从一开始就遵循一些最佳实践技巧将节省后期填坑的时间。

  1. 尽可能的使用PHP的内置方法

    只要可以尽可能的使用PHP的内置方法,而不是自己编写相同功能的方法。花点时间去熟悉和学习PHP的内置方法,不但可以帮助你更快的编写代码,而且可以使你编写的代码更高效的运行。

  2. 使用Json替代xml

    json_encode()和json_decode() 等PHP的内置方法,运行速度都非常快,所有应该优先使用Json。如果你无法避免使用xml,那么请务必使用正则表达式而不是DOM操作来进行解析。

  3. 使用缓存技术

    Memcache特别适用于减少数据库负载,而像APC或OPcache这样的字节码缓存引擎在脚本编译时可节省执行时间。

  4. 减少不必要的计算

    当一个变量会被多次使用时,一开始就计算好,肯定要比每次使用时都计算一遍要更高效。

  5. 使用isset()和empty()

    与count()、strlen()和sizeof()函数相比,isset()和empty()对于检测一个变量是否为空等场景更加简单和高效。

  6. 减少不必要的类

    如果你不打算重复使用一个类或者方法,那么它就没什么存在的价值。而如果你必须要定义和使用一个类,则需要合理规划类中的方法,对于不是特别公用的方法,尽量将他们放到子类中去,因为调用子类中的方法,比调用父类方法速度更快。

  7. 在生产环境关闭用作调试的相关代码及错误报告

    开发时打开错误报告,可以让你避免很多潜藏的Bug,而一些调试代码也有助于你定位Bug,但是当代码部署到生产环境后,这些错误报告和调试代码会拖慢你的程序速度,而且将一些错误报告直接显示给用户,也具有相当的安全风险。因此,在生产环境请关闭它们。

  8. 关闭数据库连接

    当使用完毕后,注销变量和关闭数据库连接,可以释放珍贵的内存资源。

  9. 使用聚合函数减少数据库查询

    查询数据库时,使用聚合函数,可以减少检索数据库的频率,并且使程序运行的更快。

  10. 使用强大的字符串操作函数

    举个例子,str_replace()比preg_replace()要快,而strtr()函数则比str_replace()函数快四倍。

  11. 尽量使用单引号

    如果可能,尽量使用单引号替代双引号。程序运行时,会检查双引号中的变量,这会拖慢程序的性能。

  12. 尝试使用恒等运算符

    由于“===”仅检查闭合范围,因此比使用“==”进行比较速度更快。

PHP代码之外的性能瓶颈因素

优化代码当然能够提高PHP的性能。但是,还有一些代码之外的因素也会成为PHP的性能瓶颈。这就是为什么程序员需要了解代码部署的整个服务器环境,这有助于他们在编写代码时有一定的心理准备,并能够在性能出现问题时,快速识别和定位性能瓶颈。以下是你遇到性能瓶颈时需要检查的点。

  1. 网络带宽

    如果网络带宽不够,其传输的总数据量将会受到严重影响,使其成为最明显的性能瓶颈。

  2. CPU

    如果只是传输一些纯静态的HTML,则不需要消耗很多CPU资源,但是PHP毕竟创建的是动态的应用程序,根据应用的需要,你可能至少需要一台具备多核处理器的服务器来提升PHP代码的运行效率。

  3. 共享内存

    缺少共享内存可能会影响进程间通信,从而影响程序性能。

  4. 文件系统

    随着时间推移,你的文件系统可能会出现大量磁盘碎片。如果内存足够,利用内存作为文件缓存可以加快磁盘的访问速度。

  5. 进程管理

    检查服务器的进程,确保里面没有非必要的进程。移除哪些不需要的网络协议、病毒扫描软件、邮件服务以及硬件驱动。将PHP代码运行在多线程模式,也能提高程序的响应时间。

  6. 相关的其它服务

    如果你的应用程序还依赖于一些外部服务,那这些外部服务的性能瓶颈也有可能拖慢你的应用。虽然这种情况下你能做的事情不多,但你仍然可以通过你这一边的操作来减轻外部服务性能瓶颈对你的影响,例如切换到备用服务上等。

更多PHP性能优化建议

  1. 发挥OPCache的优势

    由于默认情况下,PHP代码在执行时都会重新编译为可执行的中间代码OPCode,因此可以及时看到修改的代码所带来的变化,而不必频繁的重启PHP服务。不幸的是,如果每次在你的网站上运行时,都重新编译相同的代码会严重影响服务器的性能,这就是为什么opcode缓存或OPCache 非常有用。

    OPCache是一个将编译好的代码保存到内存中的扩展。因此,下一次代码执行时,PHP将检查时间戳和文件大小,以确定源文件是否已更改。如果没有,则直接运行缓存的代码。

    下图显示了运行无缓存的PHP应用程序,OPcache和eAccelerator(另一个PHP缓存工具)三者的执行时间和内存使用情况的差异。

    图片来源: Prestashop

  2. 识别数据库响应延迟

    如上所述,性能问题并不总是由代码引起的。大多数瓶颈都出现在应用程序必须访问资源的时候。由于PHP应用程序的数据访问层可能占用最高90%的执行时间,因此你应该采取的第一步是查看代码中访问数据库的所有实例。

    确保打开SQL的慢日志,以帮助你识别和处理慢SQL,然后评估这些查询的执行效率。如果你发现查询过多,或者在单次执行过程中发现相同的查询被多次进行,你可以通过减少数据库访问时间进行调整,从而提高应用程序的性能。

  3. 清理文件系统

    清理文件系统,并确保没有使用文件系统来存储Session。最重要的是,请注意file_exists(),filesize()或filetime()等触发文件统计信息的代码。将任何这些功能置于循环中可能会导致性能问题。

  4. 监控外部API接口

    大部分对外部系统有依赖关系的应用都会调用远程API。虽然这些远程API接口你无法直接控制,但你仍可以采取一些措施来减轻源自远程API的性能问题。例如,你可以缓存API输出的数据,或者可以在后台调用这些API。为API请求设置合理的超时时间,并且如果可能的话,随时做好API没有响应的情况下的显示输出。

  5. 使用工具评估检测你的PHP代码

    使用OPcache和监控外部API接口应该足以使大多数应用程序运行顺利;但是,如果你发现系统负载不断增加,那么可能需要使用工具来对你的PHP代码进行检测评估。完整的PHP代码检测评估虽然可能很耗时,但它可以为你提供有关应用程序性能的深入信息。幸运的是,有几个开源程序可以用于分析你的PHP代码,如Xdebug。

监控PHP性能的重要性

如果你没有做好准备,你的Web应用可能前一分钟还在正常运行,但是下一分钟,一波突然激增的流量就会导致你的应用程序崩溃。 当然,优化和重构总是需要时间、精力和资金,而且投入是否值得的也很难说。因此,做出明智决策的最佳方式是不断收集数据。

PHP性能监控软件可以帮助你立即测量所做的任何更改的影响。当然,知道要监测什么同样重要。速度和内存使用被认为是性能的最佳指标,因为它们影响到页面加载时间,这对Web应用程序至关重要。

虽然数据收集很重要,但是当你不需要监控系统时,你应该关闭监控系统,因为大量日志同样也会对性能造成影响。当然,这样的日志可以提供有关如何提高性能的有用信息,因此你应该在高峰期间定期监控。

未来的PHP性能

PHP仍在不断进化中,在目前正在开发的PHP 8版本中,最新的功能是即时编译或JIT,它将可以为我们创建更快的Web应用。随着技术的不断进步,用户的期望也随之增加。因此,开发人员必须始终关注未来的变化。

在构建Web应用程序时,请记住,今年的工作可能在明年不起作用。你可能需要进行调整才能持续保持优秀的PHP性能。在开发过程中,应该持续重点关注如何构建适用于高并发场景的Web应用和网站,保证它们的高可用性。

PHP opcode缓存

本文移至:http://www.phpgay.com/Article/detail/classid/2/id/61.html 8

  1. 什么是opcode

    解释器分析代码之后,生成可以直接运行的中间代码,就称做操作码,opcode

  2. 解释器与编译器的区别

    解释器是生成了中间代码后直接运行中间代码,运行时的控制权还是在解释器手里。

    编译器则是生成了中间代码之后还进一步优化代码,生成可以直接运行的目标程序 ,但不执行,等待用户触发执行,他的控制权在目标程序,和编译器无关。

  3. PHP是解释型语言

    PHP是解释型语言,他的原理与编译有点相似,包括词法分析,语法分析,语义分析…..,PHP解释器的核心引擎就是zend engine

  4. php如何查看一段代码的opcode

    安装PHP的parsekit扩展,通过扩展的api就可以查看PHP的opcode,如parsekit_compile_string()

    PHP -r “var_dump(parsekit_compile_string(‘print 1+1;’));”

  5. opcode有生成

    首先要经过词法分析,脚本代码可以看做是一系列单词组合,解释器要对这些单词进行分类,并打上记号

    比如print,我们查看PHP源码包中的zend/zend_language_scanner.l在这个文件中我们就可以查找到pirnt对应的标记。T_PRINT

    找到标记之后接下来就是语法分析,在zend/zend_language_parser.y中,我们可以找到T_PRINT对应的函数

    接着在zend/zend_compile.c中找到这个函数实现代码,这个函数就是实现 了opcode的转换。所有的opcode都是用户整数来表示 的。

  6. 开启opcode缓存

    生成opcode是需要系统开销的,每一次执行都要生成一次opcode,这样的开销还是可观的,所以PHP的优化必须开启opcode的缓存,来避免重复的编译。

    PHP的opcode缓存有APC,eAccelerator,XCache,这些都是把opcode放在共享内存中。

    以APC为例:在php.ini中设置 apc.cache_by_default = on

    通过可以查看缓存的情况,

  7. opcode缓存过期

    opcode缓存是会过期的,如果过期就要得新生成一次,当然也可以跳过过期检查的机制,在php.ini中设置apc.stat=off
    这样程序代码的修改得通过重启服务器来生效。

  8. 脚本的跟踪与分析,可以使用xdebug来跟踪,用xdebug可以实现性能跟踪器,找到程序的执行瓶颈,从而优化程序。
    xdebug.profiler_output_dir = /tmp/xdebug
    
    xdebug.profiler_output_name = cachegrind.out.%p
    
    
    xdebug的函数跟踪:
    
    xdebug.trace_output_dir = /tmp/xdebug
    
    xdebug.trace_output_name = trace.%c
    

window下可以用wincachegrind查看xdebug的报告文件。

PHP Effective Reference


高并发

CS_Offer/Web.md at master · xuelangZF/CS_Offer

负载均衡和F5是什么意思?百度知道

缓存

apache/nginx

ab

负载压力计算

流水->负载计算

前端优化

要从原理说起,当我们请求量特别大,请求数据少时可以将多个小图片聚合为一个大图片,通过定位来实现;如果图比较大,则需要用切图来实现,减少资源;


Docker,K8s, ElasticSearch,Hive, Spark
创建你的第一个App – Cordova中文网
利用 Puppet 实现自动化管理配置 Linux 计算机集群
envoy 中文参考文档 · GitBook


  1. 3.1 Web工作方式 – Go Web 编程 – 极客学院Wiki 
  2. 参考来源:开始使用PHPUnit|贝叶书 
  3. 看懂UML类图和时序图 — Graphic Design Patterns 
  4. 杰西·詹姆士·贾瑞特(英语:Jesse James Garrett)是一名用户体验设计领域的设计师、网页体验设计公司Adaptive Path的创办人,且为在使用浏览器浏览网页时;于页面更新内容时的过程中减低需消耗服务器发送资源之异步更新技术“AJAX”概念的命名者。Jesse James Garrett: jjg.net 
  5. 台湾著名Linux网站——”鸟哥的Linux私房菜”站长蔡德明,台湾成功大学环境工程系博士,就学期间由于研究需要接触到Linux操作系统,又因实验室交接需求而建立“鸟哥的Linux私房菜”网站。擅长领域:Linux操作系统、网站规划与维护、网络安全,兴趣是写作与阅读,研究方向是网络应用整合。 
  6. php_MySQL_数据库优化有哪些方式?SegmentFault思否
    mysql优化不可不做的事情 – 踏雪无痕SS – 博客园 
  7. 注意 query cache 
  8. php opcode缓存 – 统一B界 – 博客园 

发表评论

Top