作者归档:admin

PHP手册拾遗四:变量函数

PHP手册拾遗:变量函数
1、isset()函数
若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。
对于一个数组的元素,如果该元素的值为NULL,使用isset()函数将返回FALSE,此时需要使用array_key_exists函数。如下所示代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
$array = array('t1' => NULL);
if (isset($array['t1'])) {                                                               
    echo 'Yes';
}else{
    echo 'No';
}
echo '<br />';
 
if (array_key_exists('t1', $array)) {
    echo 'Yes';
}else{
    echo 'No';
}

2、empty()函数
这是一个语言结构而非函数
empty() 只检测变量,检测任何非变量的东西都将导致解析错误。换句话说,后边的语句将不会起作用: empty(addslashes($name))。
如下示例:

1
2
3
$str = "phppan";
if (empty(1));  //Parse error: syntax error, unexpected T_LNUMBER
if (empty(addslashes($str)));   //  Fatal error: Can't use function return value in write context

3、floatval()函数
float floatval ( mixed var )
var 可以是任何标量类型。你不能将 floatval() 用于数组或对象。

4、import_request_variables函数
将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。
很少用到此函数,一般都是直接使用$_GET/$_POST/$_COOKIE
如果要将其它变量导入到全局变量中,可以考虑使用extract()。

5、serialize()与unserialize()
serialize会存储数组/对象中的引用。因此可以通过序列化和反序列化实现深拷贝。
当序列化对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 __wakeup() 成员函数。

6、unset — 释放给定的变量
如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。
如下所示代码:

1
2
3
4
5
6
7
8
9
$a = 10;
function unset_global_var() {
    global $a;
    unset($a);
    echo $a, '<br />';
}
unset_global_var();
echo $a, '<br />';
die();

如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。
如果在函数中 unset() 一个静态变量,则 unset() 将销毁此变量及其所有的引用。
新版本的手册中的示例很能说明上面的这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
function foo() {
    static $bar;
    $bar++;
    echo "Before unset: $bar, ";
    unset($bar);
    $bar = 23;
    echo "after unset: $bar<br />";
}
 
foo();
foo();
foo();

输出:
Before unset: 1, after unset: 23
Before unset: 2, after unset: 23
Before unset: 3, after unset: 23

如果在函数中 unset() 一个全局变量,可使用 $GLOBALS 数组来实现:

WIN7下VS2008下编译PHP扩展的6个细节

1、编译生成的dll文件无法加载的问题
此时apache启动时可能会报如下错误:
PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) ‘php_martin.dll’ in Unknown on line 0
原因:get_module在动态链接库中不对外开放
修改:在vs2008的项目属性,选择【Configuration Properties】-> 【C/C++】-> 【Preprocessor】-> 【Preprocessor Definitions】增加(COMPILE_DL_MARTIN)宏定义
查看方式:进入vs2008的命令行模式,进入dll所在文件夹,输入命令:dumpbin /exports php_martin.dll
查看是否提供了get_module函数
以上的martin需换成你自己的扩展名

2、LNK2001: unresolved external symbol _ZVAL_ADDREF问题
在之前的文章PHP5.3版本编译扩展时出现:LNK2001: unresolved external symbol _ZVAL_ADDREF
有提到解决方案,只是这样是将新的接口转换成旧的接口,这对于无法修改的旧代码可以适用,但是对于新的代码,我们建议在旧版本的时候使用Z_ADDREF_P将ZVAL_ADDREF替换,如下所示代码:

1
2
3
#ifndef Z_ADDREF_P
#define Z_ADDREF_P(x) ZVAL_ADDREF(x)
#endif

感谢鸟哥的指导

3、对于在被其它c文件include的c文件,在进行编译操作时需要将其从项目中排除掉。

4、Runtime Library
在编译时如遇到显示如下错误时:

1
2
3
4
5
Error	229	error LNK2019: unresolved external symbol __imp___free_dbg referenced in function
 
Error	230	error LNK2019: unresolved external symbol __imp___malloc_dbg referenced in function 
 
Error	231	error LNK2019: unresolved external symbol __imp___strdup_dbg referenced in function

LNK2019: unresolved external symbol __imp___free_dbg referenced
在vs2008的项目属性,选择【Configuration Properties】-> 【C/C++】-> 【Code Generation】-> 【Runtime Library】,将其改为/MDd,而不是/MD

5、32位,64位问题
如有报错:Error 137 error C2466: cannot allocate an array of constant size 0
这可能是VS2008 默认使用 64 位的 time_t 结构
建议在命令中添加:/D “_USE_32BIT_TIME_T=1″

6、对于不同版本的dll编译,除了对应版本的源码外,所需要的php5ts.lib文件也要使用其相对应版本
否则会在链接时报LNK2019错误,如:
error LNK2019: unresolved external symbol __imp__zend_str_tolower_dup referenced in function
error LNK2019: unresolved external symbol __imp__gc_remove_zval_from_buffer referenced in function

–EOF–

PHP5.3版本编译扩展时出现:LNK2001: unresolved external symbol _ZVAL_ADDREF

PHP5.3版本编译扩展时出现的问题
近,因要编译PHP扩展,本着最新最好的出发点,将PHP5.3的源码包下载下来,并将扩展源码创建VS2008项目,在经历百般磨难后,终于不再出现语法错误,然而当满怀希望按下F7键后,发现出现了N多的LNK2001和LNK2019错误,其中error LNK2001巨多,在纠结了一个周末后,可能是感动上天,终于在GOOGLE中找到了答案。
报错如下:
error LNK2001: unresolved external symbol _ZVAL_ADDREF
GOOGLE给的答案是php5.3以上版本更改了一些Zend API,而ZVAL_ADDREF刚好是其中的一个。
如下为解决方案:
假设我们的扩展为martin,则在php_martin.h或martin文件中,在include了相关php本身的头文件后添加如下 代码:

1
2
3
4
5
6
7
8
9
 
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION >= 6)
#undef ZVAL_REFCOUNT
#undef ZVAL_ADDREF
#undef ZVAL_DELREF
#define ZVAL_REFCOUNT Z_REFCOUNT_P
#define ZVAL_ADDREF Z_ADDREF_P
#define ZVAL_DELREF Z_DELREF_P
#endif

以上代码的作用是将新的宏以旧名重定义,以保持其可用性。

【参考资料】

http://www.hightman.cn/bbs/showthread.php?tid=656

http://d.hatena.ne.jp/rsky/20071016/1192524940