Hologram,我们后端服务的搭建主要使用了两种编程语言:PHP和Python。 其中,PHP组件最接近用户层,它提供了所有服务的REST API接口。

有人曾向我们提出疑问:大家都在唱衰PHP,认为它“不仅笨重而且过时”,为什么你们还会重度使用PHP?在我看来,PHP得到这样评价的原因有两个:

  1. 人们早在2005年就开始使用它,当时它是一门非常年轻的语言,缺少很多真正有用或通用的功能特性,例如缺少对面向对象的特性支持。
  2. 为保持较好的兼容性,许多流行的应用程序(比如 Wordpress),它们并没有充分利用该语言的很多新功能特性,即使PHP的很多新功能特性发布很久了,开发人员仍然坚持使用老版本的PHP。

虽然上述问题客观存在,但是我仍然想为PHP辩护一下——PHP仍然是一门非常有用的编程语言,并且非常适合我们的需求。

我们都已经知道PHP具有一些不错的内置Web服务功能,例如可以获取HTTP Header信息、完整的session cookie支持等。但是,可能很多人不知道,PHP在编程语言界仍占有一席之位,这与它的一些其他功能特性有关。接下来,我要阐述PHP的一些优点。

面向对象!

PHP的早些版本不支持类对象,因此,代码很容易变得混乱起来。没有面向对象,我们就需要写一大串的include来引用需要的一些方法函数,并且还必须不断地将大量的参数变量传递给名称很长的函数。

现在,你无需有上面这种担心。如今的 PHP 具有强大的面向对象支持,包括类、构造函数、析构函数、命名空间和继承等所有必须的功能。

除此之外,PHP 具备一些特有的强大功能。

自动加载器

PHP 有一个非常有用的功能特性,如果某个类尚未加载,它可以自动加载该类的文件。这意味着在所有文件的头部可以不再包含 include / require 语句块。如果你要使用一个类对象,那么它已经被自动加载了。

就其本身而言,这已经非常好了,但是更高级的使用场景是,在你的应用程序中可以完全自定义特定的自动加载逻辑,并且能将多个自动加载器链接在一起。这意味着你所有的第三方库也将会被自动加载。

在你的代码中,只需创建类或调用它们的方法,那么一切都会为你自动加载。你无需通过编写代码加载或者像其他语言一样使用路径来加载特定内容。在测试代码之外的整个 Hologram 代码库中,我们可能仅有两次调用了include()require()

刚刚提到了第三方库,下面就说一下依赖管理。

依赖管理

PHP 的软件包管理系统不输于其他的编程语言。我们在 Hologram 上使用的是 Composer,这是最受欢迎的一个依赖管理工具。它使用起来非常简单,只需将配置参数保存在 JSON 文件中就可以了。你可以为每个软件包指定要使用的版本范围,并且它会生成一个锁定文件,将该锁定文件共享到代码库中,就能确保所有开发者使用的第三方依赖版本完全相同。

将新的依赖包添加到 JSON 文件中并进行安装,操作起来非常简单,只需要在终端执行以下命令:

composer install somepackage

流行框架

如今,PHP 拥有一个强大的开发者社区,因此不仅有大量的工具库可供使用,而且拥有很多完整的框架可帮助简化应用程序的构建。在 Hologram 中,我们使用了 Slim 框架,该框架可以非常方便的定义 API 路由,还具有其他有用的功能,比如可以非常方便的添加用于身份验证以及速率限制的中间件等。

其他流行的框架还有 Laravel、Symfony 等。

PDO 数据库接口

在我用过的所有编程语言中,PHP 拥有最好用的数据库集成接口,而 PDO 是所有数据库接口的基础。PDO 的全称是 PHP Database Objects,它是执行 SQL 查询的首选方式。

它包括用于查询以及对结果分页的所有常用功能。还可以按“行”将数据存储到 PHP 关联数组,这意味着所有“列”数据在数组里存在着键值,且支持通过键值访问数组数据。

最棒的就是它支持参数化查询并可以防止 sql 注入。这意味着你可以执行以下操作:

// define $database as a PDO object
$stmt = $database->prepare("SELECT * FROM users WHERE id = ?;");
$result = $stmt->execute([$idnumber]);
$rows = $result->fetchAll();

PDO 会自动将“?”替换为 *$idnumber* 中的值,进行正确地转义以防止 SQL 注入攻击。

你还可以做一些更酷的事情,例如,它还支持绑定命名参数:

// define $database as a PDO object
$values = ['id' => 10, 'email' => 'someemail@hologram.io'];
$stmt = $database->prepare('SELECT * FROM users WHERE id = :id AND email = :email;');
$result = $stmt->execute($values);
$rows = $result->fetchAll();

在这种情况下,PDO 会在参数化查询的同时进行正确的参数替换。

无论什么类型的数据库引擎,PDO 都会对外公开相同的接口。当然,数据库引擎之间偶尔也会有 SQL 语句的差异,但是大多数情况下,你只需在初次连接数据库时指定好数据库的类型,然后就可以调用一套函数方法对所有数据库进行相同的操作。

Phinx 数据库迁移工具

说到数据库,我必须推荐一个非常好用的第三方库——Phinx。我们可以通过该工具来完成所有的数据库迁移工作。每当我们需要进行数据库模式变更时,可以使用 Phinx 在数据库上进行数据迁移操作。迁移过程如下所示:

$orders = $this->table('orders');
$orders->addColumn('invoice_text', 'string', ['length'=>256, 'default'=>''])
    ->update();

你可以去 Phinx 官网查看详细的使用文档。

内置函数库

最后一个使 PHP 变得更便捷、好用的是它拥有出色的内置工具函数库。

假设你有一个来自数据库的结果集,该结果集是一个以行数组为元素的数组。假设你要从每个数组元素中提取 name 列。当然,我们可以使用 PHP 支持的 map 函数来执行此操作,但是还有更简单的方式执行此操作:

$names = array_column($rows, 'name');

就这么简单,而且上面的方法运行速度非常快,因为 PHP 内核直接调用运行的 C 接口。

此外,还有很多类似的内置函数,从数组操作到解析 XML 到处理上传的文件,你都可以从 PHP 官方文档中查到具体的使用方法。

我列举一下自己常用的一些 PHP 内置函数:

array_chunk —— 对数组进行截取操作

array_unique —— 移除数组中的重复元素

DateTime —— 用于处理日期的方法,还可以解析简单的英语日期描述,例如“midnight first day of next month”

fpassthru —— 读取文件内容,并输出结果给用户。

str_getcsv —— 解析 CSV 格式字段的字符串,并返回一个包含所读取字段的数组。

urlencode —— 对字符串进行 URL 编码

不要忘记一些有用的符号运算符,例如?? ,它可以让你在对数组指定默认值的同时检查数组中索引是否存在。

$a = $some_array[$x] ?? 500;

结论

大家可以考虑将 PHP 用于自己的项目!它比你想像中的要好很多。

英文原文:

Why We Don’t Hate PHP

翻译原文地址:https://www.infoq.cn/article/rBzbWYZlHZu28g1cHf0U