分类目录归档:PHP

是 WordPress 让 PHP 更流行了,而不是框架

trends_php

Tiobe Index(编程语言世界排名指数),是一个显示各种编程语言的相对流行趋势的排名,开始于 2001 年,每个月更新一次。它将很多站点的搜索结果计算在内,以得到统计数据。这些站点包括:Google,Blogger,Wikipedia,YouTube,Baidu,Yahoo,Bing,Amazon 等。

PHP 在 Tiobe 上排名一直靠前,但最近它的排名更靠前了,2012 年是第7,现在是第5。人们可能将此归因为去年年底 Zend Framework 2 的发布,但并没有什么依据。

于是作者开始探究为什么 PHP 在 Tiobe 上的排名曲线突然上扬,真的是官方框架发布造成的么?下面是他的结论,我大致翻译如下。

一、WordPress 是最流行的 PHP 应用

作者用 Google Trends 去比较几个关键字的趋势,这些关键词是:WordPress,Joomla,Drupal,Magento,Zend Framework,它们的趋势走势图如封面所示。

介绍下它们。WordPress 是开源博客程序,Joomla 和 Drupal 都是开源内容管理发布系统,Magento 是开源的电子商务程序(国内似乎有家麦神电子商务把它汉化了在卖服务),Zend Framework 是官方开源的 PHP 框架。

最流行的是 WordPress,比其他应用都流行很多,垫底的是 Zend Framework。

其实这些关键词是作者认为最流行的关于 PHP 的词了,我觉得选这些词也是合适的。框架选一个做代表就行,而应用的流行程度差别很大,尽量选名气大的。我在这些词中把 PHP 也加进去,发现 WordPress 的流行程度都快接近 PHP 了,所以说,用“最流行的 PHP 应用”来描述 WordPress 没任何问题。

二、WordPress 自身比任何 PHP 框架要流行的多

这个结论细化了第一个结论。别以为只选了一个框架做比较,其实所有框架都差不多那个数量级。

三、WordPress 没有用第三方框架

为了补充第二个结论…

四、是应用让技术流行起来,而不是框架

趋势图上提到的 Magento 这个电子商务应用,是基于 Zend Framework 开发的,但它比框架流行。所以让应用流行起来的原因,并不是因为它使用了什么框架,而是它解决了用户的实际问题。

WordPress 也是同样道理,它对很多人都很有用。当人们要装个 WordPress 时,他们就知道了 PHP 这门技术,他们需要支持 PHP 的虚拟主机空间。这就促使了 PHP 的流行。

五、可扩展的 WordPress 插件生态

让 WordPress 流行的最重要原因之一就是它的插件系统。插件几乎能做任何事情,它们让 WordPress 成为一个平台,而不仅仅是一个应用。

六、很多非程序员因为 WordPress 开始开发 PHP

很多 WordPress 用户并不是程序员,但是因为找不到合适的插件、主题等,他们开始自己开发这些需求。

七、实用主义比理想主义好

软件项目,在技术上得是美丽的,得是一致的,得遵循良好的项目计划,得赞扬设计模式。

但上面这些真的没想象中的重要。很多应用被创建是基于一种很实际的感觉,它们只专注于解决现实世界的需要。

相对而言,很多 PHP 框架,它们似乎开发自另一个星球。它们常常由理想主义的人开发,更关注设计模式。

 

我的一点总结:

作者还是用确凿的证据证明了他的观点。而我,也从中看到一些要注意的地方:

1、过于注重技术。在开发岗位工作,注重技术是必须的。但是当自己做一个产品时,最应该关注的是解决现实世界的问题。

2、框架,解决的现实问题是,帮助普通开发者基于框架能更轻松快捷地开发应用。相对应用来说,面对的用户量肯定是少几个数量级的。

3、也许,针对某个流行应用提供解决方案或服务,就很有前途。当然,开发出解决现实世界问题的应用,更有前途。

 

编程要不要美

mujiang

在《GAE 添加 PHP 支持引发的一波讨论》中,有篇挺 PHP 的文章,第四部分,作者提出了:编程不一定要美(因为 PHP 被诟病的原因之一就是很多 PHP 代码是丑陋的)。

先翻译出来,再说说我的观点。

翻译开始 {

多年前,我开始看到人们赞美 RoR(Ruby On Rails),相对于使用 Java 或 PHP 这些语言,他们认为 RoR 是 Web 应用开发的最佳选择。

我看到在 RoR 创建者 David Heinemeier Hansson 的一些言论中,他在推行这样一个概念:编程必须要美。我想知道这是什么意思,是指代码风格么?还是指项目架构?还是指开发方法学?或者其他?

可能我没抓住要点,但我会这样设想:RoR 在推行一种开发方法学,作为一种正确和多产的方式。如果你不离开 Rails 平台,你的“火车”可以行驶得飞快。

但在我看来,持续地使用一种开发方法学并不依赖于你使用哪种开发语言或者框架。

我使用同样的方法学开发 PHP 项目很多年了。我觉得自己是多产的,因为我也是一贯遵循同样的方法学。我开发项目相当的快,因为工作已趋于机械化。

看起来,RoR 给那些没有方法学可遵循的同学的 Web 项目开发带来了一致性。

但是,遵循方法学的开发并不一定要基于 RoR,也不需要基于 Ruby。在 PHP 中也同样可以,你可以选择使用一个类似的框架或者不用也可以。事实上,现在出现的很多 PHP 框架都从 RoR 中学习引进了一些东西。

RoR 也从 PHP 中引进了些东西。例如,已经整合到 RoR 项目中的 ERB 模板系统,其实这就是一套模板解析机制,在 PHP 中早就有了。

有些人还布道说,你不能将代码和 HTML 模板混在一起,如果那样,就是丑陋的,在你死后你会被打入地狱的。所以,我猜 RoR 的同学也会同意:编程不一定要美。

还有一件被人们认为丑陋的事情是,在应用中使用全局代码而不是用类封装。好吧,你看看 WordPress 的源代码,你会看到遍地的全局代码。

我写过一篇为什么《用类组织你的代码》比使用全局代码要好,但也不是一种强制性的规则。

全局代码并不美,但它能工作,PHP 允许它的存在,很多开发者还在使用它,还靠它谋生。

} 翻译结束。

 

下面是我的观点。
一、作者提及的几个事实:

1、确切的说,RoR 是指一套开发框架,而 PHP 是指一门脚本语言,但在文章中,大家应该都能看出,作者是在比较两个开发平台(或者说环境、生态)。

2、RoR 推行了一套开发方法学,能提高生产力。这也是 RoR 流行的重要原因之一。

3、PHP 因为诞生的早,使用广泛,也遗留下来很多原始的特性;而 RoR 诞生在行业更加成熟的时期,是更先进的。解释型语言很多方面可以互相学习,但 RoR 有更多值得 PHP 学习的地方。

4、开发方法学等理论知识,都是跨语言的,这些知识比掌握一门语言语法更有价值。当然语言对理论的支持程度有高低,RoR 对开发方法学的支持应该不错(我没实践过,此为揣测),而 PHP 中也有框架能支持,但框架太多,还得进行选择。

二、作者并没有证明他的观点:

1、关于“美”的概念,RoR 创建者所指的“美”应该是:好的编码风格、好项目的架构、等等(如作者所理解的),目的是为了能良好应对未来的变化。但是作者举的例子中,HTML 模板和代码不能混杂,这里的“美”的意思更偏向“完美”的硬性标准,概念变了,不能作为论据。

2、WordPress 的成功,主要是市场上的成功,而不是技术上的。不管代码美不美,我想 WordPress 都能成功,只要它抓住了市场的需求。所以,WordPress 的代码并不能作为论据。

3、作者在自己的文章《用类组织你的代码》中也提倡让代码“美”些,为了应对将来的变化。所以摆明了是在反驳自己提出的观点,除非他认为的“美”的意思是指完美。

4、所以,我和作者的观点一样,都是:编程还是得美一点。

三、题外话,学 PHP 还是 RoR:

1、如果选择 PHP

能从零开始学习服务端 Web 开发,当你达到一定的精通程度(特别是熟悉一两个主流 PHP 框架时),转学 RoR 会很容易。写一些原生的 PHP 脚本和 SQL 查询语句,会帮助你理解 Web 应用的实现原理。

2、如果选择 RoR

能马上上手进行 Web 开发,能学习更先进的 Web 开发方法,高效,享用 RoR 带来的丰富的工具(我没实践,人云亦云下)。等等。但是底层细节都被隐藏,对原理会比较模糊。

3、Web 产业如何选择

现在,Python、Ruby 比起 PHP 更能满足 Web 产业对技术的生产力的需求。虽然 PHP 也一直在进步,单元测试、包依赖管理等工具也早都有了,但还是没有大面积应用起来。

从 GAE 支持 PHP 这事看来,Google 还是承认了 PHP 的地位,也许是因为 PHP 的门槛确实低得小盆友都能进来了。

4、我的理解是:学深了,都差不多。

Composer 的结构

composer-cartoon

这片文章是 composer.json 中各个字段的说明书。

一、Root Package(根目录包)

根目录包就是在你的项目的根目录由 composer.json 定义的包。主要就是由 composer.json 来定义你的项目的依赖。

某些字段只能在根目录包的中使用,比如 config 字段,只有根目录包能定义自己的配置。依赖包中的 config 字段是被忽略的。所以 config 字段是 root-only 的。

如果你克隆了其中一个依赖包并在上面工作,那么这个包就是根目录包。composer.json 还是一样的,但上下文不同。

(注:一个包是不是根目录包,取决于上下文。)

二、composer.json 中的各个属性(字段)

1、name

包的名字。由供应方(vendor)名和项目名组成,用 / 分隔。

在发布包的时候需要填。

2、description

对包的一个简短描述,通常是一行的长度。

在发布包的时候需要填。

3、version

包的版本。

格式必须是 X.Y.Z,选择性后缀:-dev、-alphaN、-betaN、-RCN。

4、type

包的类型,默认为 library。

包类型用于定制安装逻辑。如果你的包的安装需要一些特殊的逻辑,你可以定义一个定制的类型。它可以是一个 symfony-bundle 的类型,或者 wordpress-plugin,或者 typo3-module。这些类型将被特定的项目所用,它们将提供安装器来安装这些类型的包。

Composer 支持 3 种类型:

library:默认值。它将复制文件到 vendor 目录。

project:它表示这是个项目,而不是库。比如像 Symfony 标准版这种应用。

metapackage:一个含有依赖的空包,能触发安装,但不包含文件,不会向文件系统写任何东西。

composer-install:为其他的定制类型的包提供安装器的包。

5、keywords

一个与包相关的关键词数组。用于包的搜索和过滤。

可选。

6、homepage

项目的网站 URL。

可选。

7、time

版本发布时间。必须是 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS 格式。

可选。

8、license

包的许可证。可以是字符串或字符串数组。

可选,但强烈建议加上。

9、authors

包的作者。是个对象数组。

每个 author 对象有这些属性:

name:作者名字
email:作者邮箱
homepage:作者网站 URL
role:作者在项目中的角色(如:developer 或 translator)

10、support

各种关于该项目如何获取支持的信息。包含这些属性:

email:获取支持的邮箱
issues:问题跟踪的 URL
forum:论坛的 URL
wiki:Wiki 的 URL
irc:IRC 的频道
source:查看或下载源码的 URL

可选。

11、Package links

依赖包的映射表,由包名映射版本约束。如:

(1)require

列出包所依赖的包。除非这些依赖已经存在,否则这个包不会被安装。

(2)require-dev(root-only)

列出开发这个包(或跑测试等等)所依赖的包。在使用 install 命令时,只有带上 “–dev” 参数才能安装 dev 包。在使用 update 命令时,带上 “–no-dev” 则不更新。

(3)conflict

列出包会和哪些包发生冲突。它们将不被允许和你的包一起安装。如果约束了版本,则只会针对特定的版本。

(4)replace

列出哪些包要被这个包替代。

(5)provide

这个包所推荐的包列表。这个对公共接口最有用,一个包可以依赖一个虚拟的 logger 包,而实现 logger 接口的库可以放到 provide 字段中。

12、suggest

建议一些能让这个包工作的更好或得到增强的包列表。这些信息只在包安装完成时给出,暗示用户可以添加更多包,虽然不是必须要安装的。

格式是,包名映射文字说明,如:

13、autoload

提供给 PHP autoloader 的自动加载映射。

目前支持的有:PSR-0 自动加载规范,classmap 生成器,还有 files。

PSR-0 是比较推荐的,因为它的优秀的扩展性(在添加新的类的适合,不需要重新生成自动加载器)。

(1)PSR-0

在 psr-0 键名下,定义一个命名空间到路径的映射表,相对于包的根目录。注意,这也同样支持 PEAR-style 的没有命名空间的风格。

请注意命名空间的声明得以 \\ 结尾,确保自动加载器正确响应。

PSR-0 的引用可以在安装或更新时生成的文件中查看:
vendor/composer/autoload_namespaces.php

例子:

如果你需要在多个目录里查找同一个前缀的命名空间,你可以用数组,如:

PSR-0 风格并不局限于加载命名空间的声明的东西,也可以用于类这个层级。当库中只有一个在全局命名空间中的类时,这种方式就能用上。比如你有个 PHP 源文件放在项目的根目录,你可以这样声明:

如果你有个目录下全是用命名空间组织的,你可以用空前缀:

(2)Classmap

classmap 的引用可以在安装或更新时生成的文件中查看:
vendor/composer/autoload_classmap.php

类映射表是通过扫描指定的目录或文件下的所有的 .php 和 .inc 文件生成的。

你可以给任何不支持 PSR-0 的库用 classmap 生成器实现自动加载。配置上只要指定类所在的目录或文件即可:

(3)files

如果你确定需要在任何请求中都加载某些文件,你可以使用 files 自动加载机制。对于那些包中有些 PHP 函数但不能自动加载时特别有用。例如:

14、include-path

(将被弃用,它的功能由 autoload 代替。其实就是设置 include_path,可选)

15、target-dir

指定安装目标路径。

如果包的根目录是在命名空间下,自动加载就不正确了,所以才有 target-dir 来解决这个问题。

Symfony 就是个例子。它由很多组件包组成。Yaml 组件是在 Symfony\Component\Yaml  命名空间下的,它的根目录是 Yaml 目录。要让自动加载正常工作,我们要确保它不是安装在 vendor/symfony/yaml ,而是在 vendor/symfony/yaml/Symfony/Component/Yaml ,这样自动加载器才能从 vendor/symfony/yaml 加载它。

所以要定义 target-dir 如下:

16、minimum-stability(root-only)

定义根据稳定性如何过滤包。默认是 stable,如果你信赖一个 dev 包,你需要指明。

17、prefer-stable(root-only)

如果开启,Composer 会在稳定包和不稳定包中选择前者。

18、repositories(root-only)

定制包的仓库地址。

默认的,Composer 只使用 Packagist 仓库。通过指定仓库地址,你可以从任何地方获取包。

仓库不能递归。你只能将它们添加到主的 composer.json 中。所依赖包中 composer.json 文件中的仓库定义是被忽略的。

支持的仓库的类型有:

(1)composer

composer 仓库通过网络提供 packages.json 文件,它包含一个 composer.json 对象的列表,还有额外的 dist 或 source 信息。packages.json 文件通过 PHP 流加载。

(2)vcs

版本控制系统仓库,如:git、svn、hg。

(3)pear

通过它,你可以导入任何 pear 仓库到你的项目中。

(4)package

如果你依赖一个不支持 composer 的项目,你可以定义一个 package 类型的仓库,然后将 composer.json 对象直接写入。

完整的例子:

19、config(root-only)

针对项目的一些配置。

process-timeout:默认 300 秒,Composer 进程执行超时时间;
use-include-path:默认 false,如果是 true,Composer 自动加载器也会到 PHP 的 include_path 中查找;
preferred-install:默认 auto,设置 Composer 安装方式;
github-protocols:默认 [“git”, “https”],设置与 github 通信协议;
github-oauth:设置 oauth;
vendor-dir:默认 vendor,你可以换成别的;
bin-dir:默认 vendor/bin,如果项目有二进制文件,会链接到这;
cache-dir:默认 $home/cache,存放 Composer 运行时产生的缓存;
cache-files-dir:默认 $cache-dir/files,存放包的 zip 文件;
cache-repo-dir:默认 $cache-dir/repo,存放仓库元数据;
cache-vcs-dir:默认 $cache-dir/vcs,存放 vcs 克隆;
cache-files-ttl:默认六个月,缓存的过期时间;
cache-files-maxsize:默认 300M;
notify-no-install:默认 true,从仓库安装包会有个通知,可以关掉;
discard-changes:默认false,如何处理脏的更新;

20、scripts(root-only)

Composer 允许你在安装进程中安装钩子脚本,钩子是基于事件的;

21、extra

供 scripts 消费的额外数据;

22、bin

指定哪些文件必须被当做二进制文件处理的;

23、archive

设置创建包时的选项,exclude 属性可以设置排除哪些目录,例如:

 

这篇看下来,再看 Symfony 的标准版中的 composer.json,应该了然了吧。