Zend是什么?
Zend 是创造PHP的公司.
Zend引擎是一个开源脚本引擎 (一个虚拟机),因作为PHP语言的重要核心而闻名。它使用C语言编写,用来执行 PHP 脚本;
Zend是 PHP 的解释器,PHP的语法将由它来解析,同时 Zend 支持动态扩展,让 PHP 支持更多的功能;
PHP可以做什么?
PHP 作为一门语言什么都可以开发
- 服务器脚本 (90%,用来开发Web 应用)
- 命令行脚本 (如 nslookup 在 shell 中执行的命令行程序,PHP也可以开发,经常给运维人员使用,用的几率很少。一般使用Python)
- 图形界面(不是PHP的主攻方向,但是可以开发,需要加载扩展)
Zend 引擎支持动态扩展,只要有相应的扩展,连 Win32窗口程序都可以开发
扩展
在PHP安装目录的 ext 目录下,有着各种各样的扩展 dll (.so),在PHP配置文件中,可以配置 是否开启某个扩展,扩展开启后,PHP就有了这方面的能力;
如: 在PHP配置中开启 Mysql的扩展,则PHP就具有了连接MYSQL的能力;
其实,扩展的本质就是一些 C 函数库(dll/so),当Zend引擎解析PHP脚本的时候,遇到调用第三方扩展库的代码,则连接库,调用库里面的函数,从而完成某些PHP本身做不到的功能; 由于 Zend 引擎是C语言写的,所以要求扩展库可以被C所动态调用,接下来我们也会简单的了解到,如何 开发自己的扩展库~
所以,PHP理论上可以实现任何功能,只要有对应的扩展库~
查看当前PHP加载的扩展
扩展存放在 ext 目录下,需要在配置文件 php.ini 中开启后,才可以被加载 ;如何查看当前PHP环境,哪些扩展被加载那? 可以使用下面这几种办法
01、通过查看PHP的配置文件,看看开启了哪些扩展(不方便)
02、通过调用 php 命令获得扩展信息
在 PHP 的安装目录下,提供了一些 程序,这些程序就是用来运行PHP脚本的(如同 Java中的 java.exe)
php -m
列出开启的扩展(最清晰)php -i
和 phpinfo() 效果一样,打印出PHP信息,从这里也能看出扩展,不过比较凌乱;php -i > D:\out.txt
打印出 phpinfo() PHP信息,输出在 D:out.txt 里,内容重定向
03、 通过 php 代码 <? phpinfo() ?>; 来查看扩展,比较凌乱;
04、通过 PHP代码 $resultArr = get_loaded_extensions()
函数 来获得,返回一个 扩展名称 数组;
05、通过 PHP代码 extension_loaded("")
可以通过传入扩展名,检测扩展是否加载;
06、通过 PHP代码 function_exists("")
可以通过传入函数名,检测扩展中的函数是否存在,从而判断扩展是否加载;
查看扩展的信息(版本等)
php --ri 扩展名
指定某个扩展名,输出该扩展的信息,可以看到版本,也可以看到它是否被加载;
例如:
php --ri memcached
结果如下:
php --ri memcached
memcached
memcached support => enabled
Version => 2.2.0
自己开发扩展
一、使用ext-skel C语言开发
ext-skel是PHP官方源码里提供的生成php扩展的工具,可以生成一个c语言框架的php扩展的骨架。
PHP 官方对扩展开发者非常不友好,源代码中提供的Zend API极其难用,API复杂而且凌乱,充斥着各种宏的写法。Zend API坑非常多,普通开发者很容易踩到坑里。出现各种莫名其妙的core dump问题。Zend API几乎没有任何文档,开发者如果要真正掌握这项技能需要付出大量的学习时间。
以上是swoole扩展开发者的肺腑之言,可见用这个方法来开发扩展,对我们初学者来说将是对自信心极严重的打击。幸好有大神们为我们准备了其他开发php扩展的方法,不用学习zend api,不用精通c语言,也照样能开发php扩展,而且生成的扩展运行速度不会比c语言开发的相差太多。
二、使用zephir 类php语言开发
Zephir提供了一种类似php的高级语言语法的方式,来自动生成扩展的c语言代码,使编写php扩展变得非常的简单。不过这种开发方式带来了一个问题,就是由于他用的不是c/c++语言开发,那就没办法直接利用现有的各种c/c++开发库来实现强大的功能。所以感觉上有点鸡肋。
三、使用PHP-X C++语言开发
php-x是知名的swoole扩展开发者根据多年的开发经验,提炼出来的一套基于c++的扩展开发框架。从文档来看,这是一个比较容易上手的开发框架,数据类型很齐全,和php cpp的开发风格非常相似,但本人还没有去体验使用。
按照php-x官方的文档,开发出来的扩展只支持PHP7以上,这是一个遗憾。
四、使用phpcpp C++语言开发
PHP CPP是我重点推荐的php扩展开发框架,简明易懂,功能强大,开发效率高,代码易维护,执行速度快。
PHP CPP是一款免费的php开发扩展库,主要针对C++语言,可以进行类集合的扩展和构建,采用简单的计算机语言,让扩展变得更有趣更有用,方便开发者进行维护和编写,易于理解、维护轻松并且代码优美。用C ++编写的算法看起来与用PHP编写的算法几乎完全相同。如果你知道如何在PHP中编程,你可以很容易地学习如何在C ++中做同样的。
- 优点一:不需要Zend引擎知识。
Zend引擎的内部太复杂,Zend引擎的代码是一团糟,并且大多是无证的。但是PHP-CPP库已经在非常容易使用的C ++类和对象中封装了所有这些复杂的结构。你可以使用C ++写出惊人的快速算法,而不必直接调用Zend引擎,甚至无需查看Zend引擎源代码。使用PHP-CPP,您可以编写本地代码,而无需处理PHP的内部。
- 优点二:支持所有重要的PHP功能
使用PHP-CPP,您可以像使用普通PHP脚本一样轻松地处理变量,数组,函数,对象,类,接口,异常和命名空间。除此之外,你可以使用C ++的所有功能,包括线程,lambda和异步编程。
- 优点三:支持PHP 5.X,PHP7的扩展开发
PHP-CPP有两套扩展开发框架,分别支持PHP 5.X,PHP7,虽然框架代码有两个,但是接口却是一样的。所以如果你要开发兼容多个版本的php扩展,不会花费你额外太多时间做兼容。
安装扩展就比较简单了,其实扩展就是函数库(动态连接库),将它放在 ext 目录下,并且在配置中开启加载即可;
(本文只做简单介绍,如果需要,查询更多资料来了解与开发
)
PHP两种执行方式
在 PHP 安装目录下,有 php.exe 和 php-cgi.exe,这两个都是执行PHP的解析器; php.exe 经常被用作 CLI命令行程序的 PHP解析器;
php-cgi.exe 被用作与Apache/Nginx配合的,FastCGI解析器;
所以 PHP 就有如下两种运行方式;
CLI 命令行执行
php D:\study.php
参数介绍:php -a
php采用shell交互式的方式运行PHP代码php -c
使用指定路径的配置文件(或配置文件目录 )来运行PHP脚本
php index_cli.php -c D:\\apache\\apache2.2.22\\bin\\php.ini
php -i
phpinfo信息输出php -m
显示加载的模块php -r
运行一段 PHP代码,而不是一整个脚本文件php -v
版本号php -h
帮助信息php --ini
显示配置信息,采用的配置文件路径php --ri
显示扩展名配置php -S
执行的时候,顺便开启一个微型 Web Server方便调试,这个还是挺有用的,需要临时调一个PHP的时候,不用装Apache/nginx那么庞大的环境
php 命令行脚本获取命令行参数
1. 命令行自定义变量 【argv|argv|argc】
在命令行里输入程序参数来更改其运行方式是很常见的做法。你也可以对CLI程序这样做。 PHP CLI带有两个特殊的变量,专门用来达到这个目的:
一个是$argv 变量,它通过命令行把传递给PHP脚本的参数保存为单独的数组元素;
另一个是 $argc
变量,它用来保存$argv数组里元素的个数。
!!!要注意的是,$argv的第一个自变量总是脚本自己的名称。
php -f .\\cli.php name age sex
## cli.php代码
<?php
print_r($argv);
## 输出
array(4) {
[0]=>
string(9) ".\cli.php"
[1]=>
string(4) "name"
[2]=>
string(3) "age"
[3]=>
string(3) "sex"
}
2. 命令行自定义变量[Console getopt()]
注意:这个方式需要在配置中打开[register\_argc\_argv]
php.exe \\tools\\index.php -f "value for f" -v -a --required value --optional="optional value" --option will
## tools\index.php 的代码
<?php
$shortopts = "";
$shortopts .= "f:"; // Required value
$shortopts .= "v::"; // Optional value
$shortopts .= "abc"; // These options do not accept values
$longopts = array( "required:", // Required value
"optional::", // Optional value
"option", // No value
"opt", // No value
);
$options = getopt($shortopts, $longopts);
var_dump($options);
?>
结果:
array(6) {
["f"]=>
string(11) "value for f"
["v"]=>
bool(false)
["a"]=>
bool(false)
["required"]=>
string(5) "value"
["optional"]=>
string(14) "optional value"
["option"]=>
bool(false)
}
CLI 命令行脚本的输入输出
在PHP CLI中,可以使用3个系统常量,分别为 STDIN、 STDOUT 和 STDERR。
(1) STDIN
STDIN 全称为 standard in 或 standard input 标准输入可以从终端取得任何数据。
(2) STDOUT
STDOUT 全称为 standard out 或 standard output 标准输出可以直接输出到屏幕(也可以输出到其他程序,使用STDIN取得),如果在PHP CLI模式里使用print或echo语句,则这些数据将发送到STDOUT。
(3) STDERR
STDERR 全称为 standard error 在默认情况下会直接发送至用户终端,当使用STDIN文件句柄从其他应用程序没有读取到数据时会生成一个“stdin.stderr”。
<?php
/**
* 本例是一个CLI与用户交互脚本,让其输出用户名与年龄并输出
* 标准输出: fwrite(STDOUT,'请输出用户名:') //输出内容
* 标准输入: fgets(STDIN) //获取用户输入的内容
* 标准错误输出: fwrite(STDERR,'错误:xxxxx') //输出错误信息
*
* 运行效果:
* [root@zzx tmp]# /usr/local/php/bin/php /wwwroot/test/httpsqs/cliPHP.php
* Enter your name:
* Enter your name:zhangsan
* Enter your age:abc
* Notice: age must be an integer,try again!
* Enter your age:aaa
* Notice: age must be an integer,try again!
* Enter your age:22
* Hello zhangsan, your age is 22
*/
$name = '';
$age = '';
while(true){
fwrite(STDOUT,"Enter your name:"); //标准输出,等待用户输入用户名
$name = trim(fgets(STDIN)); //标准输入,立即获取用户名
if(!empty($name)){
break 1;
}
}
while(true){
fwrite(STDOUT,"Enter your age:");
$age = trim(fgets(STDIN));
if(empty($age)){
continue 1;
}
$matchNum = preg_match('/^\d+$/',$age); //验证整型,获取匹配次数
if($matchNum == 0){
fwrite(STDERR,"Notice: age must be an integer,try again!\r\n");
}else{
break 1;
}
}
//do something here...
$outStr = "Hello $name, your age is $age";
fwrite(STDOUT,$outStr);
echo "\n\n";
?>
FastCGI(CGI) 方式执行
FastCgi的时候是使用 php-cgi 来解析PHP的,详情请直接 php-cgi -h
来看看如何使用它~
Web FastCGI 运行 和 CLI 运行时 不一致的问题
php.exe 和 php-cgi 虽然应用场景不同,但是他们背后都是同一个 Zend 引擎,但是有些时候,你会发现 Web PHP 的扩展 和 CLI 扩展不一致,这种情况可能出现,我们来分析一下原因;
比如,现在有一个 Web项目,你想看看当前加载了哪些扩展,你在Web 中使用 phpinfo() ,然后 php -m
也输出了当前加载的扩展列表,但是他们有可能不一致;
造成这样的原因是,有可能 php 和 php-cgi 分别加载了不同的 php.ini ; 如果想要 CLI 和 Web 的运行配置一致,那么可以使用命令,让CLI使用 Web 的配置;
# 让 index_cli.php 命令行脚本和 Web 使用相同的配置
php index_cli.php -c D:\\apache\\apache2.2.22\\bin\\php.ini
查看当前配置文件路径
php -i 和 phpinfo() 中有两个地方显示和当前配置相关的信息;
在 CLI 模式下,你可以使用 php --ini
来获得当前的配置文件位置
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。