PHP is_array()

同事维护的站点遇到一个SQL注入漏洞,最后发现是由于对in_array()的理解错误(一直以为是绝对匹配才会返回true),同时拼接SQL语句时也没有使用Prepared Statement导致。代码中使用in_array($var, $white_set)判断从Query String获得的变量是否符合要求,参见下面示例代码($var为一整型变量,取用时没有使用intval($var)或者(int)$var强制转换为整型)。

$white_set = array(11, 13, 16);
$var = $_GET['var'];
if (in_array($var, $white_set)) {
$query = ‘ … column = ‘ . $var . ‘ … ‘;

}

访问http://www.example.com/path/to?var=16′ and ‘x’='时,$var=16′ and ‘x’=',使用in_array($var, $white_set)判断会得到true,因为in_array的第三个参数默认为false,此时在依次比较$var和$white_set中的元素会进行类型转换,相当于使用==进行比较;如果第三个参数为true,则相当于使用===进行比较,两个变量只有完全一致才会返回true。

总结:in_array()第三个参数决定变量和数组中元素如何进行比较。值为false时(默认),相当于==;值为true时,相当于===。

使用PHP SimpleXML生成XML文件

使用SimpleXML生成XML文件很简单,示例代码如下:

$xml = new SimpleXMLElement('<books />');
$book = $xml->addChild('book');
$book->addChild('title', '拖延心理学');
$book->addChild('isbn', '9787300113906');
$rating = $book->addChild('rating', 5);
$rating->addAttribute('type', 'stars');
// 添加其他节点
echo $xml->asXML();

输入结果如下:

<?xml version="1.0"?>
<books><book><title>&#x62D6;&#x5EF6;&#x5FC3;&#x7406;&#x5B66;</title><isbn>9787300113906</isbn><rating type="stars">5</rating></book></books>

请注意输出的XML内容,声明中没有encoding="UTF-8",汉字也被转换为对应的UTF-8编码。

如何解决上面遇到的问题呢?

虽然SimpleXML没有提供设置encoding的接口,但是可以通过以下途径解决:

使用如下代码初始化SimpleXMLElement对象:

$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><books />');

PS:网上有建议说在最后生成字符串时使用$xml = str_replace('<?xml version="1.0"?>', '<?xml version="1.0" encoding="UTF-8"?>', $xml);命令进行替换实现添加encoding的目的,但是这种方法无法解决汉字转为UTF-8编码的问题。

PHP: json_encode()

开发过程中经常使用到的API大部分使用JSON作为数据交换的格式,PHP使用json_encode()将PHP的不同类型的变量转换为对应的JSON字符串。虽然经常使用,但直到今天我才注意到原来json_encode()还支持第二个参数options。

函数原型

string json_encode(mixed $value [, int $options = 0])

参数说明

value

value可以为非resource类型的任意PHP变量。

options

目前我本地的PHP版本为5.3.2,因此只试验了5.3.0引入的常量,所有可用的常量以及它们含义可以在JSON Constant页面查看。每一个常量的字面意思表达的都很清楚,不过对于它们的使用场景我还有些疑惑,比如:可不可以混搭使用?

PHP 5.3.0

  • JSON_HEX_QUOT: 将所有的双引号(”)转换为\u0022。
    // 实例代码:
    $data = '"';
    echo json_encode($data); // "\""
    echo json_encode($data, JSON_HEX_QUOT); // "\u0022"
  • JSON_HEX_TAG: 将所有的大于号(>)转换为\u003E,将所有的小于号(<)转换为 \u003C。
  • JSON_HEX_AMP: 将所有的与号(&)转换为 \u0026。
  • JSON_HEX_APOS: 将所有的单引号(’)转换为\u0027。
  • JSON_FORCE_OBJECT: 当value为非关联数组时强制输出结果为JSON对象。在接收者要求数据为对象且value为空数组时使用。
    // 实例代码:
    $data = array();
    echo json_encode($data); // []
    echo json_encode($data, JSON_FORCE_OBJECT); // {}

PHP 5.3.3

  • JSON_NUMERIC_CHECK: Encodes numeric strings as numbers.

PHP 5.4.0

  • JSON_BIGINT_AS_STRING: Encodes large integers as their original string value. Available since PHP 5.4.0.
  • JSON_PRETTY_PRINT: Use whitespace in returned data to format it. Available since PHP 5.4.0.
  • JSON_UNESCAPED_SLASHES: Don’t escape /. Available since PHP 5.4.0.
  • JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (default is to escape as \uXXXX). Available since PHP 5.4.0.

PS:今天花在浏览网页的时间太多了,也不知道写些什么,最后挑了个简单的话题完成了今天的更新任务。

Update:

多种JSON常量可以混搭使用,如将所有的单引号和双引号转换为对应的16进制Unicode编码:json_encode($data, JSON_HEX_QUOT + JSON_HEX_APOS);

PHP最佳实践之编码规范

本文编译自上面展示的幻灯片,作者为Zend Framework架构师、项目负责人。

编码规范的目的

  1. 效率
  2. 可维护性
  3. 协作

效率

如果没有编码规范,你将会:

  1. 经常格式化他人的代码
  2. 6个月前的代码和今天的代码具有不同的视觉结构
  3. 修改旧代码的时候,不时遇到语法错误,如条件语句缺少括号、列表数据遗漏逗号等等

可维护性

遵循编码规范,你的代码将具有可预见的布局,包括文件布局和代码布局。容易阅读的代码将会容易理解、维护和重构。

协作

团队成员遵循编码规范,任何程序员可以拾起并理解他人的代码,这将帮助他们进行维护和重构。还可以更加高效的进行开发,获得更高的客户满意度。

编码规范提供了什么?

  1. 文件布局的一致性
  2. 代码布局的一致性

使用公共规范

不要发明自己的规范,不管是为个人还是为公司。因为你并不特别,你的PHP代码也不是独一无二的。他人已经探讨过这个问题,你可以受益于集体的智慧。

为什么使用公共规范?

  1. 客观 – 选择将不是基于主观的喜好,而是实际的经验
  2. 招聘或外包的需求 – 容易判断求职者的经验或代码的质量
  3. 兼容性 – 遵循你用到的库的编码规范

已有的选择

  1. PEAR 编码规范
  2. Zend Framework 编码规范
  3. eZcomponents 编码规范
  4. PHPLib

PEAR编码规范

PEAR的规范是最广泛接受并使用的编码桂冠,这很大程度上受到PEAR用户数的影响,也是得益于该规范的整体质量与明确性。

PEAR命名约定

 类名(Classes)

  1. 混合模式
  2. 首字母大写
  3. 使用下划线分隔逻辑包和代码的边界
  4. 示例:Spreadsheet_Excel_Writer, Services_Google_AdWords

文件(Files)

  1. 文件名和类名一一对应(一个类一个文件)
  2. .php 后缀
  3. 类名的下划线对应着目录结构
  4. 没有松散的PHP代码
  5. 示例:Spreadsheet_Excel_Writer ==> Spreadsheet/Excel/Writer.php

变量(Variables)

  1. 驼峰模式(CamelCase)
  2. 首字母小写
  3. 示例:var $firstName =

常量(Constants)

  1. 全部大写
  2. 下划线分隔单词
  3. 示例:const DB_HOST =

私有和受保护的属性(Private or protected properties)

  1. 首字母为下划线
  2. 示例:private $_username;

函数与方法(Functions & Methods)

  1. 驼峰模式
  2. 首字母小写
  3. 示例: function toString()

私有和受保护的方法(Private or protected methods)

  1. 首字母为下划线
  2. 示例:private function _doLogin()

缩进(Indentation)

  1. 使用空格(Spaces)而不是制表符(Tabs)(永恒的圣战)
  2. 每层缩进使用4个空格
  3. 目的是跨编辑器获得一致的视觉效果

行长度(Line Length)

  1. 建议75 – 85个字符

不使用Shell风格注释(#)

块格式(Block formatting)

  1. 函数和类的左括号在声明的下一行,同一层缩进
  2. 控制结构保证左括号和声明在同一行
  3. 所有的控制结构使用括号,没有例外

更多PEAR编码规范的信息

当前规范:http://pear.php.net/manual/en/standards.php

提名规范:http://pear.php.net/manual/en/pear2cs.php

总结

  1. 使用公共的编码规范
  2. 总是遵循编码规范

Gonna Sailing ;-)
==END==