http://hi.baidu.com/netcoffeehuang/blog/item/97f570193d539a7ddab4bd9c.html
http://www.ibm.com/developerworks/cn/opensource/os-php-xdebug/
一:CTags PHP5 函数查找及一些快捷键介绍
ctags 常用快捷键 :
{ 转到上一个空行
} 转到下一个空行
gd 转到当前光标所指的局部变量的定义
* 转到当前光标所指的单词下一次出现的地方
# 转到当前光标所指的单词上一次出现的地方
tags内不包含调用点,只包含函数定义的位置信息,所以不能查找所有调用。
二:Grep用-P参数的Perl正则查找函数原型的使用示例:
这个在linux下使用shell命令:大写P是正则的意思,否则匹配会有问题,n是行号。
find . -name "*.php"|xargs grep -Pn 'setPlayCache\s*\('
实践查找smodifyData函数原型:
进一步过滤去掉jack备份目录,并只在models下找(因为有可能其它目录也有相同函数):
显示行数-i:
find . -name "*.php"|xargs grep -Pin "function\smodifyData\s\("|grep models|grep -v jack
./application/models/play.php:70: public function setPlayCache($cacheKey, $data = array())
实践如下:
例外情况,有时不是\s能查到的,是任何字符才能查,如下:
find . -name "*.php"|xargs grep -Pir ".*Token.*"
$app = new Token('user_token_'.$this->user_id);
$app = new Token('hostw');
——————————————————————————————————————————————
vim里查找函数原型,和平时查找一样的,只是多了个\s,(也不用像grep那样转意:
vi index.php 输入左斜杠开始查找:
查找某个文件里的函数原型:
cat session.php |grep -P function
查看被调用的位置,就需要使用cscope了
如果grep时出现下面问题,解决方法如下:
[root@iZ25dcp92ckZ]# grep -rinP "checkPass" ./
grep: this version of PCRE is compiled without UTF support
Linux 查看内存的插槽数,已经使用多少插槽。每条内存多大,已使用内存多大
# dmidecode|grep -P -A5 "Memory\s+Device"|grep Size|grep -v Range
查看内存支持的最大内存容量
# dmidecode|grep -P 'Maximum\s+Capacity'
查看内存的频率
dmidecode|grep -A16 "Memory Device"|grep 'Speed'
开始查询遇到这个错误:
grep: this version of PCRE is not compiled with PCRE_UTF8 support
看来是PCRE扩展没有开启支持UFT8格式,重新下载个新版http://iweb.dl.sourceforge.net/project/pcre/pcre/8.36/pcre-8.36.tar.gz 编译,参数./configure --enable-utf8。
装完后还是不行,因为grep也要重新编译。。。
好吧继续下grep:
http://ftp.gnu.org/gnu/grep/grep-2.21.tar.xz
来自:http://www.shentou.org/hacker/166.html
附录:
其实最简单的就是:把光标移动到某个元素上,CTRL+],就会跳转到对应的定义啦。CTRL+o可以回退到原来的地方。
Howto patch ctags 5.6 to work with php5 class member variable features (private, public, protected). ??
早些时候下载了 GVIM Taglist 插件,用来显示 PHP 文件的结构,Taglist 需要 Ctags 的支持,但是 Ctags 目前尚不支持 PHP5 的类限制符(Public/Protected/Private),所以无法识别类中的方法。问题暴露出来了,总会有人去摆平它的,经过一番搜索,找到了一个老外放出的支持 PHP5 的 Ctags Patch,但只能在 Linux 下面使用,Windows 的用户需要自己下载源码重新编译 ctags.exe 文件,所幸的是这个东东也有人编译好了,还是最新的 Ctags 5.6 版本。所以善用搜索,几乎没有解决不了的问题哈,呵呵 :)
Ctrl+]的返回应该是Ctrl+t
Ctrl-O是返回前一个打开的文件,所以看起来结果相同。
下载地址:windows版本的
http://untidy.net/blog/2006/10/04/ctags-php-5-support/
http://blog.chrisramsay.co.uk/2006/10/24/ctags-with-vim-for-php5/
安装位置如下:
cp ctags /usr/local/bin/ctags && chmod 755 /usr/local/bin/ctags
cp ./ctags.1 /usr/local/share/man/man1/ctags.1 && chmod 644 /usr/local/share/man/man1/ctags.1
[root@localhost ctags-5.8]# whereis ctags
ctags: /usr/bin/ctags /usr/local/bin/ctags
Linux 用如下方法:
One of the features I have missed since starting using Vim as my main source code editor is the ability to navigate a source file by its classes, properties and methods. I am aware of the existence of Ctags as a program for mapping source files and creating indexes accessible for use by text editors, but my experience has been up until recently that Ctags cannot correctly index PHP5 files - Ctags does not seem to understand the Private, Protected and Public precursors to the function arguments. However I have come across a patch - provided by Christian Stocker at bITFLUX that fixes this problem.
Patching and Installing Ctags
Christian says on his site that his patch works for Ctags 5.5.4 - I have tried it against version 5.6 and found no problems. Below is a brief run through of installing and patching Ctags on an Linux or Cygwin machine.
Firstly download and untar Ctags and Christian Stocker’s patch
# wget http://kent.dl.sourceforge.net/sourceforge/ctags/ctags-5.6.tar.gz
# tar -xvf ctags-5.6.tar.gz
# wget http://svn.bitflux.ch/repos/public/misc/ctags-php5.patch
# mv ctags-php5.patch ctags-5.6
Next, it’s time to apply the patch to the Ctags php.c file.
# cd ctags-5.6
# patch php.c ctags-php5.patch
Next, configure the build and make install. Note the optional --prefix="/" - this is because I ran this particular example in Cygwin.
# ./configure --prefix="/usr/local/ctags"
# make
# make install
# make clean
删除掉原来的不支持PHP的ctags,然后再做软链接到现在支持PHP的ctags:
rpm -ql ctags
/usr/bin/ctags
/usr/share/doc/ctags-5.8
/usr/share/doc/ctags-5.8/COPYING
/usr/share/doc/ctags-5.8/EXTENDING.html
/usr/share/doc/ctags-5.8/FAQ
/usr/share/doc/ctags-5.8/NEWS
/usr/share/doc/ctags-5.8/README
/usr/share/man/man1/ctags.1.gz
/usr/bin/ctags
If everything made ok, try running the following:
rpm -e ctags
替换原来的ctags。
cp /usr/local/bin/ctags /usr/bin
不用作软连接的办法:
vi /etc/profile 加上:
export PATH=/usr/local/ctags/bin/ctags:$PATH :
单独文件放profile.d文件夹里新建一文件,和上面一样的道理,在登录时会去刷这个文件夹:
cat /etc/profile.d/ctags.sh
export PATH=/usr/local/ctags/bin/ctags:$PATH
在vim里加载ctags:
ctags -R
在用-R直接生成的tags的时候,如果无关的文件太多,tags生成的会非常而且慢,比如cocos2d-x的项目。
解决的方法比较简单,参考了cscope生成 cscope.files的思路:
find . -name "*.h" -o -name "*.c" -o -name "*.cpp" -o -name "*.m" -o -name "*.mm" -o -name "*.java" -o -name "*.py" > src.files
ctags -R --c++-kinds=+px --fields=+iaS --extra=+q -L src.files
find . -name "*.h" -o -name "*.c" -o -name "*.cpp" -o -name "*.m" -o -name "*.mm" -o -name "*.java" -o -name "*.py" > src.files
ctags -R --c++-kinds=+px --fields=+iaS --extra=+q -L src.files
这样生成的速度就会快很多啦
自动加载ctags配置,vim 打开PHP文件后自动加载ctags,使用如下命令:
Set tags=tags的文件路径
Set tags=/data/htdocs/XXX.com/tags
vi ~/.vimrc //vim打开就加载tags。
set tags=/data/htdocs/XXX.com/tags;
https://jackxiang.com/post/1635/
之后,才是使用前面的快捷键。
方案2 (这个是对这个ctags作脚本替换,并没有直接像方案1这样编译进去,所以,这个方法不是太好,我没有试,再就是这个.ctags能不能自动运行都是个问题。)
1. $ vim ~/.ctags
增加
alias phptags='/usr/local/ctags/ctags --langmap=php:.engine.inc.module.theme.php --php-kinds=cdf --languages=php'
2. $ vim ~/.ctags
写入
--regex-php=/^[ \t]*[(private|public|static)( \t)]*function[ \t]+([A-Za-z0-9_]+)[ \t]*\(/\1/f, function, functions/
--regex-php=/^[ \t]*[(private|public|static)]+[ \t]+\$([A-Za-z0-9_]+)[ \t]*/\1/p, property, properties/
--regex-php=/^[ \t]*(const)[ \t]+([A-Za-z0-9_]+)[ \t]*/\2/d, const, constants/
3. $ phptags -R
方案二来自:http://web.hanzheng.info/lamp/tool-lamp/vim/vim-%E8%A7%A3%E5%86%B3ctags%E5%AF%B9php%E7%9A%84%E6%94%AF%E6%8C%81
# ctags --help
You’ll soon see that Ctags is a very powerful tool - there are many available arguments, though I’ll just use one of the two most commonly used commands here - the (-R) recursive command. There are several strategies for generating and using Ctags in projects, particularly when it comes to multi level directory hierarchies. You’ll find some help here on the Ctags Sourceforge FAQ here. I am using the ‘local tag file in each directory only for the source files in that directory’ method.
# cd /myprojects/project_a
# ctags -R
Once Ctags has finished generating the tags file, you are in business and ready to start editing in Vim. So fire up Vim and open a PHP file. To see what Ctags has generated for the file, type TlistToggle in command mode and hit CTRL + w twice to change focus to the Ctags window. You can then navigate up and down the tree and hit enter to go straight to that point in the source file.
说一下如何使用 Tab 键自动完成,按照习惯,Tab 键通常是用来缩进行的,如输入 4 个空格 如果要把 Tab 映射为自动完成,可能使用上稍微有点麻烦,下面会讲如何解决这个问题。
首先需要为 Vim 提供一个 PHP 的函数列表文件,这样 Vim 才能知道如何自动完成一个 PHP 函数。 函数列表不需要自己做,PHP 网站上有现成的,拿来用就可以了:
http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt
得到这个文件,直接拷贝到 Vim 目录中,比如根目录下面,然后在 vimrc 中加入如下代码, 告知 vim 在自动完成时,需要扫描这个文件来分析关键字。
"You can obtain the completion dictionary file from:
" http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt
set dictionary-=/etc/vim/funclist.txt dictionary+=/etc/vim/funclist.txt
"Use the dictionary completion
set complete-=k complete+=k
那么如何解决缩进的问题呢?我们肯定不愿意在映射另外一个键来做缩进用,感觉会很别扭。 下面的函数会解决这个问题。
"Auto completion using the TAB key
"This function determines, wether we are on
"the start of the line text(then tab indents)
"or if we want to try auto completion
function! InsertTabWrapper()
let col=col('.')-1
if !col || getline('.')[col-1] !~ '\k'
return "\"
else
return "\"
endif
endfunction
"Remap the tab key to select action with InsertTabWrapper
inoremap =InsertTabWrapper()
这个函数的作用是判断当前光标前的一个字符是否为一个 Keyword 字符(:help iskeyword),vim 中用 \k 表示, 这个字符的范围大约是所有非空白的可打印的字符,但除开某些特殊字符,比如 @ * " 等等。
于是效果就出来了,当前导字符为空白或者 @ * 等字符时,Tab 就映射为 成为缩进键。 否则就映射为 ,也就是 CTRL+N 调用自动完成功能。
大约就是这样...
首先需要为 Vim 提供一个 PHP 的函数列表文件,这样 Vim 才能知道如何自动完成一个 PHP 函数。 函数列表不需要自己做,PHP 网站上有现成的,拿来用就可以了:
http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt
得到这个文件,直接拷贝到 Vim 目录中,比如根目录下面,然后在 vimrc 中加入如下代码, 告知 vim 在自动完成时,需要扫描这个文件来分析关键字。
"You can obtain the completion dictionary file from:
" http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt
set dictionary-=/etc/vim/funclist.txt dictionary+=/etc/vim/funclist.txt
"Use the dictionary completion
set complete-=k complete+=k
那么如何解决缩进的问题呢?我们肯定不愿意在映射另外一个键来做缩进用,感觉会很别扭。 下面的函数会解决这个问题。
"Auto completion using the TAB key
"This function determines, wether we are on
"the start of the line text(then tab indents)
"or if we want to try auto completion
function! InsertTabWrapper()
let col=col('.')-1
if !col || getline('.')[col-1] !~ '\k'
return "\
else
return "\
endif
endfunction
"Remap the tab key to select action with InsertTabWrapper
inoremap
这个函数的作用是判断当前光标前的一个字符是否为一个 Keyword 字符(:help iskeyword),vim 中用 \k 表示, 这个字符的范围大约是所有非空白的可打印的字符,但除开某些特殊字符,比如 @ * " 等等。
于是效果就出来了,当前导字符为空白或者 @ * 等字符时,Tab 就映射为 成为缩进键。 否则就映射为 ,也就是 CTRL+N 调用自动完成功能。
大约就是这样...
好像很多编辑器里都有括号自动完成这样的功能,比如,输入左边括号"("后自动完成")",并把光标定位到两个括号中间,vim通过简单的键映射也可以做到.
以下是我在 O'Reilly Network 看到的一篇文章里学到的,把以下代码拷贝到.vimrc文件里
:inoremap ( ()
:inoremap )
:inoremap { {}
:inoremap }
:inoremap [ []
:inoremap ]
function ClosePair(char)
if getline('.')[col('.') - 1] == a:char
return "\
else
return a:char
endif
endf
echo dirname(__FILE__);
echo "<p>";
echo dirname(dirname(__FILE__));
echo "<p>";
echo dirname(dirname(__FILE__));
display:
E:\wwwroot\www\htdocs\5-5
E:\wwwroot\www\htdocs
使用范例:
本例返回字符串 $file 为 "/etc"。
<?
$path = "/etc/hostname";
$file = dirname($path);
?>
$path = "/etc/hostname";
$file = dirname($path);
?>
一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。
四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。
五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。
于是构造出如下PHP函数:
这个更全space的:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。
四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。
五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。
于是构造出如下PHP函数:
function getIp(){
if (getenv('HTTP_CLIENT_IP'))
{
$ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR'))
{
list($ip) = explode(',', getenv('HTTP_X_FORWARDED_FOR'));
} elseif (getenv('REMOTE_ADDR'))
{
$ip = getenv('REMOTE_ADDR');
}
else
{
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
if (getenv('HTTP_CLIENT_IP'))
{
$ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR'))
{
list($ip) = explode(',', getenv('HTTP_X_FORWARDED_FOR'));
} elseif (getenv('REMOTE_ADDR'))
{
$ip = getenv('REMOTE_ADDR');
}
else
{
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
这个更全space的:
static public function getIp() {
// Gets the default ip sent by the user
if (!empty($_SERVER['REMOTE_ADDR'])) {
$direct_ip = $_SERVER['REMOTE_ADDR'];
}
// Gets the proxy ip sent by the user
$proxy_ip = '';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else if (!empty($_SERVER['HTTP_X_FORWARDED'])) {
$proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
} else if (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
$proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
} else if (!empty($_SERVER['HTTP_FORWARDED'])) {
$proxy_ip = $_SERVER['HTTP_FORWARDED'];
} else if (!empty($_SERVER['HTTP_VIA'])) {
$proxy_ip = $_SERVER['HTTP_VIA'];
} else if (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
$proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
} else if (!empty($_SERVER['HTTP_COMING_FROM'])) {
$proxy_ip = $_SERVER['HTTP_COMING_FROM'];
}
// Returns the true IP if it has been found, else FALSE
if (empty($proxy_ip)) {
// True IP without proxy
return $direct_ip;
} else {
$is_ip = preg_match('|^([0-9]{1,3}\.){3,3}[0-9]{1,3}|', $proxy_ip, $regs);
if ($is_ip && (count($regs) > 0)) {
// True IP behind a proxy
return $regs[0];
} else {
// Can't define IP: there is a proxy but we don't have
// information about the true IP
return $direct_ip;
}
}
}
// Gets the default ip sent by the user
if (!empty($_SERVER['REMOTE_ADDR'])) {
$direct_ip = $_SERVER['REMOTE_ADDR'];
}
// Gets the proxy ip sent by the user
$proxy_ip = '';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else if (!empty($_SERVER['HTTP_X_FORWARDED'])) {
$proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
} else if (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
$proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
} else if (!empty($_SERVER['HTTP_FORWARDED'])) {
$proxy_ip = $_SERVER['HTTP_FORWARDED'];
} else if (!empty($_SERVER['HTTP_VIA'])) {
$proxy_ip = $_SERVER['HTTP_VIA'];
} else if (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
$proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
} else if (!empty($_SERVER['HTTP_COMING_FROM'])) {
$proxy_ip = $_SERVER['HTTP_COMING_FROM'];
}
// Returns the true IP if it has been found, else FALSE
if (empty($proxy_ip)) {
// True IP without proxy
return $direct_ip;
} else {
$is_ip = preg_match('|^([0-9]{1,3}\.){3,3}[0-9]{1,3}|', $proxy_ip, $regs);
if ($is_ip && (count($regs) > 0)) {
// True IP behind a proxy
return $regs[0];
} else {
// Can't define IP: there is a proxy but we don't have
// information about the true IP
return $direct_ip;
}
}
}
有时候做监控或者别的什么的需要发带附件的邮件,mail 命令不能直接这么做,好在多数系统都自带了 mutt ,这个工具可以做到。
echo "mail content" | mutt -s "subject" -a "/path/to/attachment" to@domain.com
今天用到了,搜了好一会才发现这个办法。这里笔记一下。
mutt 是一个很强大的字符界面的邮件终端,貌似好多牛人都用这个来收发邮件。
echo "mail content" | mutt -s "subject" -a "/path/to/attachment" to@domain.com
今天用到了,搜了好一会才发现这个办法。这里笔记一下。
mutt 是一个很强大的字符界面的邮件终端,貌似好多牛人都用这个来收发邮件。
<?php
$str="hallo world"; //比如这个是元算结果
$code= "print('\n$str\n');";//这个是保存在数据库内的php代码
echo "***";
echo($code);//打印组合后的命令,str字符串被替代了,形成一个完整的php命令,但并是不会执行
echo "###";
eval($code);//执行了这条命令
?>;
$str="hallo world"; //比如这个是元算结果
$code= "print('\n$str\n');";//这个是保存在数据库内的php代码
echo "***";
echo($code);//打印组合后的命令,str字符串被替代了,形成一个完整的php命令,但并是不会执行
echo "###";
eval($code);//执行了这条命令
?>;
eval这个函数很可能有漏洞,因为可以执行很多命令:如:net user 等,会导致注入漏洞等,黑客很有可能拿到服务器的密码,然后反解密,很是危险性,必须防范,在我们的开发中如发feed等可以通过先拼接好字符串,然后构造函数发送feed!
有个插件名字叫 Limit Posts Automatically,可以统一截断首页的文章输出。
最终被我找到的函数是 mb_strimwidth()。它能满足的需求有:正确截断,无乱码,每条截取内容的长度基本相等。
乱码问题解释和解决:
先简单介绍一下。mb_strimwidth() 会根据”宽度”来截取文字,全角字符宽度为2,半角字符为 1,只要我们将截断的宽度设置为偶数,那最后截断输出的内容一定不会有乱码。
在截断输出首页文章内容的问题上,我们还应该搭配 strip_tags() 来共同实现。strip_tags() 的作用是清除字符串内的 html 标签,放在这里就是清除输出的内容格式(包括清除图片)。既然目的是截取小段文字,自然也不需讲求格式。
废话打住,说”正题”:
请找到模板内 index.php 中的
将其替换为
post_content)), 0, 120,”……”); ?>
之后首页文章内容截断输出就实现了。更改截取字数请调整例子中的 “120″ 为你想要的数值,它后面的 “……” 是输出末尾的替换内容,款式参考我的首页。这六个点也算在 120 之内,占 6 个半角宽度。
如果有看我前面对 mb_strimwidth 的介绍,聪明人该知道怎么将他们用在 Wordpress 模板侧边栏,毕竟在 css3 普及之前,用 PHP 的截断方式肯定是最佳的侧边栏截断选择。
老大在邮件做如下汇总:
echo mb_strimwidth("一二三四五六七八九十一二", 0, 23, '...','utf-8');
会输出如下内容:一二三四五六七八九十...这是因为mb这个函数算长度,如果总字符串小于指定的长度,那就不用截取啦!我在你原
来的字符串上加了个”二”,就会截出你要的结果了!看来是我们对这个函数了解不够
啊!
最终被我找到的函数是 mb_strimwidth()。它能满足的需求有:正确截断,无乱码,每条截取内容的长度基本相等。
乱码问题解释和解决:
先简单介绍一下。mb_strimwidth() 会根据”宽度”来截取文字,全角字符宽度为2,半角字符为 1,只要我们将截断的宽度设置为偶数,那最后截断输出的内容一定不会有乱码。
在截断输出首页文章内容的问题上,我们还应该搭配 strip_tags() 来共同实现。strip_tags() 的作用是清除字符串内的 html 标签,放在这里就是清除输出的内容格式(包括清除图片)。既然目的是截取小段文字,自然也不需讲求格式。
废话打住,说”正题”:
请找到模板内 index.php 中的
将其替换为
post_content)), 0, 120,”……”); ?>
之后首页文章内容截断输出就实现了。更改截取字数请调整例子中的 “120″ 为你想要的数值,它后面的 “……” 是输出末尾的替换内容,款式参考我的首页。这六个点也算在 120 之内,占 6 个半角宽度。
如果有看我前面对 mb_strimwidth 的介绍,聪明人该知道怎么将他们用在 Wordpress 模板侧边栏,毕竟在 css3 普及之前,用 PHP 的截断方式肯定是最佳的侧边栏截断选择。
老大在邮件做如下汇总:
echo mb_strimwidth("一二三四五六七八九十一二", 0, 23, '...','utf-8');
会输出如下内容:一二三四五六七八九十...这是因为mb这个函数算长度,如果总字符串小于指定的长度,那就不用截取啦!我在你原
来的字符串上加了个”二”,就会截出你要的结果了!看来是我们对这个函数了解不够
啊!
开发代码结束或者基本结束后,往往由于前面时间紧张写的代码可能不符合公司的规范,所以需要对代码加以格式化,也方便阅读等等:
打开zend for eclipse6.1,当然是D版,然后选择以前开发的代码工程,然后,preferences-『窗口』-〉 『首选项』如图:
1.选择php的格式模板,如何缩进等,花括号如何摆放etc。。。
在工程上选择需要格式的几个php目录(同时选择php文件可能出不了source的菜单),用菜单source里面的format,即可格式化目录里面的php文件!
ctrl+shift+f对代码进行格式化阅读全文
打开zend for eclipse6.1,当然是D版,然后选择以前开发的代码工程,然后,preferences-『窗口』-〉 『首选项』如图:
1.选择php的格式模板,如何缩进等,花括号如何摆放etc。。。
在工程上选择需要格式的几个php目录(同时选择php文件可能出不了source的菜单),用菜单source里面的format,即可格式化目录里面的php文件!
ctrl+shift+f对代码进行格式化阅读全文
发现我的MYSQL无法建立innodb表了,显象是在Create Table 语句中指定了ENGINE=INNODB 但是表建完后发现有一个warning信息,使用show warnings \G查看发现,Mysql提示使用Myisam建立表。然后使用 Show Variables like '%innodb%' 查看发现have_innodb 的值为Disable这表明不能建立innodb表。
Step 1. Stop MySQL service
Step 2:打开my.ini 找到 skip-innodb 并在其前加'#'号
Step 3: Restart MySQL service
问题解决。
做记录的时候要修改为innodb来存储:
ALTER TABLE `ac_follow` ENGINE = INNODB
但是没有修改成功:
对比了一下:show variables;或者:Show Variables like '%innodb%'
发现:have_innodb | DISABLED
修改:have_innodb | YES
把table_type的默认值MYISAM改为INNODB:
[mysqld]
basedir=
datadir=
default-table-type=innodb
default-table-type=innodb 就是你所要加的..
即可!
啰嗦几句,如果你是默认在linux安装的包装的mysql或者apache,my.ini 和php.ini它的目录为:
默认:
httpd.conf 在/etc/httpd/conf
my.cnf 在/etc
php.ini 在/usr/local/lib
在Unix上,php.ini文件缺省放在/usr/local/lib上面,因为缺省的存放路径是 /lib,但是可以在编译的时候使用--with-config-file-path参数来修改php.ini的存放位置,例如你可以使用--with- config-file-path=/etc把它存放到/etc下面,然后可以从源码包中拷贝php.ini-dist到/etc/php.ini并修改使之满足需要。
Windows上面php.ini的缺省位置是windows系统目录,如果使用了Apache的话,那么将首先从 Apache的安装目录中查找 php.ini,例如:c:program filesapache groupapache,这样你可以在同一台机器上面为不同的Apache版本设置不同的php.ini文件。
Step 1. Stop MySQL service
Step 2:打开my.ini 找到 skip-innodb 并在其前加'#'号
Step 3: Restart MySQL service
问题解决。
做记录的时候要修改为innodb来存储:
ALTER TABLE `ac_follow` ENGINE = INNODB
但是没有修改成功:
对比了一下:show variables;或者:Show Variables like '%innodb%'
发现:have_innodb | DISABLED
修改:have_innodb | YES
把table_type的默认值MYISAM改为INNODB:
[mysqld]
basedir=
datadir=
default-table-type=innodb
default-table-type=innodb 就是你所要加的..
即可!
啰嗦几句,如果你是默认在linux安装的包装的mysql或者apache,my.ini 和php.ini它的目录为:
默认:
httpd.conf 在/etc/httpd/conf
my.cnf 在/etc
php.ini 在/usr/local/lib
在Unix上,php.ini文件缺省放在/usr/local/lib上面,因为缺省的存放路径是
Windows上面php.ini的缺省位置是windows系统目录,如果使用了Apache的话,那么将首先从 Apache的安装目录中查找 php.ini,例如:c:program filesapache groupapache,这样你可以在同一台机器上面为不同的Apache版本设置不同的php.ini文件。
一行解决写入日志:
一行完成Curl的POST输出:
临时调试:
路径变量:
在调试上传文件时,如苹果Android等(这一行来自PHP高级编程:岁月如哥【俗称:膘哥】(191295**)它提供的。2013-04-11 09:58 AM ):
后记:
岁月如哥(191295**) 15:20:48
你要看一下ios下。如果图片过大。或者。。。有些异常情况发生的时候。
$_FILES都为空的。
这些我们都遇到过
收到的内容全部为空。而且会导致其他所有的变量都为空
回忆未来-向东-Jàck(3726476**) 15:23:51
那有可能是这个问题,我用上面这个直接打Post有值,呵呵。
膘哥说得对,是可能图片太大了。
调试:
就能看到调试信息。
看了一下phpcms的源码:
function cache_write($file, $string, $type = 'array')
{
if(is_array($string))
{
$type = strtolower($type);
if($type == 'array')
{
$string = "<?php\n return ".var_export($string,TRUE).";\n?>";
}
elseif($type == 'constant')
{
$data='';
foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".
addslashes($value)."');\n";
$string = "<?php\n".$data."\n?>";
}
}
$strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string,FILE_APPEND); //最好加上FILE_APPEND,否则tail -f出现
tail: /tmp/friendviews.txt: file truncated 参看:http://www.xiangdong.org/blog/post/1614/
chmod(PHPCMS_CACHEDIR.$file, 0777);
return $strlen;
}
可以看到
var_export
解释下
var_export
(PHP 4 >= 4.2.0, PHP 5)
var_export -- 输出或返回一个变量的字符串表示
描述
mixed var_export ( mixed expression [, bool return])
此函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码。
您可以通过将函数的第二个参数设置为 TRUE ,从而返回变量的表示。
应用场景:
假如我们看到一个数组是多维的,其实通过serialize之后写入文件 读出来之后unserialize也可以,但我们只是想看看数组里面是什么,但又不想打印到页面上。
实例:
结果:
array (
0 => 1,
1 => 2,
2 =>
array (
0 => 'a',
1 => 'b',
2 => 'c',
),
)
http_build_query 把数组整成一个get串:
一行完成Curl的POST输出:
临时调试:
路径变量:
在调试上传文件时,如苹果Android等(这一行来自PHP高级编程:岁月如哥【俗称:膘哥】(191295**)它提供的。2013-04-11 09:58 AM ):
后记:
岁月如哥(191295**) 15:20:48
你要看一下ios下。如果图片过大。或者。。。有些异常情况发生的时候。
$_FILES都为空的。
这些我们都遇到过
收到的内容全部为空。而且会导致其他所有的变量都为空
回忆未来-向东-Jàck(3726476**) 15:23:51
那有可能是这个问题,我用上面这个直接打Post有值,呵呵。
膘哥说得对,是可能图片太大了。
调试:
就能看到调试信息。
看了一下phpcms的源码:
function cache_write($file, $string, $type = 'array')
{
if(is_array($string))
{
$type = strtolower($type);
if($type == 'array')
{
$string = "<?php\n return ".var_export($string,TRUE).";\n?>";
}
elseif($type == 'constant')
{
$data='';
foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".
addslashes($value)."');\n";
$string = "<?php\n".$data."\n?>";
}
}
$strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string,FILE_APPEND); //最好加上FILE_APPEND,否则tail -f出现
tail: /tmp/friendviews.txt: file truncated 参看:http://www.xiangdong.org/blog/post/1614/
chmod(PHPCMS_CACHEDIR.$file, 0777);
return $strlen;
}
可以看到
var_export
解释下
var_export
(PHP 4 >= 4.2.0, PHP 5)
var_export -- 输出或返回一个变量的字符串表示
描述
mixed var_export ( mixed expression [, bool return])
此函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码。
您可以通过将函数的第二个参数设置为 TRUE ,从而返回变量的表示。
应用场景:
假如我们看到一个数组是多维的,其实通过serialize之后写入文件 读出来之后unserialize也可以,但我们只是想看看数组里面是什么,但又不想打印到页面上。
实例:
<?php
$a = array ( 1 , 2 , array ( "a" , "b" , "c" ));
$file_string = var_export ( $a,True);
var_dump($file_string);
file_put_contents("/tmp/friendviews.txt",$file_string,FILE_APPEND);
exit;
?>
$a = array ( 1 , 2 , array ( "a" , "b" , "c" ));
$file_string = var_export ( $a,True);
var_dump($file_string);
file_put_contents("/tmp/friendviews.txt",$file_string,FILE_APPEND);
exit;
?>
tail -f /tmp/friendviews.txt
结果:
array (
0 => 1,
1 => 2,
2 =>
array (
0 => 'a',
1 => 'b',
2 => 'c',
),
)
http_build_query 把数组整成一个get串:
file_get_contents.php: Post数据
接收数据:
request_post_result.php 接收经过Post的数据:
更加简洁:
<?php
function Post($url, $post = null)
{
$context = array();
if (is_array($post))
{
ksort($post);
$context['http'] = array
(
'method' => 'POST',
'content' => http_build_query($post, '', '&'),
);
}
return file_get_contents($url, false, stream_context_create($context));
}
$data = array
(
'name' => 'test',
'email' => 'test@gmail.com',
'submit' => 'submit',
);
echo Post('http://localhost/5-5/request_post_result.php', $data);
?>
function Post($url, $post = null)
{
$context = array();
if (is_array($post))
{
ksort($post);
$context['http'] = array
(
'method' => 'POST',
'content' => http_build_query($post, '', '&'),
);
}
return file_get_contents($url, false, stream_context_create($context));
}
$data = array
(
'name' => 'test',
'email' => 'test@gmail.com',
'submit' => 'submit',
);
echo Post('http://localhost/5-5/request_post_result.php', $data);
?>
接收数据:
request_post_result.php 接收经过Post的数据:
<?php
echo $_POST['name'];
echo $_POST['email'];
echo $_POST['submit'];
echo "fdfd";
?>
echo $_POST['name'];
echo $_POST['email'];
echo $_POST['submit'];
echo "fdfd";
?>
更加简洁:
参看:http://www.phpe.net/articles/83.shtml
<?PHP
/*
CREATE TABLE `category` (
`categoryID` int(10) unsigned NOT NULL auto_increment,
`categoryParentID` int(10) unsigned NOT NULL default '0',
`categoryName` varchar(50) NOT NULL default '',
KEY `cate_id` (`categoryID`)
) TYPE=MyISAM AUTO_INCREMENT=11 ;
#
# 导出表中的数据 `category`
#
INSERT INTO `category` VALUES (1, 0, '一级类别1');
INSERT INTO `category` VALUES (2, 1, '二级类别1');
INSERT INTO `category` VALUES (3, 1, '二级类别2');
INSERT INTO `category` VALUES (4, 1, '二级类别3');
INSERT INTO `category` VALUES (5, 2, '三级类别21');
INSERT INTO `category` VALUES (6, 2, '三级类别22');
INSERT INTO `category` VALUES (7, 2, '三级类别23');
INSERT INTO `category` VALUES (8, 3, 'rfwesdfsd');
INSERT INTO `category` VALUES (9, 4, '54534w43');
INSERT INTO `category` VALUES (10, 5, '66666');
有问题请不要问我就行了。其他OK。欢迎修改使用。这是简单的。
*/
mysql_connect( "localhost", 'root', '' );
mysql_select_db( "test3" );
$cate_table = "category";
function _GetCategory( $category_id = 0, $depth = 1 )
{
global $cate_table;
$sql = "SELECT * FROM $cate_table ORDER BY categoryID DESC";
$result = mysql_query( $sql );
while ( $row = mysql_fetch_array( $result ) )
{
$array[$row[categoryParentID]][$row[categoryID]]
= array(
'id' => $row[categoryID],
'parent' => $row[categoryParentID],
'name' => $row[categoryName]
);
}
if ( !isset( $array[$category_id] ) )
{
return "";
}
foreach( $array[$category_id] AS $key => $category )
{
echo " <OPTION VALUE=".$category['id']." ";
if ( $category['parent'] == 0 )
{
echo " class='main' ";
}
if ( $depth > 1 )
{
echo ">" . str_repeat( "--", $depth - 1 ) . " " . $category['name'] . "</option>n";
}
else
{
echo ">" . $category['name'] . "</option>\n";
}
_GetCategory( $key, $depth + 1 );
}
unset( $array[$category_id] );
}
?>
<select name="categoryID">
<option selected value="">-------------</option>
<?=_GetCategory();?>
</select>
/*
CREATE TABLE `category` (
`categoryID` int(10) unsigned NOT NULL auto_increment,
`categoryParentID` int(10) unsigned NOT NULL default '0',
`categoryName` varchar(50) NOT NULL default '',
KEY `cate_id` (`categoryID`)
) TYPE=MyISAM AUTO_INCREMENT=11 ;
#
# 导出表中的数据 `category`
#
INSERT INTO `category` VALUES (1, 0, '一级类别1');
INSERT INTO `category` VALUES (2, 1, '二级类别1');
INSERT INTO `category` VALUES (3, 1, '二级类别2');
INSERT INTO `category` VALUES (4, 1, '二级类别3');
INSERT INTO `category` VALUES (5, 2, '三级类别21');
INSERT INTO `category` VALUES (6, 2, '三级类别22');
INSERT INTO `category` VALUES (7, 2, '三级类别23');
INSERT INTO `category` VALUES (8, 3, 'rfwesdfsd');
INSERT INTO `category` VALUES (9, 4, '54534w43');
INSERT INTO `category` VALUES (10, 5, '66666');
有问题请不要问我就行了。其他OK。欢迎修改使用。这是简单的。
*/
mysql_connect( "localhost", 'root', '' );
mysql_select_db( "test3" );
$cate_table = "category";
function _GetCategory( $category_id = 0, $depth = 1 )
{
global $cate_table;
$sql = "SELECT * FROM $cate_table ORDER BY categoryID DESC";
$result = mysql_query( $sql );
while ( $row = mysql_fetch_array( $result ) )
{
$array[$row[categoryParentID]][$row[categoryID]]
= array(
'id' => $row[categoryID],
'parent' => $row[categoryParentID],
'name' => $row[categoryName]
);
}
if ( !isset( $array[$category_id] ) )
{
return "";
}
foreach( $array[$category_id] AS $key => $category )
{
echo " <OPTION VALUE=".$category['id']." ";
if ( $category['parent'] == 0 )
{
echo " class='main' ";
}
if ( $depth > 1 )
{
echo ">" . str_repeat( "--", $depth - 1 ) . " " . $category['name'] . "</option>n";
}
else
{
echo ">" . $category['name'] . "</option>\n";
}
_GetCategory( $key, $depth + 1 );
}
unset( $array[$category_id] );
}
?>
<select name="categoryID">
<option selected value="">-------------</option>
<?=_GetCategory();?>
</select>
计算机的串口不能用,怎么与目标板的串口连接呢?
windows下可以用USB转串口线实现,在google上搜索了一下,linux下更简单,连驱动都免装!
测试环境:redhat linux fedora core 4
总结如下:
1. 检查是否存在设备/dev/ttyUSB0,如果没有就建立一个:
mknod /dev/ttyUSB0 c 188 0
以下推理未测试:
如果有多个USB口,可以类推,建立/dev/ttyUSB[1-n],注意从设备号要累加,如:mknod /dev/ttyUSB[1-n] c 188 [1-n]
2. 启动minicom, 设置串口设备为 /dev/ttyUSB0, 再设置波特率/数据位/停止位,保存为缺省配置df1
3. 重启minicom, 复位目标板,看是否有打印信息?
如果没有请确认:a)USB/串口线没问题,b)确认你使用的USB口是第一个(一个个的试吧,一般电脑不会标示出来)
windows下可以用USB转串口线实现,在google上搜索了一下,linux下更简单,连驱动都免装!
测试环境:redhat linux fedora core 4
总结如下:
1. 检查是否存在设备/dev/ttyUSB0,如果没有就建立一个:
mknod /dev/ttyUSB0 c 188 0
以下推理未测试:
如果有多个USB口,可以类推,建立/dev/ttyUSB[1-n],注意从设备号要累加,如:mknod /dev/ttyUSB[1-n] c 188 [1-n]
2. 启动minicom, 设置串口设备为 /dev/ttyUSB0, 再设置波特率/数据位/停止位,保存为缺省配置df1
3. 重启minicom, 复位目标板,看是否有打印信息?
如果没有请确认:a)USB/串口线没问题,b)确认你使用的USB口是第一个(一个个的试吧,一般电脑不会标示出来)
先看这篇文章:
http://www.chinaunix.net/jh/27/771726.html
引用:
接上篇:
[硬件 通讯]PHP在RS232串口通讯协议的应用演示[测试环境PHP5.1.4]
http://bbs.chinaunix.net/viewthread.php?tid=771726
引用:
1. 代码之中的: 请修改为你自己的实际测试文件
$handle = fopen ("E:\\RS232\\TEST\\WAPMMonitor.exe", "rb");
$handle = fopen("E:\\RS232\\TEST\\S_WAPMMonitor.exe", 'w');
2. 进过测试,可以传送文本文件、二进制文件。
3. HQB232协议修改,原01、02、03指令,修改为chr(0).chr(1)、chr(0).chr(2)、chr(0).chr(3)来构成
http://blog.sina.com.cn/s/blog_44c07fb301000449.html
http://www.chinaunix.net/jh/27/771726.html
引用:
接上篇:
[硬件 通讯]PHP在RS232串口通讯协议的应用演示[测试环境PHP5.1.4]
http://bbs.chinaunix.net/viewthread.php?tid=771726
<?php
// --------------------------------------------------------------------------
// File name : RS232_Server.php
// Description : RS232演示上位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)
//
// 程序简介:
// 本程序与RS232_Client构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
// C->S 01 //请求通讯
// S->C 02 //响应通讯
// C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
// C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
// HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
// 请求和响应,数据帧的结构。
// 演示过程为通讯的请求和响应,文件的发送(数据帧), 通讯的结束
// 数据帧的结构为当前的当前数据的长度,数据的HEX字符串(两位补足)
//
// 欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM1: baud=9600 data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM1:', O_RDWR);
if(!$fd)
{
die("Error when open COM1");
}
$ff = dio_stat($fd);print_r($ff);
echo "HQB232 SERVER is listenning on COM1\n";
/// read
$len = 2;
$t=0;while (($t++)<1000)
{
$data = dio_read($fd, $len);
if ($data) {
if($data==chr(0).chr(1)){
echo "S_RECV:01\n";
echo "S_SEND:02\n";
dio_write($fd,chr(0).chr(2));
break;
}
}
}
$handle = fopen("E:\\RS232\\TEST\\S_WAPMMonitor.exe", 'w');
/// read
$len = 2;
$t=0;while ($handle && ($t++)<1000)
{
$len = 2;
$data = dio_read($fd, $len);
if($data==chr(0).chr(3)){
echo "S_RECV:03\n";
break;
}
elseif ($data) {
$len = hexdec($data);
if($len>0)
{
$data = dio_read($fd, $len);
if($data){
fwrite($handle, str2hex($data));
echo "S_RECV:($len) ".microtime()."\n";
}
}
}
}
fclose($handle);
dio_close($fd);
function str2hex($string)
{
$str = '';
for($i=0; $i<strlen($string); $i+=2){
$str .= chr(hexdec(substr($string,$i,2)));
}
return $str;
}
?>
// --------------------------------------------------------------------------
// File name : RS232_Server.php
// Description : RS232演示上位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)
//
// 程序简介:
// 本程序与RS232_Client构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
// C->S 01 //请求通讯
// S->C 02 //响应通讯
// C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
// C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
// HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
// 请求和响应,数据帧的结构。
// 演示过程为通讯的请求和响应,文件的发送(数据帧), 通讯的结束
// 数据帧的结构为当前的当前数据的长度,数据的HEX字符串(两位补足)
//
// 欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM1: baud=9600 data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM1:', O_RDWR);
if(!$fd)
{
die("Error when open COM1");
}
$ff = dio_stat($fd);print_r($ff);
echo "HQB232 SERVER is listenning on COM1\n";
/// read
$len = 2;
$t=0;while (($t++)<1000)
{
$data = dio_read($fd, $len);
if ($data) {
if($data==chr(0).chr(1)){
echo "S_RECV:01\n";
echo "S_SEND:02\n";
dio_write($fd,chr(0).chr(2));
break;
}
}
}
$handle = fopen("E:\\RS232\\TEST\\S_WAPMMonitor.exe", 'w');
/// read
$len = 2;
$t=0;while ($handle && ($t++)<1000)
{
$len = 2;
$data = dio_read($fd, $len);
if($data==chr(0).chr(3)){
echo "S_RECV:03\n";
break;
}
elseif ($data) {
$len = hexdec($data);
if($len>0)
{
$data = dio_read($fd, $len);
if($data){
fwrite($handle, str2hex($data));
echo "S_RECV:($len) ".microtime()."\n";
}
}
}
}
fclose($handle);
dio_close($fd);
function str2hex($string)
{
$str = '';
for($i=0; $i<strlen($string); $i+=2){
$str .= chr(hexdec(substr($string,$i,2)));
}
return $str;
}
?>
<?php
// --------------------------------------------------------------------------
// File name : RS232_Client.php
// Description : RS232演示下位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)
//
// 程序简介:
// 本程序与RS232_Server构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
// C->S 01 //请求通讯
// S->C 02 //响应通讯
// C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
// C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
// HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
// 请求和响应,数据帧的结构。
// 演示过程为通讯的请求和响应,文件的发送(数据帧), 通讯的结束
// 数据帧的结构为当前的当前数据的长度,数据的HEX字符串(两位补足)
//
// 欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM2: baud=9600 data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM2:', O_RDWR);
if(!$fd)
{
die("Error when open COM2");
}
$ff = dio_stat($fd);print_r($ff);
echo "HQB232 CLIENT is start on COM2\n";
dio_write($fd,chr(0).chr(1));echo "C_SEND:01\n";
$len = 2;
$t=0;while(($t++)<1000)
{
$data = dio_read($fd, $len);
if($data==chr(0).chr(2)){
echo "C_RECV:02\n";
break;
}
}
/*
$len = 2;
$t=0;while(($t++)<10)
{
$sdata = sprintf("%03d",$t) . "=" . microtime() . " (" . randomkeys(rand(0,35)) . ")";
$slen = strlen($sdata);
$stxlen = sprintf("%02d",$slen);
dio_write($fd,"$stxlen");
dio_write($fd,"$sdata");echo "C_SEND:($stxlen)$sdata\n";
//sleep(1);
}
*/
$handle = fopen ("E:\\RS232\\TEST\\WAPMMonitor.exe", "rb");
$data = "";
while ($handle && !feof($handle)) {
$sdata = fread($handle, 127);
$sdata = hex2str($sdata);
$slen = strlen($sdata);
$stxlen = sprintf("%02X",$slen);
dio_write($fd,"$stxlen");
dio_write($fd,"$sdata");echo "C_SEND:($slen) ".microtime()."\n";
usleep(300);
}
fclose($handle);
dio_write($fd,chr(0).chr(3));echo "C_SEND:03\n";
dio_close($fd);
function randomkeys($length)
{
$pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
for($i=0;$i<$length;$i++)
{
$key .= $pattern{rand(0,35)};
}
return $key;
}
function hex2str($hexstring)
{
$str = '';
for($i=0; $i<strlen($hexstring); $i++){
$str .= sprintf("%02X",ord(substr($hexstring,$i,1)));
}
return $str;
}
?>
// --------------------------------------------------------------------------
// File name : RS232_Client.php
// Description : RS232演示下位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)
//
// 程序简介:
// 本程序与RS232_Server构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
// C->S 01 //请求通讯
// S->C 02 //响应通讯
// C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
// C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
// HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
// 请求和响应,数据帧的结构。
// 演示过程为通讯的请求和响应,文件的发送(数据帧), 通讯的结束
// 数据帧的结构为当前的当前数据的长度,数据的HEX字符串(两位补足)
//
// 欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM2: baud=9600 data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM2:', O_RDWR);
if(!$fd)
{
die("Error when open COM2");
}
$ff = dio_stat($fd);print_r($ff);
echo "HQB232 CLIENT is start on COM2\n";
dio_write($fd,chr(0).chr(1));echo "C_SEND:01\n";
$len = 2;
$t=0;while(($t++)<1000)
{
$data = dio_read($fd, $len);
if($data==chr(0).chr(2)){
echo "C_RECV:02\n";
break;
}
}
/*
$len = 2;
$t=0;while(($t++)<10)
{
$sdata = sprintf("%03d",$t) . "=" . microtime() . " (" . randomkeys(rand(0,35)) . ")";
$slen = strlen($sdata);
$stxlen = sprintf("%02d",$slen);
dio_write($fd,"$stxlen");
dio_write($fd,"$sdata");echo "C_SEND:($stxlen)$sdata\n";
//sleep(1);
}
*/
$handle = fopen ("E:\\RS232\\TEST\\WAPMMonitor.exe", "rb");
$data = "";
while ($handle && !feof($handle)) {
$sdata = fread($handle, 127);
$sdata = hex2str($sdata);
$slen = strlen($sdata);
$stxlen = sprintf("%02X",$slen);
dio_write($fd,"$stxlen");
dio_write($fd,"$sdata");echo "C_SEND:($slen) ".microtime()."\n";
usleep(300);
}
fclose($handle);
dio_write($fd,chr(0).chr(3));echo "C_SEND:03\n";
dio_close($fd);
function randomkeys($length)
{
$pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
for($i=0;$i<$length;$i++)
{
$key .= $pattern{rand(0,35)};
}
return $key;
}
function hex2str($hexstring)
{
$str = '';
for($i=0; $i<strlen($hexstring); $i++){
$str .= sprintf("%02X",ord(substr($hexstring,$i,1)));
}
return $str;
}
?>
引用:
1. 代码之中的: 请修改为你自己的实际测试文件
$handle = fopen ("E:\\RS232\\TEST\\WAPMMonitor.exe", "rb");
$handle = fopen("E:\\RS232\\TEST\\S_WAPMMonitor.exe", 'w');
2. 进过测试,可以传送文本文件、二进制文件。
3. HQB232协议修改,原01、02、03指令,修改为chr(0).chr(1)、chr(0).chr(2)、chr(0).chr(3)来构成
http://blog.sina.com.cn/s/blog_44c07fb301000449.html