吾日三省吾身

From 左耳耗子:

我现在45岁,属于老家伙了,我应该是要被年轻人干掉的。但是我还没有被干掉,为什么?因为年轻人都在加班,他们没时间学习。

所以我要感谢加班文化,感谢国内的互联网公司、微博上的娱乐八卦、微信上面的很无聊的碎片性的信息,感谢知乎上99%抖机灵的回答,感谢今日头条、抖音在消耗着大家的时间,把大家大块大块的时间变得很碎片,让你们根本学不了,还要感谢我们的墙,让你们出不去,所以我都不用努力了,我只要正常地看两本书,基本上就可以超越你们这些年轻人了。

From 韩天峰:

看到很多PHP程序员职业规划的文章,都是直接上来就提Linux、PHP、MySQL、Nginx、Redis、Memcache、jQuery这些,然后就直接上手搭环境、做项目,中级就是学习各种PHP框架和类库,高级阶段就是MySQL优化、PHP内核与扩展、架构设计这些了。

这些文章都存在一个严重的缺陷,不重视基础。就好比练武功,只求速成,不修炼内功和心法,只练各种招式,这样能高到哪里去?我所见过的PHP大牛每一个都是具备非常扎实的基础,他们之所以能成为大牛,是因为基础足够好。基础不稳,面对技术复杂的系统,如同盲人摸象、管中窥豹,只得其门不得其法。而且如果基础不扎实,也没办法进入大公司。国外的Google、Facebook,国内的腾讯、阿里、百度、滴滴、京东、新浪等知名互联网企业,无论哪一家公司面试必然会考验应聘者的技术功底。无法进入一个拥有大规模并发请求的项目中得到历练,不坚持提升自己,那也只能在小公司混日子了。

我最开始工作也是在2家小公司,后来加入腾讯阿里,主要原因还是我坚持学习基础知识,从而得倒了这个机会。有几个方面的基础知识,我建议每一位PHP程序员都应该好好学习一下。我推荐几本书给大家,包括深入理解计算机系统、现代操作系统、C程序设计语言、C语言数据结构和算法、Unix环境高级编程、TCP/IP网络通信详解。另外我建议大家学习一下面向对象方面知识,PHP这方面的书不太多,建议看Java面向对象编程、Java编程思想、J2EE这些书。PHP语言基础方面,建议认真地把PHP5权威编程这本书好好读完。另外不光要读,还要照着书中的讲解动手去编程实践。

总之有一个好的基础,再去学LAMP、Redis、PHP框架、前端,这样取得的成就更大。这与年龄无关、与学历无关、与智力无关,与天赋也无关。只要肯努力学习,人人可以成为技术大牛。

From 2gua

提升自己的最佳方式就是抠细节,细节抠多了,能力就提升了。

不要光光谈什么高大上的理由和理论,方法只是为了更好的抠细节,主体是抠细节,方法是辅助性质。

学习之路就是要抠细节,学习上抠细节是为了应用上放松脚步不抠细节。也就是加法做完做减法。做减法的时候又是另一个砍掉繁枝杂叶的过程,浓缩成精华,形成方法论。如此循环往复,良性前行。

CGI/FastCGI/PHP-CGI/PHP-FPM 概念

摘自https://jaminzhang.github.io/web/CGI-FastCGI-PHP-CGI-PHP-FPM-Concepts-Understanding/

CGI

CGI 全称是“公共网关接口”(Common Gateway Interface),HTTP 服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。

CGI 可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如 PHP, Perl, Tcl 等。

FastCGI

FastCGI 像是一个常驻(long-live)型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次(这是 CGI 最为人诟病的 fork-and-execute 模式)。
它还支持分布式的运算,即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

FastCGI 是语言无关的、可伸缩架构的 CGI 开放扩展,其主要行为是将 CGI 解释器进程保持在内存中并因此获得较高的性能。
众所周知,CGI 解释器的反复加载是 CGI 性能低下的主要原因,如果 CGI 解释器保持在内存中并接受 FastCGI 进程管理器调度,则可以提供良好的性能、伸缩性、Fail-Over 特性等等。

FastCGI特点:

  • FastCGI 具有语言无关性
  • FastCGI 在进程中的应用程序,独立于核心 Web 服务器运行,提供了一个比 API 更安全的环境。API 把应用程序的代码与核心的 Web 服务器链接在一起,这意味着在一个错误的 API 的应用程序可能会损坏其他应用程序或核心服务器。恶意的 API 的应用程序代码甚至可以窃取另一个应用程序或核心服务器的密钥
  • FastCGI 技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby 等。相关模块在 Apache, IIS, Lighttpd 等流行的服务器上也是可用的
  • FastCGI 不依赖于任何 Web 服务器的内部架构,因此即使服务器技术的变化, FastCGI 依然稳定不变

FastCGI工作原理:

  • Web Server 启动时载入 FastCGI 进程管理器(IIS ISAPI 或 Apache Module)
  • FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程(可见多个 php-cgi )并等待来自 Web Server 的连接
  • 当客户端请求到达 Web Server 时,FastCGI 进程管理器选择并连接到一个 CGI 解释器。Web Server 将 CGI 环境变量和标准输入发送到 FastCGI 子进程 php-cgi
  • FastCGI 子进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。当 FastCGI 子进程关闭连接时,请求便告处理完成。FastCGI 子进程接着等待并处理来自 FastCGI 进程管理器(运行在 Web Server 中)的下一个连接。 在 CGI 模式中,php-cgi 在此便退出了

FastCGI优缺点:

  • 优势:使用 FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作
  • 不足:因为是多进程,所以比 CGI 多线程消耗更多的服务器内存,PHP-CGI 解释器每进程消耗 7 至 25 兆内存,将这个数字乘以 50 或 100 就是很大的内存数

PHP-CGI

PHP-CGI 是 PHP 自带的 FastCGI 管理器。

PHP-CGI的不足:

  • php-cgi 变更 php.ini 配置后需重启 php-cgi 才能让新的 php-ini 生效,不可以平滑重启
  • 直接杀死 php-cgi 进程,php就不能运行了。(PHP-FPM 和 Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程

PHP-FPM

PHP-FPM 是一个 PHP FastCGI 管理器,是只用于 PHP 的,可以在 http://php-fpm.org/download 下载得到。

PHP-FPM 其实是 PHP 源代码的一个补丁,旨在将 FastCGI 进程管理整合进 PHP 包中。必须将它 patch 到你的 PHP 源代码中,在编译安装 PHP 后才可以使用。

我们可以在PHP 5.3.2 的源码树里下载得到直接整合了 PHP-FPM 的分支,据说下个版本会融合进 PHP 的主分支去。相对 Spawn-FCGI,PHP-FPM 在 CPU 和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用 crontab 进行监控,而 PHP-FPM 则没有这种烦恼。

PHP 5.3.3 已经集成 php-fpm 了,不再是第三方的包了。
PHP-FPM 提供了更好的 PHP 进程管理方式,可以有效控制内存和进程、可以平滑重载 PHP 配置,比 spawn-fcgi 具有更多有点,所以被 PHP 官方收录了。在 ./configure 的时候带 –enable-fpm 参数即可开启 PHP-FPM。

Spawn-FCGI

Spawn-FCGI 是一个通用的 FastCGI 管理服务器,它是 Lighttpd 中的一部分,很多人都用 Lighttpd 的 Spawn-FCGI 进行 FastCGI 模式下的管理工作,不过有不少缺点。而 PHP-FPM 的出现多少缓解了一些问题,但 PHP-FPM 有个缺点就是要重新编译,这对于一些已经运行的环境可能有不小的风险,在 PHP 5.3.3 中可以直接使用 PHP-FPM了。

PHP-FPM 与 Spawn-FCGI 对比

PHP-FPM 的使用非常方便,配置都是在 php-fpm.ini 的文件内,而启动、重启都可以从 php/sbin/php-fpm中进行。
更方便的是修改 php.ini后可以直接使用 php-fpm reload 进行加载,无需杀掉进程就可以完成 php.ini的修改加载。

结果显示使用 php-fpm 可以使 PHP 有不小的性能提升。php-fpm 控制的进程 CPU 回收的速度比较慢,内存分配的很均匀。
Spawn-FCGI 控制的进程 CPU 下降的很快,而内存分配的比较不均匀。有很多进程似乎未分配到,而另外一些却占用很高。可能是由于进程任务分配的不均匀导致的。而这也导致了总体响应速度的下降。而 PHP-FPM 合理的分配,导致总体响应的提到以及任务的平均。

数据结构算法总结

线性表

  • 数组
  • 链表
    • 单链表
    • 双向链表
    • 循环链表
    • 双向循环链表
    • 静态链表
    • 顺序栈
    • 链式栈
  • 队列
    • 普通队列
    • 双端队列
    • 阻塞队列
    • 并发队列
    • 阻塞并发队列

散列表

  • 散列函数
  • 冲突解决
    • 链表法
    • 开放寻址
    • 其他
  • 动态扩容
  • 位图

  • 二叉树
    • 平衡二叉树
    • 二叉查找树
    • 平衡二叉查找树
      • AVL树
      • 红黑树
    • 完全二叉树
    • 满二叉树
  • 多路查找树
    • B树
    • B+树
    • 2-3树
    • 2-3-4树
    • 小顶堆
    • 大顶堆
    • 优先级队列
    • 斐波那契堆
    • 二项堆
  • 其他
    • 树状数组
    • 线段树

  • 图的存储
    • 邻接矩阵
    • 邻接表
  • 拓扑排序
  • 最短路径
  • 关键路径
  • 最小生成树
  • 二分图
  • 最大流

复杂度分析

  • 空间复杂度
  • 时间复杂度
    • 最好
    • 最坏
    • 平均
    • 均摊

基本算法思想

  • 贪心算法
  • 分治算法
  • 动态规划
  • 回溯算法
  • 枚举算法

排序

  • O(n^2)
    • 冒泡排序
    • 插入排序
    • 选择排序
    • 希尔排序
  • O(nlogn)
    • 归并排序
    • 快速排序
    • 堆排序
  • O(n)
    • 计数排序
    • 基数排序
    • 桶排序

搜索

  • 深度优先搜索
  • 广度优先搜索
  • A*启发式搜索

查找

  • 线性表查找
  • 树结构查找
  • 散列表查找

字符串匹配

  • 朴素
  • KMP
  • Robin-Karp
  • Boyer-Moore
  • AC自动机
  • Trie
  • 后缀数组

其他

  • 数论
  • 计算几何
  • 概率分析
  • 并查集
  • 拓扑网络
  • 矩阵运算
  • 线性规划

PHP版本迭代更新特性(持续更新)

PHP 7 新特性

  • 类型声明
  • 命名空间批量声明
  • 匿名类
  • 老式构造方法废弃
  • Throwable接口
  • 新的操作符
  • 常量数组
  • switch不再支持多个默认值
  • session_start函数调整
  • unserialize引入过滤器

类型生声明

函数入参和出参支持声明类型:

declare(strict_types=1); // 严格限制入参类型

function test(int $num) : int 
{
    return $num * $num;
}

print_r(test('2'));

命名空间批量声明

同一命名空间下的类、方法、常量可以合并引入(非混合模式、混合模式、复合模式),以复合模式为例:

use Publishers\{
    Paper\Book,
    Electronic\Ebook,
    Media\Video,
    Media\Audio
}

匿名类

与正常类相似,可以继承父类、实现接口,区别在于没有类名。主要用于快速实现小块的功能单元:

class Math
{
    public $first_number = 10;
    public $second_number = 20;

    public function add() : float
    {
        return $this->first_number + $this->second_number;
    }

    public function multiply_num()
    {
        return new class() extends Math
        {
            public function multiply(float $third_number) : float
            {
                return $this->add() * $third_number;
            }
        };
    }
}

$math = new Math();
print_r($math->multiply_num()->multiply(2));  

老式构造方法废弃

使用与类名同名的函数作为构造函数这种方式不推荐使用,将会在未来版本中移除。

Throwable接口

异常(Exception)和绝大部分错误(Fatal)都能通过 try/catch 的方式予以捕获并处理(继承自 Throwable 接口):

<?php
try {
    $a = 20;
    $division = $a / 0;
} catch (DivisionByZeroError $e) {
    echo $e->getMessage();
}

新操作符

  1. <=> 用于对参数进行比较: 两边相等返回0,左边小于右边返回-1,左边大于右边返回1
  2. ?? 三元运算符的优化,以前需要这么写: $title = isset($_POST[『title』]) ? $_POST[『title』] : NULL; 现在可以这么写: $title = $_POST[『title』] ?? NULL;
  3. 统一变量语法 为了解决 $$first[『name』] 这种写法容易造成语法混淆,引入统一变量语法,这种写法需要改为: ${$first[『name』]} 即将优先执行的部分用花括号括起来,否则会报错,并且得到不确定的输出。

常量数组

define('STORES', ['en', 'fr', 'ar']);

switch不再支持多个默认值

switch(true)
{
    default:
        echo '1';
        break;
    default:
        echo '2';    
}

以上代码在 PHP 7 中会报错: Fatal error: Switch statements may only contain one default …

session_start函数调整

支持传递配置参数以覆盖 php.ini 中的默认配置。

unserialize引入过滤器

为了安全起见,在该函数中引入过滤器,以限定可以反序列化的对象。

PHP 7.4 转自 PHP7.4新特性预览

  • 短闭包 RFC
  • 属性类型定义 RFC
  • Null Coalescing Assignment Operator RFC
  • 自定义对象序列化 RFC
  • 弃用左关联三元运算符 RFC
  • 预加载 RFC
  • 外部函数接口 RFC
  • Reflection for references RFC
  • mb_str_split RFC
  • ext-hash 始终开启RFC

短闭包

引用更简单的闭包写法,在原来的基础加上fn关键字,采用了类型javascript =>写法。

<?php
// 7.3之前
array_map(function (User $user) { 
    return $user->id; 
}, $users)
// 现在
array_map(fn(User $user) => $user->id, $users)

关于短封闭的一些注意事项:

  • 可以直接访问父作用域,不需要使用use关键字
  • $this像普通的闭包一样可用
  • 短闭包只能包含一行,也就是return语句

属性类型定义

可以指定类属性的类型定义,更加的明确类型。

<?php

class A
{
    public string $name;

    public Foo $foo;

    protected ClassName $classType;

    private ?ClassName $nullableClassType;

     // Types are also legal on static properties
    public static iterable $staticProp;


}

关于属性类型定义更详细的说明请参考此处

Null Coalescing Assignment Operator

更短的??操作符写法。

<?php
// 7.4之前
$data['date'] = $data['date'] ?? new DateTime();

// 现在
$data['date'] ??= new DateTime();

弃用左关联三元运算符

与大多数其他语言不同,PHP中的三元运算符是左关联的而不是右关联的。对于在不同语言之间切换的程序员来说,左关联行为通常没有用,并且令人困惑。此RFC建议弃用并删除三元运算符的左关联性,并且需要显式使用括号。

<?php

echo 1 ? 2 : 3 ? 4 : 5;   // deprecated 7.4, 7.3 之前这是ok的。
echo (1 ? 2 : 3) ? 4 : 5; // ok 

自定义对象序列化

添加两个新的序列化魔术方法__serialize,__unserialize主要来解决__wakeupSerializable带来一些问题。可以通过https://wiki.php.net/rfc/custom_object_serialization来查看对比。

预加载

预加载是PHP这期核心的变更,可以带来一些重大的性能改进。

简而言之,如果您使用的所有PHP Web框架,则必须在每次请求时加载和重新编译其文件。预加载允许服务器在启动时在内存中加载PHP文件,并使它们永久可用于所有后续请求。

性能提升当然需要付出代价,如果预加载文件的来源发生变化,则必须重新启动服务器。

外部函数接口

外部函数接口,简称FFI,此API允许在纯PHP中加载共享库(.DLL或.so),调用C函数和访问C数据结构,而无需深入了解Zend扩展API,也无需学习第三种“中间”语言。对于PHP,FFI开辟了一种在纯PHP中编写PHP扩展和绑定到C库的方法。。 这是一个复杂的主题。您仍然需要C知识才能正确使用此功能。大家可以阅读该项目来了解https://github.com/dstogov/php-ffi

Reflection for references

SymfonyvarCloner转储程序,这样的库很大程度上依赖于反射API来可靠地转储变量。以前,没有对引用的适当反射支持,导致这些库依赖hack来检测引用。 PHP 7.4添加了ReflectionReference类来解决这个问题。

mb_str_split

添加了多字节的字符串分割函数和str_split一样。

<?php
print_r(mb_str_split("你好中国", 2));

Array
(
    [0] => 你好
    [1] => 中国
)

ext-hash 默认开启

哈希扩展(ext / hash)始终可用,类似于datesplpcre扩展。