当前位置: 编程技术>php
本页文章导读:
▪PHP生成excel时单元格内换行问题的解决方法
翻出来源码开了下,字符串中使用换行的方法为"Name:{$name}\nAddress:{$adress}\nCity:{$city}\nCountry:{$country}\n ......" 既然"\n"起不到换行的目的,修改成"\r\n"看看. 修改 =》 提交 =》测试 得出的结果.........
▪PHP下对字符串的递增运算代码
有同学问了一个问题: 代码如下: <?php for($i = 'A'; $i <= 'Z'; $i++) { echo $i; } //输出是啥? 输出是: 代码如下: ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARAS……. 为啥? 其实很简单, PHP的.........
▪深入理解PHP原理之异常机制
PHP的异常机制的原理是什么? 在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢? 让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:”对于下面的代码, onError明明.........
[1]PHP生成excel时单元格内换行问题的解决方法
来源: 互联网 发布时间: 2013-11-30
翻出来源码开了下,字符串中使用换行的方法为"Name:{$name}\nAddress:{$adress}\nCity:{$city}\nCountry:{$country}\n ......"
既然"\n"起不到换行的目的,修改成"\r\n"看看.
修改 =》 提交 =》测试
得出的结果还是 没有换行!!!!
难道是操作系统兼容问题??
直接使用php runtime 常量 PHP_EOL 替代 "\r\n"
修改 =》 提交 =》测试
得出的结果还是 没有换行!!!!
什么情况? 不可能这个也解决不了 操作系统兼容性问题的换行符号。
看看到底这个xls文件是怎么用php生成的。
看了下 生成excel的代码,Oh My Lady gaga,原来是用html的格式,只是文件后缀写成xls,既然html的格式,那么应该<br />可以起到换行的效果吧。
继续
修改 =》 提交 =》测试
结果是 可以换行了。 可喜可贺啊。问题终于解决了。
告诉老大问题解决,此时心中甚是喜悦啊。
过了一刻钟的样子,老大跑过来说:“换行效果的问题是解决了,但是你看下,数据不好复制了。”
。。。。
省略沟通N句。
把一个单元格的数据复制下,然后 粘贴到 word中。Oh My Lady gaga, 为啥会有border????
到底什么问题?? 使用\n、\r\n 把不能起到换行的相关,使用<br />把效果是有了,但是又出现了新问题。。。 到底如何是好?
没辙了,使用BAIDU google吧。
终于 黄天不负有心人,找到了问题的答案。
在<style></styel>标签中追加 CSS样式br {mso-data-placement:same-cell;}
终于 问题 完美解决。
原文如下:
将HTML文件的扩展名改为XLS后,用Excel打开,里边的每个<br />都会使后边的文字进入另一个单元格,要使<br />在一个单元格内起到换行的作用,可以在CSS里加入这一句:
br {mso-data-placement:same-cell;}
Excel就会把<br />解释成回车了。
在此多谢“卡卡西的真面目” 这位仁兄 把 知识分享出来。 要不然的话,不知道我还要折腾到什么时候才能解决!!
既然"\n"起不到换行的目的,修改成"\r\n"看看.
修改 =》 提交 =》测试
得出的结果还是 没有换行!!!!
难道是操作系统兼容问题??
直接使用php runtime 常量 PHP_EOL 替代 "\r\n"
修改 =》 提交 =》测试
得出的结果还是 没有换行!!!!
什么情况? 不可能这个也解决不了 操作系统兼容性问题的换行符号。
看看到底这个xls文件是怎么用php生成的。
看了下 生成excel的代码,Oh My Lady gaga,原来是用html的格式,只是文件后缀写成xls,既然html的格式,那么应该<br />可以起到换行的效果吧。
继续
修改 =》 提交 =》测试
结果是 可以换行了。 可喜可贺啊。问题终于解决了。
告诉老大问题解决,此时心中甚是喜悦啊。
过了一刻钟的样子,老大跑过来说:“换行效果的问题是解决了,但是你看下,数据不好复制了。”
。。。。
省略沟通N句。
把一个单元格的数据复制下,然后 粘贴到 word中。Oh My Lady gaga, 为啥会有border????
到底什么问题?? 使用\n、\r\n 把不能起到换行的相关,使用<br />把效果是有了,但是又出现了新问题。。。 到底如何是好?
没辙了,使用BAIDU google吧。
终于 黄天不负有心人,找到了问题的答案。
在<style></styel>标签中追加 CSS样式br {mso-data-placement:same-cell;}
终于 问题 完美解决。
原文如下:
代码如下:
将HTML文件的扩展名改为XLS后,用Excel打开,里边的每个<br />都会使后边的文字进入另一个单元格,要使<br />在一个单元格内起到换行的作用,可以在CSS里加入这一句:
br {mso-data-placement:same-cell;}
Excel就会把<br />解释成回车了。
在此多谢“卡卡西的真面目” 这位仁兄 把 知识分享出来。 要不然的话,不知道我还要折腾到什么时候才能解决!!
[2]PHP下对字符串的递增运算代码
来源: 互联网 发布时间: 2013-11-30
有同学问了一个问题:
<?php
for($i = 'A'; $i <= 'Z'; $i++) {
echo $i;
}
//输出是啥?
输出是:
ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARAS…….
为啥?
其实很简单, PHP的手册中也有说明, 只不过恐怕很多人不会一章一节的把手册仔细阅读一遍:
PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's. For example, in Perl ‘Z'+1 turns into ‘AA', while in C ‘Z'+1 turns into ‘[‘ ( ord(‘Z') == 90, ord(‘[‘) == 91 ). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported.
在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。例如,在 Perl 中 ‘Z'+1 将得到 ‘AA',而在 C 中,'Z'+1 将得到 ‘[‘(ord(‘Z') == 90,ord(‘[‘) == 91)。注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。
也就是说, 如果:
$name = "laruence";
++$name; //将会是"laruencf"
而:
$name = "laruence";
--$name; //没有影响, 还是"laruence"
所以, 这个问题的原因就是当$i = Z的时候, ++$i成了AA, 而字符串比较的话,
AA,BB,XX一直到YZ都是小于等于Z的… so..
作者: laruence
代码如下:
<?php
for($i = 'A'; $i <= 'Z'; $i++) {
echo $i;
}
//输出是啥?
输出是:
代码如下:
ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARAS…….
为啥?
其实很简单, PHP的手册中也有说明, 只不过恐怕很多人不会一章一节的把手册仔细阅读一遍:
代码如下:
PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's. For example, in Perl ‘Z'+1 turns into ‘AA', while in C ‘Z'+1 turns into ‘[‘ ( ord(‘Z') == 90, ord(‘[‘) == 91 ). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported.
在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。例如,在 Perl 中 ‘Z'+1 将得到 ‘AA',而在 C 中,'Z'+1 将得到 ‘[‘(ord(‘Z') == 90,ord(‘[‘) == 91)。注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。
也就是说, 如果:
代码如下:
$name = "laruence";
++$name; //将会是"laruencf"
而:
代码如下:
$name = "laruence";
--$name; //没有影响, 还是"laruence"
所以, 这个问题的原因就是当$i = Z的时候, ++$i成了AA, 而字符串比较的话,
AA,BB,XX一直到YZ都是小于等于Z的… so..
作者: laruence
[3]深入理解PHP原理之异常机制
来源: 互联网 发布时间: 2013-11-30
PHP的异常机制的原理是什么?
在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢?
让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:”对于下面的代码, onError明明执行了, 但是onException却没有执行, 为什么?”.
<?php
function onError($errCode, $errMesg, $errFile, $errLine) {
echo "Error Occurred\n";
throw new Exception($errMesg);
}
function onException($e) {
echo $e->getMessage();
}
set_error_handler("onError");
set_exception_handler("onException");
/* 我从不会以我的名字命名文件, 所以这个文件不存在 */
require("laruence.php");
运行结果:
Error Occurred
PHP Fatal error: main(): Failed opening required 'laruence.php
首先, 我们要知道, Require在包含一个找不到的问题的时候, 会前后抛出俩个错误,
WARNING : 在PHP试图打开这个文件的时候抛出.
E_COMPILE_ERROR : 从PHP打开文件的函数返回失败以后抛出
而我们知道, set_error_handler是不能捕获E_COMPILE_ERROR错误的:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
所以, 在onError中, 只能捕获到第一个WARNING错误, 而在onError中抛出的异常, 为什么没有被默认exception_handler捕获呢?
这就要说说PHP的异常机制了.
了解opcode(深入理解PHP原理之Opcodes的同学都知道, 在PHP5.3以前, 每一个可独立运行的op array(文件, 函数, 方法)的最后一条opcode都是ZEND_HANDLE_EXCEPTION, 而这个opcode是做什么用的呢?
原来在PHP中, 当有异常被throw的时候, 会跳到每一个op array的最后一行, 来执行这条ZEND_HANDLE_EXCEPTION, 伪码如下:
void on_throw_exception(zval *exception TSRMLS_DC) {
1. 判断是否已经有异常抛出
2. 记录exception
3. 记录下一条要执行的op line的序号
4. 下一条要执行的op line序号 = 当前op array的最后一条
}
恩, 就和改写ip寄存器一样, 改写下一条要执行的op line的序号, 就改变了程序的流向, 这样, 就会进入到了ZEND_HANDLE_EXCEPTION的处理逻辑中.
而在ZEND_HANDLE_EXCEPTION中, 会判断这个异常是否在try catch中,
如果是 则把下一条要执行的op line, 置为第一个catch的op line, 并继续执行.
如果不是 则销毁一些不需要的变量, 和opline, 然后直接结束执行过程
有的同学要问了:”那set_exception_handler设置的异常默认处理函数(user_exception_handler)什么时候起作用呢?”
恩, 是在执行完成退出执行LOOP以后才判断是否有默认异常处理函数, 如果有才调用:
//执行
zend_execute(EG(active_op_array) TSRMLS_CC);
if (EG(exception)) {
if (EG(user_exception_handler)) {
调用用户定义的默认异常处理函数
} else {
未捕获的异常
}
} else {
没有异常
}
destroy_op_array(EG(active_op_array) TSRMLS_CC);
efree(EG(active_op_array));
PHP异常流程
注: 图中有一处不严谨, 即在确定是否最后一个catch块的时候, 会同时判断(is_a), 如果是才进入最后一个catch块执行.
而PHP在遇到Fatal Error的时候, 会直接zend_bailout, 而zend_bailout会导致程序流程直接跳过上面代码段, 也可以理解为直接exit了(longjmp), 这就导致了user_exception_handler没有机会发生作用.
了解到这些, 我想文章开头的问题的为什么? 也就很清晰了吧?
最后, 关于ZEND_HANDLE_EXCEPTION, 也许有同学会有疑问: 如果是这样, 那为什么每一个可独立执行的op array最后都有这个ZEND_HANDLE_EXCEPTION呢? 最简单的, 如果一个函数中不会throw, 那么这个opcode 是明显不需要的啊? 嘿嘿, 你很聪明, PHP 5.3开始, 已经按照你的想法调整了.. 只有在throw时刻, 才会动态的生成ZEND_HANDLE_EXCEPTION opline.
PHP5 changelog:
Changed exception handling. Now each op_array doesn't contain ZEND_HANDLE_EXCEPTION opcode in the end. (Dmitry)
在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢?
让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:”对于下面的代码, onError明明执行了, 但是onException却没有执行, 为什么?”.
代码如下:
<?php
function onError($errCode, $errMesg, $errFile, $errLine) {
echo "Error Occurred\n";
throw new Exception($errMesg);
}
function onException($e) {
echo $e->getMessage();
}
set_error_handler("onError");
set_exception_handler("onException");
/* 我从不会以我的名字命名文件, 所以这个文件不存在 */
require("laruence.php");
运行结果:
代码如下:
Error Occurred
PHP Fatal error: main(): Failed opening required 'laruence.php
首先, 我们要知道, Require在包含一个找不到的问题的时候, 会前后抛出俩个错误,
代码如下:
WARNING : 在PHP试图打开这个文件的时候抛出.
E_COMPILE_ERROR : 从PHP打开文件的函数返回失败以后抛出
而我们知道, set_error_handler是不能捕获E_COMPILE_ERROR错误的:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
所以, 在onError中, 只能捕获到第一个WARNING错误, 而在onError中抛出的异常, 为什么没有被默认exception_handler捕获呢?
这就要说说PHP的异常机制了.
了解opcode(深入理解PHP原理之Opcodes的同学都知道, 在PHP5.3以前, 每一个可独立运行的op array(文件, 函数, 方法)的最后一条opcode都是ZEND_HANDLE_EXCEPTION, 而这个opcode是做什么用的呢?
原来在PHP中, 当有异常被throw的时候, 会跳到每一个op array的最后一行, 来执行这条ZEND_HANDLE_EXCEPTION, 伪码如下:
代码如下:
void on_throw_exception(zval *exception TSRMLS_DC) {
1. 判断是否已经有异常抛出
2. 记录exception
3. 记录下一条要执行的op line的序号
4. 下一条要执行的op line序号 = 当前op array的最后一条
}
恩, 就和改写ip寄存器一样, 改写下一条要执行的op line的序号, 就改变了程序的流向, 这样, 就会进入到了ZEND_HANDLE_EXCEPTION的处理逻辑中.
而在ZEND_HANDLE_EXCEPTION中, 会判断这个异常是否在try catch中,
代码如下:
如果是 则把下一条要执行的op line, 置为第一个catch的op line, 并继续执行.
如果不是 则销毁一些不需要的变量, 和opline, 然后直接结束执行过程
有的同学要问了:”那set_exception_handler设置的异常默认处理函数(user_exception_handler)什么时候起作用呢?”
恩, 是在执行完成退出执行LOOP以后才判断是否有默认异常处理函数, 如果有才调用:
代码如下:
//执行
zend_execute(EG(active_op_array) TSRMLS_CC);
if (EG(exception)) {
if (EG(user_exception_handler)) {
调用用户定义的默认异常处理函数
} else {
未捕获的异常
}
} else {
没有异常
}
destroy_op_array(EG(active_op_array) TSRMLS_CC);
efree(EG(active_op_array));
PHP异常流程
注: 图中有一处不严谨, 即在确定是否最后一个catch块的时候, 会同时判断(is_a), 如果是才进入最后一个catch块执行.
而PHP在遇到Fatal Error的时候, 会直接zend_bailout, 而zend_bailout会导致程序流程直接跳过上面代码段, 也可以理解为直接exit了(longjmp), 这就导致了user_exception_handler没有机会发生作用.
了解到这些, 我想文章开头的问题的为什么? 也就很清晰了吧?
最后, 关于ZEND_HANDLE_EXCEPTION, 也许有同学会有疑问: 如果是这样, 那为什么每一个可独立执行的op array最后都有这个ZEND_HANDLE_EXCEPTION呢? 最简单的, 如果一个函数中不会throw, 那么这个opcode 是明显不需要的啊? 嘿嘿, 你很聪明, PHP 5.3开始, 已经按照你的想法调整了.. 只有在throw时刻, 才会动态的生成ZEND_HANDLE_EXCEPTION opline.
PHP5 changelog:
Changed exception handling. Now each op_array doesn't contain ZEND_HANDLE_EXCEPTION opcode in the end. (Dmitry)
最新技术文章: