Submitted by gouki on 2010, February 23, 9:01 AM
以下内容均来自老王。说实话,simplexml的这些问题我以前遇到过,而且还是非常强烈的遇到了。
那时候是08年的事了,项目中与SOAP在交互,返回的都是XML,所以就直接采用了simplexml_load_string了。这时候就会遇到这种问题,比如我拉一个列表,但会有三种情况:1、没数据,2、1条数据,3、正常数据
1、没数据的时候,返回一个空的simplexml Object,
2、一条数据的时候,返回的也是一个simplexml Object,结果集成了这个object的元素
3、数据列表,这时候返回的却是一个Array,每一个元素是simplexml Object,等同于2。
后来我是没办法,就多写了一个函数判断,如果是object,并且不为空,直接把object强制转为array,因为,如果是空的simplexml Object,强制转的话,还是Object,转不了。。。
当时还有一个可恨的事情,我以前可能介绍过,xml在返回的时候,他的形式可能是这样的<test-name>gouki</test-name>,在返回这样的形式时,生成object时,却是test_name,在没有print_r出来时,我死活搞不定。。。后来才发现这个问题,郁闷啊
好了,说了半天,该说说老王的内容了:
这个问题遇到好几次了,今天翻看以前代码的时候看到,便记下来,先用一段代码重现一下问题:
PHP代码
- <pre>
- <?php
- $string = <<<EOF
- <data>
- <foo><bar>hello</bar></foo>
- <foo><bar>world</bar></foo>
- </data>
- EOF;
-
- $data = simplexml_load_string($string);
-
- print_r($data);
- print_r($data->foo);
- ?>
- </pre>
乍一看,结果很让人费解:
XML/HTML代码
- SimpleXMLElement Object
- (
- [foo] => Array
- (
- [0] => SimpleXMLElement Object
- (
- [bar] => hello
- )
- [1] => SimpleXMLElement Object
- (
- [bar] => world
- )
- )
- )
- SimpleXMLElement Object
- (
- [bar] => hello
- )
明明print_r显示foo是一个有两个bar元素的数组,但是最后却仅仅显示了一个bar元素!
原因其实很简单,在如上所示simplexml_load_string的结果里,foo并不是数组,而是一个迭代对象!
可以这样确认:
PHP代码
- foreach ($data->foo as $v) print_r($v);
- foreach ($data->children() as $v) print_r($v);
看来,print_r或者var_dump之类的表象并不完全可信,自己多留心吧。
原文来自:http://hi.baidu.com/thinkinginlamp/blog/item/9dbb15ce7a621632b700c86a.html
Tags: simplexml, 老王
PHP | 评论:1
| 阅读:39549
Submitted by gouki on 2010, February 21, 2:15 PM
前段时间有人问,如何统计自己的项目一共写了多少行代码,当时我说的是,遍历目录,然后用files函数读取每个要统计的文件【根据后缀名过滤】,并去掉空行,最后就把数字累加起来就可以了。
后来,他是google到一个专门统计代码的程序后搞定了。
刚才,看到cnitblog,有人这样写道:
XML/HTML代码
- find . -name "*.代码文件后缀" | xargs wc -l
当然,这是在linux下面。。如果有SVN,还需要加上:
XML/HTML代码
- $find . -name "*.代码文件后缀" | grep -v "./svn" | xargs wc -l
一切都是这么的自然。。。
linux下面的方法来自:http://www.cnblogs.com/maczpc/archive/2010/01/28/1658371.html
PHP | 评论:0
| 阅读:23237
Submitted by gouki on 2010, February 21, 1:30 PM
不知道你是否注意过,在firefox或者Chrome下面,即使没有定义input type=submit,只要点击任何一个button,都能触发form 的submit事件,这是为什么呢?
看看这篇文章吧,介绍的有点详细,把它留下来是因为我一向属于知其然不知其所以然,只知道问题所在,和如何解决,从来不深究它的内涵,这也是我为什么水平上不去的原因。。。所以,不要学我,还是看完这篇文章吧。。。虽然不一定详细,但毕竟知其一部分所以然了。
原文来自:不同浏 览器对回车提交表单的处理办法
内容如下:
在浏览器中填写表单的时,可以直接在“文本框”中敲击“Enter”来提交表单,很是方便。条件是:
1、<form>属性的“action”字段必填;
2、有一个type="submit"的“input”。
- 在Chrome和Safari下 满足第一条即可。(注释1)
所以,如果要控制提交行为的话(比如,提交前检查必填项是否已填),可以在type="submit"的“input”后添加 Javascript“onXXX(比如onClick)”事件。而如果需要用异步交互来检测相关字段,则无效了。因为return false是作为onreadystate=的子函数,并不能控制全局。这时就需要用到<form>的 “onsubmit”属性(注释2)。比如:
HTML
<form name="form1" id="form1" action="act.php" method="post" onsubmit="myfn();return false;">
- myfn()是自己定义的函数:无论通过什么办法 (比如敲击“enter”或点击type="submit"(而不是type="button")的“input”按钮)提交,都会触发这个这个函数。于 是,大可不必再在type="submit"的“input”后添加Javascript事件“onXXX”了。直接在“onsubmit”中控制,更直 观与统一,除非有意控制提交方式(是onClick还是什么)。
- return false位于末尾,表示不提交本表单。提交表单的字句document.form1.submit()可以作为myfn()的一个选择条件的分支。
总结:
这样,<form>有“action”和“onsubmit”属性,有type="submit"的“input”的提交按钮后, 就可以在任何浏览器下(不行吗?请给我反馈)实现使用“Enter”键和鼠标都可以对表单的相关字段进行异步(Ajax)和同步(单纯的 Javascript)检查并予以提交。
其他:
1、如果使用type="button"来异步检测相关字段呢?
这样,这个“input”必须得有一个事件触发器。在IE和FF下,无法直接在文本框中按下“Enter”来提交表单。如果要的话,需要使用额 外的函数来监听用户按下了什么,给出一个怎样的反映(注释3)。更糟糕的是,在Ch和Sa下,会忽略是否有type="submit"按钮,而直接根据 “action”属性来提交表单,如此以来,便无法实现预期的检测,可能还有更麻烦的后果。
2、如果不写“action”属性,直接异步提交表单呢?
这样,通过异步的方式提交表单,而不仅仅是检测,这个属性则没有必要。而且还是多余。假如这样能提供更好的用户体验,何乐而不为呢?呵呵。
【参考】
1 在IE8,FF,Ch中测试有效。Opera和Sa没有测试。参考了这篇文章(http://tieba.baidu.com/f?kz=669494938)
2 这篇文章(http://blog.csdn.net/xiewhenwe/archive/2009/11/08/4785469.aspx) 给了我借鉴
3 参考我以前的文章(http://www.cnblogs.com/lamper/archive/2010/02/06/1665117.html)
Tags: form, firefox, chrome, ie, submit
PHP | 评论:0
| 阅读:30583
Submitted by gouki on 2010, February 9, 4:51 PM
小记录,一般情况而言,默认安装好的lamp中,时间都是标准GMT时间,基本上,我们中国时间都应该是+8才对,但很多人往往不设置。
因此,为了时间正确,建议你还是设置一下默认时区,否则出现这8小时的误差也很郁闷的。
那么如何知道自己的时区是否正确呢?在不知道一些系统函数的情况下,直接输出 date('Y-m-d H:i:s', now()) ,就可以了解了。。
那么,我在知道这样的问题后,怎么能够知道当前设定的时区是哪里呢?这时可以通过:date_default_timezone_get()函数来获取,理所当然,设置时区就是date_default_timezone_set()了。
手册上也说明,在PHP 5.1之后,如果时区不正确,那每次在调用Date或者time函数时,都会有一个warning 或者 notice出现:
XML/HTML代码
- Note: Since PHP 5.1.0 (when the date/time functions were rewritten), every call to a date/time function will generate a E_NOTICE if the timezone isn't valid, and/or a E_STRICT message if using the system settings or the TZ environment variable.
当然,如果你觉得这样设置很麻烦,你可以更改php.ini文件中的 ;date.timezone = ,添加自己需要的时区,例如 date.timezone = Asia/Chongqing,然后重启服务器就可以了。PHP支持的 timezone 的字符串在手册中能够查到。
手册中的:Appendix J. List of Supported Timezones,可以查看所有支持的时区。
Note: The latest version of the timezone database can be installed via PECL's timezonedb. For Windows users, a pre-compiled DLL can be downloaded from the PECL4Win site: php_timezonedb.dll.
Tags: 时区
PHP | 评论:0
| 阅读:18629
Submitted by gouki on 2010, February 6, 11:05 PM
关于飞信,我上次写过学着写PHP飞信,然而今天晚上我把上文中测试的内容重现时却发现,现实有点残酷。我用curl的时候,速度居然没有fsocketopen快?我于是多次测试,然而,我却得到了一些令人沮丧的结果
【$postData,$postLength,都不提供。。。】
1、curl,利用curl来post
平均【大约 1.8~1.9秒】
- $ch = curl_init();
- $chOptions = array(
- CURLOPT_URL => "http://nav.fetion.com.cn/nav/getsystemconfig.aspx",
- CURLOPT_HTTP_VERSION => 'HTTP/1.0',
- CURLOPT_USERAGENT => sprintf('IIC2.0/pc %s' , self::FETION_CLIENT_VERSION),
- CURLOPT_ENCODING => 'gzip,deflate',
- CURLOPT_HTTPHEADER => array('Content-Type: text/xml; charset=utf-8'),
- CURLOPT_POST => 1,
- CURLOPT_POSTFIELDS => $postData ,
- CURLOPT_RETURNTRANSFER => 1,
- CURLOPT_HEADER => 0
- );
- curl_setopt_array($ch, $chOptions);
- $res = curl_exec($ch);
2、fsocketopen,同样POST数据
平均【大约 0.8~0.9秒】
- $headers=<<<eot
- POST /nav/getsystemconfig.aspx HTTP/1.0
- User-Agent: IIC2.0/pc 3.1.0480
- Accept-Encoding: deflate, gzip
- Host: nav.fetion.com.cn:80
- Content-Length: {$postLength}
-
- {$postData}
- eot;
- fwrite($fp,$headers);
- $received=fread($fp,1024);
- fclose($fp);
3、stream,利用文件流
平均【大约 1.3~1.4秒】
- $opts = array (
- 'http' => array (
- 'method' => 'POST',
- 'header'=> "Content-type: application/x-www-form-urlencoded" .
- "Content-Length: " . $postLength . "",
- 'content' => $postData
- ),
- );
- $context = stream_context_create($opts);
-
- $fp = fopen('http://nav.fetion.com.cn/nav/getsystemconfig.aspx','r',false,$context);
- if($fp){
- $received = fgets($fp, 512); //在这里我用了三种测试,fgets,fread,stream_get_contents
- fclose($fp);
- }
在这里我用了两种方式,一种是file_get_contents还有一种是fopen,file_get_contents的方法被我注释了。。。
在这三种中,我发现真的只有fsocketopen后然后fread是最快的。
真让我沮丧。。因为第三种方法中file_get_contens也可以指定读取的长度。但PHPRPC作者andot却认为,file_get_contents把头已经读回来了。我想,file_get_contents其实已经把数据读回来了,虽然是指定了长度,但其实只是读回来后再截取的。
唉。看来,不得不用fsocketopen了。。不知道除此之外有没有什么好办法。
PHP | 评论:0
| 阅读:19722