分类 代码分析 下的文章

前台显示的总会员数与用户表总数不一致的问题排查

今天有个朋友反应他的站前台显示的会员数和用户表里不一致,顺便帮他排查了下。

原因:
由于QQ互联之前更改了注册流程,引入了QQ互联游客组的概念。
所以Discuz侧计算会员总数的时候也带上了QQ互联游客组的数目。

具体的分析:
source\class\table\table_common_member.php文件,有如下代码:

/**
 * 统计会员数
 * @param int $fetch_archive 0:只查询主表,1:查询主表和存档表
 * @return int
 */
public function count($fetch_archive = 1) {
	$count = DB::result_first('SELECT COUNT(*) FROM %t', array($this->_table));
	if(isset($this->membersplit) && $fetch_archive) {
		$count += C::t($this->_table.'_archive')->count();
	}
	//增加QQ互联临时用户数
	$count += intval(DB::result_first('SELECT COUNT(*) FROM '.DB::table('common_connect_guest'), null, true));
	return $count;
}

注意其中的这句代码
$count += intval(DB::result_first('SELECT COUNT(*) FROM '.DB::table('common_connect_guest'), null, true));

这里加上了common_connect_guest表里的记录数,common_member_guest表是QQ互联的游客用户表。

Windows Phone通知类型分析

最近在做手机推送方面的工作,整理一下Windows Phone通知的相关资料。

Windows Phone支持的通知类型有三种:

Toast通知

Toast 通知显示在屏幕的顶部,用于通知用户某个事件,如新闻或天气警报。除非用户通过向右轻拂关闭通知,否则 Toast 将显示大约 10 秒钟。如果用户点按 Toast,则会启动发送该 Toast 通知的应用程序。
Toast通知

磁贴通知

磁贴通知可用于更新“开始”屏幕上的磁贴。磁贴为分为正反两面。
磁贴通知

RAW通知

可以使用 Raw 通知向您的应用程序发送信息。
如果您的应用程序当前未运行,则 Raw 通知会在 Microsoft 推送通知服务上丢弃并且不会发送到设备。

自定义的HTTP标头:

MessageID

与响应关联的通知消息 ID。
如果未将此标头添加到 POST 请求,则 Microsoft 推送通知服务会在响应中忽略此标头。

格式:X-MessageID:MessageIDValue
其中MessageIDValue类型为STRING。

NotificationClass

批处理间隔,指示推送通知将从推送通知服务发送到应用程序的时间。
如果此标头不存在,则推送通知服务会立即发送该消息。

格式:X-NotificationClass:NotificationClassValue
其中NotificationClassValue类型为DIGIT。

此标头可能的值:

Toast 通知
2 立即发送
12 在 450 秒内发送
22 在 900 秒内发送
磁贴 通知
1 立即发送
11 在 450 秒内发送
21 在 900 秒内发送
RAW 通知
3 立即发送
13 在 450 秒内发送
23 在 900 秒内发送
通知类型

要发送的推送通知的类型。
可能的选项为磁贴、Toast 和 Raw。
如果此标头不存在,则推送通知将被视为 Raw 通知。

格式:X-WindowsPhone-Target:NotificationTypeValue
其中NotificationTypeValue类型为STRING。

CallbackURI

当触发某个特定事件时将注册的回调消息发送到的通知通道 URI。
仅当在经过身份验证的 Web 服务中注册回调消息时才允许使用此自定义标头。

格式:X-CallbackURI:CallbackURIValue
其中CallbackURIValue类型为STRING。

推送内容格式:

Toast推送内容格式:
$msg =	"" .
				"" .
				"" .
				"$title" .
				"$message" .
				"" .
				"";

参数说明:
a)Text1标题。紧挨着应用程序图标之后显示的黑体字字符串。在 XML 架构中,该字符串定义为 Text1 属性。
b)Text2内容。紧挨着“标题”之后显示的非黑体字字符串。在 XML 架构中,该字符串定义为 Text2 属性。
c)Param参数。如果用户点按 Toast,则将参数值传递给您的应用程序,而不进行显示。该参数可以指示应用程序应该启动到的页面。该参数还包含传递到应用程序的名称-值对。在 XML 架构中,该字符串定义为 Param 属性。此参数只支持Windows Phone OS 7.1或更高版本的设备,若将具有此参数的通知发送到Windows Phone OS 7.0设备会导致错误,并且通道会被关闭。

可以显示的文本数量取决于在 Toast 消息中使用的字符以及“标题”(粗体)和“内容”(非粗体)的长度。如果只设置了一个“标题”,则可以显示大约 40 个字符,之后的字符将被截断。如果只设置了“内容”,则可以显示大约 47 个字符。如果一个 Toast 在“标题”和“内容”之间平均拆分,则可以显示大约 41 个字符。无法放在 Toast 上的任何文本都将被截断。

显示如图(Title对应Text1,Sub-title对应Text2)
Toast通知

磁贴推送内容格式:
$msg = 	"" .
				"" .
				"" .
				"$image_url" .
				"$count" .
				"$title" .
				"" .
				"";

参数说明:
1.正面磁贴

Title标题。指示应用程序标题的字符串。标题必须适合单行文本并且不应该比实际磁贴宽。标题中大约可以包含 15 个字符,多余部分将被截断。
BackgroundImage。显示在磁贴正面的图像。建议您在磁贴正面始终拥有背景图像。
Count计数(也称为徽章)。从 1 到 99 的整数值。如果未设置“计数”的值或者设置为 0,则不会在磁贴上显示圆形图像和值。

显示如图
正面磁贴

2.反面磁贴
以下参数只能推送到Windows Phone OS 7.1 或更高版本的设备,推送到Windows Phone OS 7.0版本的设备会导致错误,并且通道会被关闭.

BackTitle。显示在磁贴背面底部的字符串。BackTitle 必须适合单行文本并且不应该比实际磁贴宽。标题中大约可以包含 15 个字符,多余部分将被截断。
BackBackgroundImage。显示在磁贴背面的图像。
BackContent。显示在磁贴背面中心的字符串。磁贴中大约可以包含 40 个字符,多余部分将被截断。

显示如图
反面磁贴

RAW

直接将数据转换成二进制数据的字节数组,写入 HTTP Request Stream 即可。

iPhone推送内容分析见之前的文章iOS推送通知的格式说明

iOS推送通知的格式说明

最近在做手机推送方面的功能,特地整理了iOS推送通知的格式。

KeyValue TypeComment
alert string or dictionary 如果包含这个这个属性 iOS 将会显示一个标准的提示. 你可用指定一个字符串作为提醒或作为字典的值. 如果你指定了一个字符串, 它会变成有两个按钮的警报消息: 关闭和显示. 如果用户点击查看, 应用程序将会启动
另外, 你可以指定一个字典来作为提示的内容. 对于这类字典,请查看下表
badge number 这个数字将作为应用程序的的徽章图标显示. 如果此属性不存在, 任何当前显示的徽章号码将会被删除.
sound string 它是捆绑再应用程序的声音文件名. 这个声音文件播放声音警报. 如果这个声音文件不存在或指定默认值,这时会播放预设的警报音. 它的音频必须是兼容的系统数据格式之一; 详细信息,请阅读“Preparing Custom Alert Sounds”准备定义提示音.




KeyValue TypeComment
body string 提示信息.
action-loc-key string or null 查看按钮的文字.
iOS 用字符串作为键来获得当前本地化的字符串,并将其用于右边按钮的标题,代替了“view”. 如果字符串值为null,系统将显示一个简单的“确定”按钮,当点击时,将会简单的消除按钮.
访问 “Localized Formatted Strings” 获得更多消息.
loc-key string 本地提示消息的一个字符串KEY, 字符串KEY可以格式化这样%@ and %n$ 在loc-args指定参数变量.
访问 “Localized Formatted Strings” 可以获得更多信息.
loc-args array of strings loc-key里的变量对应的值.
访问 “Localized Formatted Strings” 可以获得更多信息.
launch-image string 应用程序中的一个图像文件. 当用户点击动作按钮或移动动作滑块,图片将会被显示出来. 如果这个属性没有指定, 系统会使用以前的图片,通过在应用程序的Info.plist键来使用图像识别, 或返回到默认的png文件.
这个属性再ios4.0才被添加的.

PHP的单例模式

单例模式,顾名思义强调的是单一,只有一个实例,而且自行实例化并向整个系统提供这个实例。

条件3点:
1、需要一个静态变量,保存类的唯一实例。
2、需要一个公共静态方法,返回唯一实例的一个引用。
3、构造函数(__construct)、克隆函数(__clone)私有化,从而防止外部程序 new 类,从而失去单例模式的意义。

这里说明一下第3点。
如果不声明私有的构造函数,那么可以通过new实例化类调用相应的方法。

class test{

    static private $_instance = null;

    static public function getInstance() {
        if (is_null(self::$_instance) || !isset(self::$_instance)) {
            self::$_instance = new self();
        }
        
        return self::$_instance;
    }
    
    public function testA() {
    
        echo 'test is done!';
    }
}

$a = new test;
$a->testA();

如果不声明私有的克隆函数,那么可以通过克隆一个类的示例来调用原类的方法。

class test{

    static private $_instance = null;

    static public function getInstance() {
        if (is_null(self::$_instance) || !isset(self::$_instance)) {
            self::$_instance = new self();
        }
        
        return self::$_instance;
    }
    
    public function testA() {
    
        echo 'test is done!';
    }
}

$a = test::getInstance();
$b = clone $a;
$b->testA();

优点:
1、节省系统资源,避免重复实例化,是一种“计划”生育。
2、避免大量的new 操作。例如,数据库应用。一个系统程序,会存在大量的数据库操作,如果使用单例模式,就可以避免大量new 操作。
3、如果系统中需要一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现。这个可以参看zend framework 的frontController部分。
4、便于调试,管理,因为所有代码 都集中在一个类里。我们可以在类中设置钩子,输出日志,从而避免 到处 var_dump,echo

缺点:
众所周知,php语言是一种解释型脚本语言,这种运行机制使得每个php页面被解释执行后,所有的相关资源都会被收回。也就是说,php在语言级别上没办法使某个对象常驻内存。
这与asp.net、java等编译型是不同的。然而php,所有的变量无论是全局变量还是静态变量,静态成员都是页面级的。
每次页面执行时,都会重新建立新的对象,都会在页面执行完毕后被清空。
这样似乎php单例模式没什么意义了,所以php的单例模式是针对单次页面级同时出现多个应用场景并需要共享同一对象资源时,是非常有意义的。

本文参考资料:http://blog.csdn.net/calllmq/article/details/7347736

PHPUnit+Selenium自动化测试过程中遇到的问题

最近在做自动化测试,前段捣鼓好了自动化测试环境,具体见

使用火狐下的Selenium扩展录制操作过程,然后导出成PHPUnit格式的测试用例文件,自己稍微修改,通过PHPUnit执行测试用例进行自动化测试。

整理一下修改导出的PHPUnit格式的测试用例文件时遇到的问题:

1.Selenium定位元素的时候支持Xpath。推荐使用火狐浏览器,可以很方便的获取某个元素的Xpath。不得不说,火狐浏览器真是开发人员的神器!!
安装firebug扩展后,查看某个元素,右键就可以复制Xpath了,如图。
firebug下获取Xpath
注意这里获取的Xpath都是通用的,而Chrome下的xpathOnClick扩展虽然也可以获取Xpath,但是它获取的都不是通用的,还需要自己再进行修改,所以推荐直接使用火狐。

另外推荐火狐下另外一款扩展——Xpath checker,可以直接获取Xpath,而且还可以验证你的Xpath是否正确。
在要查看Xpath的元素上右键,如图。
Xpath checker使用
验证Xpath是否正确,如图。
Xpath checker使用

这里获取的Xpath可能是类似下面的:

/html/body/div[6]/div[2]/div[2]/div[2]/div[3]/div[2]/table/tbody/tr/td[2]/dl/dt/a

Selenium要求Xpath以两个//开头,所以需要在上面的Xpath前面再加一个/。这点须注意,我就是因为这个捣鼓了快1个小时。

2.PHPUnit测试用例里的方法名必须是test****TestCase,****部分可以自定义,但是前后部分必须是test和TestCase,否则测试用例无法执行。
类似如图。
PHPUnit测试用例代码

最后上一下我自己的测试用例执行结果:
PHPUnit+Selenium执行情况

PHPUnit+Selenium执行情况

PHPUnit+Selenium执行情况

Ps:突然想到这货要是可以自动识别验证码,就完全可以搞成自动灌水机了啊!看我自己执行测试用例发的帖子数,这些都是它自己登录自己发出去的帖子。
PHPUnit+Selenium执行情况