自己开发了一款批量截图软件,用来对一组url批量截图。当web项目修改后,运行软件,重新截图一遍,查看是否有样式错乱。使用aau开发(http://www.aau.cn),在此特别推荐一下aau,一款国人研发的开发语言。
webmonitor源码地址:git://gitcafe.com/lcc/WebMonitor.git
webmonitor项目页面:https://gitcafe.com/lcc/WebMonitor
说明:1. git获取项目源代码 2. 从www.aau.cn上下载aau开发工具,用开发工具打开项目点击“运行”试用程序,或者点击“发布”生成应用程序。
使用截图:
创建项目
添加url
截的图片
又折腾了下Widget,纪录下遇到的两个小问题。
1. Layout中嵌入Widget,Widget未显示声明NOLAYOUT时,出现循环调用。
例:Lib/Tpl/_layout.html
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>这是layout</h1> <div> {__CONTENT__} </div> <div> {:W('Test')} </div> </body> </html>
Lib/Widget/Test/test.html
<ul> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> </ul>
这个时候,编译出来的Widget模板大概是这样
<?php if (!defined('THINK_PATH')) exit();?><!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>这是layout</h1> <div> <ul> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> <li><a href="javascript:;">这是Widget中的内容</a></li> </ul> </div> <div> <?php echo W('Test');?> </div> </body> </html>
Widget模板编译的时候被填充在了Layout的{__CONTENT__}中,下面W('test')的Widget调用依然存在。于是发生死循环没有报错页面一片空白,逐行调试了好久才找到问题。
解决方法:在 Lib/Widget/Test/test.html 开头添加一行{__NOLAYOUT__}
2. Widget的调用方式和传参。
我参考的是官方3.1.2的手册,手册上的示例是{:W('ShowComment')},大意是调用ShowComment得到返回的内容。在 Action 中使用 $widgetContent = W('ShowComment'); $this->assign('widgetContent',$widgetContent);但是$widgetContent的内容没有出现在模板变量{$widgetContent}出现的位置,查看函数时才看到W函数在默认情况下是echo出widget的内容。模板中正确的调法是{~W('ShowComment')},如果只是要取到Widget的内容应该使用W('ShowComment',array(),true);。
ThinkPHP新版的模板引擎添加了layout试用了下layout功能还是蛮强大的,但还是用法还不太灵活需要在配置文件中手动指定。自己用Behavior做了一个小功能来扩展layout,在Action类中指定$layout属性的值即可自动启用layout,也可以在单个Action方法中设置layout的值,设置为空值时不启用layout。
1. 创建ActionEx
文件:Lib/Model/ActionEx.class.php
<?php class ActionEx extends Action { public $layout; public $_runViewAssist; // 初始化动作绑定 public function _initialize() { ActionEx::action($this); add_tag_behavior('view_begin','ViewAssist'); } // 暂存action static public $_action; // 获取action static function action(&$action = false) { if ($action) { self::$_action = $action; } return self::$_action; } } ?>
2. 配置自动加载路径
在Conf/config.php中添加 'APP_AUTOLOAD_PATH' => '@.Model', 将Model添加到自动加载路径。
3. 添加Behavior
Lib/Behavior/ViewAssistBehavior.class.php
<?php class ViewAssistBehavior extends Behavior { protected $options = array(); public function run(&$params) { $act = ActionEx::action(); if (!$act->_runViewAssist) { $act->_runViewAssist = true; if ($act->layout) { C('LAYOUT_ON', 1); C('LAYOUT_NAME', $act->layout); // var_dump($act->layout);exit; } } } } ?>
4. 测试Layout
Lib/Action/TestAction.class.php
<?php class TestAction extends ActionEx { public $layout = '_layout'; public function index() { $this->display(); } public function test2() { // 禁用layout $this->layout = ''; $this->display(); } } ?>
Tpl/_layout.html
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>这是layout</h1> <div> {__CONTENT__} </div> </body> </html>
Tpl/Test/index.html
<h3>这是action中的内容</h3>
Tpl/Test/test2.html
<h3>test2</h3>
分别访问localhost/Test/index和localhost/Test/test2可以看到启用layout和未启用layout界面。
附:
文件目录
| | |~Common/ | | |~Conf/ | | | `-config.php | | |~Lang/ | | |~Lib/ | | | |~Action/ | | | | |-IndexAction.class.php | | | | `-TestAction.class.php | | | |~Behavior/ | | | | `-ViewAssistBehavior.class.php | | | |~Model/ | | | | `-ActionEx.class.php | | | `~Widget/ | | |+Runtime/ | | |~Tpl/ | | | |~Test/ | | | | |-index.html | | | | `-test2.html | | | `-_layout.html | | `-index.php
启用Layout和禁用Layout的截图
相关链接
ThinkPHP官网:http://www.thinkphp.cn/
有一个小需求,将一个目录包括子目录中的coffee文件批量转换到另一个指定的目录中,同时保挂子目录的结构。改了一个类似的Makefile。发一下备忘:
coffeeBaseDir=coffee/ coffeeDir=$(abspath $(coffeeBaseDir)) jsBaseDir=js/ jsDir=$(abspath $(jsBaseDir)) jsFile=$(shell find $(coffeeBaseDir) -type f -name *.coffee | sed 's@^$(coffeeBaseDir)@$(jsDir)/@g' | sed 's@\.coffee$$@\.js@g') jsDeploy: $(jsFile) $(jsDir)/%.js: $(coffeeDir)/%.coffee @mkdir -p `sed 's@/[^/]\+$$@/@g' <<< '$@'` coffee -bp $< > $@ test: @echo $(jsFile) clean: @rm js -fr @echo 'clean success!'
测试结果:
>find coffee -type f coffee/abc.coffee/3.coffee coffee/abc.coffee/1.coffee coffee/abc.coffee/2.coffee coffee/p1/3.coffee coffee/p1/1.coffee coffee/p1/2.coffee coffee/p2/3.coffee coffee/p2/1.coffee coffee/p2/2.coffee coffee/p3/3.coffee coffee/p3/1.coffee coffee/p3/2.coffee >find js -type f js/abc.coffee/2.js js/abc.coffee/1.js js/abc.coffee/3.js js/p1/2.js js/p1/1.js js/p1/3.js js/p2/2.js js/p2/1.js js/p2/3.js js/p3/2.js js/p3/1.js js/p3/3.js
在nginx官网看到有ngx_http_empty_gif_module这个模块,可以默认输出一个空白的gif,某个png透明的插件要用到这种透明的gif文件,简单看了下,配置方法很简单:
最开始我本地总是提示File not found.针对php框架的rewrite将这个请求重定向到了php请求,在rewrite最开始添加了一行 rewrite ^/_\.gif$ /_.gif break; 将文件重定向一次OK了
参考链接:
ngx_http_empty_gif_module: http://nginx.org/en/docs/http/ngx_http_empty_gif_module.html
更新说明:
2013-05-27 上传到gitcafe上面拖管 https://gitcafe.com/lcc/somecode/tree/master/jsdraw
写了一段生成象素点来绘制5边形的代码。用到了 Bresenham斜线画法、三角函数等知识。代码如下:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>JS绘制五边形</title> <style type="text/css"> .paper { width: 600px; height: 300px; border-color: #E0E0E0; border: 1px solid #DDD; position: relative; } .point { width: 1px; height: 1px; position: absolute; overflow: hidden; display: block; zoom: 1; } .red { background-color: red; } </style> <script type="text/javascript"> // 画斜线 function drawLine(point1, point2) { var point, pointElem, paper; pointElem = document.createElement('div'); if ('className' in pointElem) { pointElem.className = 'point red'; } else { pointElem.setAttribute('class', 'point red'); } paper = document.getElementById('paper'); var xLen = Math.abs(point2[0] - point1[0]); var yLen = Math.abs(point2[1] - point1[1]); var x, y, cx, cy, tox, toy, rate, rateVal, isAdd = true; // 从x轴遍历 if (xLen >= yLen) { if (point1[0] > point2[0]) { point1 = [point2, point2=point1][0]; } if (point1[1] > point2[1]) { isAdd = false; } x = cx = point1[0]; y = cy = point1[1]; tox = point2[0]; toy = point2[1]; rateVal = rate = parseInt( (yLen / xLen) * 1000) for (var i=x; i<tox; i++) { cx = i; point = pointElem.cloneNode(); paper.appendChild(point); point.style.left = cx + 'px'; point.style.top = cy + 'px'; rateVal += rate if (rateVal >= 1000) { cy += isAdd ? 1 : -1 rateVal -= 1000; } } } // 从y轴遍历 else { if (point1[1] > point2[1]) { point1 = [point2, point2=point1][0]; } if (point1[0] > point2[0]) { isAdd = false; } x = cx = point1[0]; y = cy = point1[1]; tox = point2[0]; toy = point2[1]; rateVal = rate = parseInt( (xLen / yLen) * 1000) for (var i=y; i<toy; i++) { cy = i; point = pointElem.cloneNode(); paper.appendChild(point); point.style.left = cx + 'px'; point.style.top = cy + 'px'; point = null rateVal += rate if (rateVal >= 1000) { cx += isAdd ? 1 : -1 rateVal -= 1000; } } } // 补点 if (cx != tox || cy != toy) { point = pointElem.cloneNode(); paper.appendChild(point); point.setAttribute('style', 'left:' + tox + 'px; top:' + toy + 'px'); point = null } pointElem = null; } // 获取点信息 function getPointInfo(R, dot) { var A = 360 / 5 var sinLen = Math.sin(A / 180 * Math.PI) * R var cosLen = Math.cos(A / 180 * Math.PI) * R sinLen = Math.round(sinLen) cosLen = Math.round(cosLen) var point1 = [dot[0], dot[1] - R] var point2 = [dot[0] + sinLen, dot[1]- cosLen] var point5 = [dot[0] - sinLen, dot[1] - cosLen] var A2 = (180 - A) / 2 sinLen = Math.sin(A2 / 180 * Math.PI) * R cosLen = Math.cos(A2 / 180 * Math.PI) * R sinLen = Math.round(sinLen) cosLen = Math.round(cosLen) var point3 = [dot[0] + cosLen, dot[1] + sinLen] var point4 = [dot[0] - cosLen, dot[1] + sinLen] return [point1, point2, point3, point4, point5]; } // 画点 function drawShape(type, R, dot) { var pointInfo = getPointInfo(R, dot) var point1 = pointInfo[0]; var point2 = pointInfo[1]; var point3 = pointInfo[2]; var point4 = pointInfo[3]; var point5 = pointInfo[4]; // 五边形 if (type == 1) { drawLine(point1, point2); drawLine(point2, point3); drawLine(point3, point4); drawLine(point4, point5); drawLine(point5, point1); } // 五角星 else if (type == 2){ drawLine(point1, point3); drawLine(point3, point5); drawLine(point5, point2); drawLine(point2, point4); drawLine(point1, point4); } } window.onload = function () { drawShape(1, 100, [150, 150]) drawShape(2, 100, [450, 150]) } </script> </head> <body> <div id="paper" class="paper"></div> </body> </html>
效果图:
经常折腾系统,来回切换或更换系统。官方的安装程序每次都要重新安装npm包比较麻烦。折腾了下,下载二进制文件,配置环境变量来安装nodejs。
1、下载nodejs
http://nodejs.org/dist/v0.10.7/node.exe 下载的文件放到D:\node目录下
2、下载npm
http://nodejs.org/dist/npm/npm-1.2.22.zip 将压缩包中的 npm.cmd node_modules 解压到D:\node目录下。注意是.zip格式的,不是.tgz格式的,两个包里面的内容不同。
3、设置环境变量
新建2个环境变量
NODE_HOME 值 D:\node
NODE_PATH 值 %NODE_HOME%\node_modules
在PATH后面追加 ;%NODE_HOME%
4、打开cmd,输入npm ls -g,这时应该能打印出包的信息,说明安装成功。
之前在网上找nginx配置PATH_INFO的方法,有一种是将PATH_INFO的值指定为$fastcgi_script_name,在php.ini中设置cgi.fix_pathinfo的值为1,前天在使用某款依赖PATH_INFO的框架时,果断被坑。将入口文件改为请求 http://localhost/index-dev.php时,PATH_INFO的值为 index-dev.php,框架将index-dev框架识别为controller报错。
附可用的配置方法:
set $path_info ""; set $real_script_name $fastcgi_script_name; if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") { set $real_script_name $1; set $path_info $2; } fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_NAME $real_script_name;
几种配置方案PATH_INFO值的对比:
配置类型 | 请求地址 | PATH_INFO | PHP_SELF | SCRIPT_NAME | 说明 |
Apache | /test.php | 无 | /test.php | /test.php | Apache的值为参考 |
/test.php/abc/123 | /abc/123 | /test.php/abc/123 | /test.php | Apache的值为参考 | |
nginx设置PATH_INFO 和SCRIPT_NAME |
/test.php | no value | /test.php | /test.php | 正常 |
/test.php/abc/123 | /abc/123 | /test.php/abc/123 | /test.php | 正常 | |
nginx设置PATH_INFO的值为 $fastcgi_script_name |
/test.php | /test.php | /test.php/test.php | /test.php |
PATH_INFO异常 PHP_SELF异常 |
/test.php/abc/123 | /abc/123 | /test.php/abc/123 | /test.php | PHP_SELF异常 |
另外:网上所提的 cgi.fix_pathinfo 打开时的露洞,已修补。cgi.fix_pathinfo的值设为0时,请求/test.php/abc/123的地址时,会报 Access denied. 的错误。
看到ThinkPHP发布了3.1.3版本,下载了一个创建项目玩玩。中间还遇到些小问题,记录一下。
1.下载解压缩TP
unzip ThinkPHP3.1.3_Full.zip -d /www/lib/
2.创建项目文件
cd /www/cms/tp
vim index.php
<?php define('APP_DEBUG', 1); require '../../lib/ThinkPHP/ThinkPHP.php';
3.修改权限
chmod 775 . -R
4.浏览器访问,基本上会出现如下错误
无法加载模块:index.php
错误位置
FILE: /data/www/lib/ThinkPHP/Common/functions.php LINE: 112
5.编辑配置文件
vim Conf/config.php
<?php return array( //'配置项'=>'配置值' 'URL_HTML_SUFFIX' => '', 'URL_CASE_INSENSITIVE' => 1, ); ?>
至此大功告成
附本人nginx host配置
# tp.cms.com server { listen 80; root /www/cms/tp; index index.html index.htm index.php index-dev.php; server_name .tp.cms.com; location ~* \.php { fastcgi_pass 127.0.0.1:9000; #fastcgi_pass unix:/tmp/nginx_sockets_php5-fpm.sock; fastcgi_index index.php; include fastcgi.conf; set $path_info ""; set $real_script_name $fastcgi_script_name; if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") { set $real_script_name $1; set $path_info $2; } fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_NAME $real_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } if (!-e $request_filename) { rewrite ^(.*)$ /index.php$1 break; } }
更新记录:
2015-12-28:修改nginx配置的错误
工作中用makefile执行打包、压缩、转换等功能,一个需求涉及到多层相对路径嵌套,于是想到将相对路径转换为绝对路径。百度谷歌数遍,找到一曲径通幽的方法。
PUBLICDIR = $(shell cd ../public; pwd)
*2012年11月16日更新
经依云大大提点,又上网搜索了一下Makefile相关函数。Makefile自带有两个函数可以得到绝对路径。
1. realpath 函数获取文件名序列中存在的文件和目录的真实路径,会判断文件和目录是否存在,如果不存在,则返回空。
2. abspath 函数获取文件名序列中存在的文件和目录的真实路径,函数不会检查文件或者目录是否存在。
示例:
PUBLICDIR = $(abspath ../public; pwd)
经本人测试,realpath abspath 能跨过软链接,获取文件的真实路径。
例如:
ln -s /usr/local/www /www
Makefile:
WWWDIR = $(abspath /www)
test:
echo $(WWWDIR) #output /usr/local/www
make test #output /usr/local/www