“最近在做一个“评诗网”,guwen.wobu2.com。 去年年中测试爬虫时抓的数据,近期代码写得少,拿来练手保持节奏。不觉得这玩意儿能赚到钱,能做出点别处没有的功能,方便有需要的人就够了。运营一个微信号“问世间是否此山最高”,每日一首情诗情话。蛋疼的朋友可以加 most_favourite”
搜索引擎看不到微博(@Dlad)的推介,在这里做个入口。
虽然不对盈利有期待,但是搜都搜不到就太过分了。
一个诗文检索网站
http://guwen.wobu2.com
身不饥寒,天未曾负我
“最近在做一个“评诗网”,guwen.wobu2.com。 去年年中测试爬虫时抓的数据,近期代码写得少,拿来练手保持节奏。不觉得这玩意儿能赚到钱,能做出点别处没有的功能,方便有需要的人就够了。运营一个微信号“问世间是否此山最高”,每日一首情诗情话。蛋疼的朋友可以加 most_favourite”
搜索引擎看不到微博(@Dlad)的推介,在这里做个入口。
虽然不对盈利有期待,但是搜都搜不到就太过分了。
一个诗文检索网站
http://guwen.wobu2.com
……
“可是还有一个人,列文,我认为他才是《安娜卡列琳娜》里真正的主角,他爱上了ketty, 遭到拒绝,但是他没有成为无病呻吟的人,又是忧伤,又是惆怅,又是悲悯,好像这世界上只有他一个失恋似的,甚至还会有人逢人就讲自己失恋的故事,像钱钟书写的”把他们的伤心立刻像叫花子的烂腿,血淋淋的地公开展览,博人怜悯,或者时过境迁,像战士的金疮旧癍,脱衣指示,使人惊佩 “(人民文学出版社《围城》106页)。列文回到他的农场,跟庄家人一起干活,他思考,写农业改革计划,他在爱情失败后,仍旧让他的人生丰富多彩,充满意 义和快乐。没有爱情的生活似乎不是很精彩,但也不至于黯淡无光。Ketty 对沃伦斯基的爱情遭到了拒绝,病倒了,到了乡下,时隔了1年左右列文和Ketty 再次相遇,相谈非常和谐。关键是列文依旧爱着Ketty. 然后在一个非常合适的场合,列文在桌上写”你的拒绝仅限于当时,还是永远”… Ketty 默默得看着列文… 这样的一对眼神直接把他们送进了教堂。这是我最最喜欢的一段关于爱情的描写。没有出轨,没有婚外恋,没有谴责,没有嫉妒,只有祝福,来自天上和地上的。”
看起来似乎很坚硬,其实一碰就碎了。
出冷汗,坐立不安。
无法违心的说热爱挫折。
但是挫折的确使人成熟,变的冰冷,增长器量。
生存压力之后,这是我唯一知道的有效动力。
踏实,专注,我又可以做到了。
知道是collation的问题,不想逐表修改,又没有好办法。
寻求redmine区域配置而不得,最终找到方法将所有表设定为 CHARSET=utf8。
参考这位同胞的方法:凍仁的筆記
导出表结构:
mysqldump –user=root -p redmine_default > redmine_default.sql
vim批量替换:
:%s/latin1/utf8/g
导入表结构:
mysql -uroot -p redmine_default < redmine_default.sql
PS:
前两天写接口collation默认latin,手动一个一个改成了utf8_general_ci.
心想应该写个脚本做这件事,只想了导出表名、批量生成sql一条路。
上面这个方法既直观也很方便,记一笔。
=============续:默认中文数据乱码=============
症状:过滤器下,第二列可选项乱码。角色中文名乱码。
涉及表trackers, roles, enumerations等。
redmine官方安装文档 中
第六步建立表结构,无法设定编码。(设定成功的兄弟请纠正)
第七步导入默认数据,可以通过REDMINE_LANG参数设定编码
RAILS_ENV=production REDMINE_LANG=zh rake redmine:load_default_data
接到任务为公司股东做个企业站。
日方站做得很好,心说争口气,让这些只接触过外包公司的传统行业见识下现代互联网。
商量好了流程,搭了框架Git,绷紧神经准备干一票呢。今天突然被叫停,非叫用个现成的改一下。
就这么几个页面,功能交叉不多,改cms未必有重头写来的快。达到高标准反而要做更多工作。
_被闪了一下。但也松了口气。
工作不忙的时候标准自动定得很高,工作忙过线就行了。
越是想把一件事情做好,越可能过于执着,看不清事实,不尊重规律。
这种一不是主要工作内容,二没有内行产品推动,三不是自己项目。何必呢?图什么啊!
同事说得很好,要不找个500块的外包吧
=================内心独白的分割线====================
记得上学时候,学习之外老师家长安排的事,都是过线就行。一直是个很懒散的家伙,何时变成一个负责的人了。
最恨不飘逸了!但是觉得自己很无趣的说……怎么回事
现在这样也不错,结果中庸有得有失,总体感觉靠谱。全按自己意思,疯起来受众太小……
容易路人转黑!
_
最近和不同风格的人一起工作,慢慢把握到自己的节奏。
接触了许多强人,受到很大震动。心情就像上膛的子弹,找到方向随时冲出去的感觉。
跟群里coder学习讨论了两周,还是觉得zf2坑略深,不顺手。
本周自己搭了个单入口mvc的框架。
实现越快越好,技术问题不是主要问题。
ios app节奏太慢,决定做之前基于map api的社交游戏,先让别人知道自己。
https://github.com/qdladoooo/bmw27
框架地址。基本机制已完成,边边角角用到再完善。
求羞辱,求指点,求探讨。
Linode是我见过的最专业省心的VPS服务商。
使用一年后,昨天把付费周期调整为两年自动续费。
放出我的referral code:2d3ccfa5fcad20b84d950a91e1b4600a2e8449b2
使用此code购买linode服务,服务运行满90天,Linode将支付我$20的推广费用。
我会分你一半 ^ ^
PS:
当年买VPS,一个叫 留点后路 的伙计号称可以返利,就用了他的referal code.
四个月后找他要钱,说账户没钱等下月,后来就不理我了。
这还是个打开门做生意的人,居然为了六十几块食言而肥……— —#
___待整理待验证___
制作全新ERP取代南湖现有ERP行不通。
正确方法应当选取10-100个涵盖80%日常操作的功能,建立快速原型搭建可用替代系统。在一段时间内新旧系统并行,逐步把功能从老系统向新系统迁移。直至新系统能够完全胜任工作。
唯有这样才能保证不脱离实际,吸纳现有领域经验的同时建立一套成熟、务实的旅游管理系统。
技术实施的过程中:
1.注重建立稳固底层,2.持续重构,3。有意识的把南湖当做一个普通商家来进行产品设计和数据结构设计。
最坏情况,在构建新系统过程中没人提纲挈领的 意识到/总结出 具有指导意义的模式。此时我们将得到一个使用互联网思想改造过的,同粤2旅游集团契合的不错的ERP系统。
较好的情况是,在构建过程中,面对各种逐渐浮现的问题,大家集思广益,找到各种场景下的捷径或最优解。得到一个大幅提高生产力的产品。
关于B2B平台。
考虑阿里巴巴,我认为通用平台比垂直平台逻辑上要简单。
阿里巴巴没能解决上下游信息屏蔽的问题,我们也不要去解决。
这不是智力高低或威权大小的问题。
纵观信息革命以来的趋势,靠阻碍信息流动牟利的公司/行业已日渐式微。
看到一句话大意说:看一个人的智力,要看他能否持有两种相反观点的同时,还具备行动的能力。
对我而言,这是一个鼓舞。
我意识到所谓的“单线程生物”“不能同时做多件事”“没有方向”,都是懒惰的借口。
把自己没在做正事的时间分出一半来做构架、设计、编码,就算要同时实践多个想法也够了。
被动的压力再也不能帮助我了。
我要。
要宝马的SUV,
要精装修的大房子,
要各式各样的开发板,
要系统训练所需的时间和金钱,
要经济自由。
做个有价值的产品,打动1000个人。
以此为目标开始行动。
今天做一个拖动排序的效果(demo)
功能很明确,拖动部分居然出现问题。
调试近一个小时,最终发现是浏览器默认行为导致的。
对img对象进行拖动,ff和chrome会创造一个跟随的半透明图片副本,光标变为“阻止”。
同时鼠标移动不再触发mousemove事件。
解决方案:使用div设置背景替代img标签
<div class=”pic”></div>
.pic {
width: 13px;
height: 16px;
background-image: url(“ic_launcher.png”);
}
这个问题点略偏。
调试蛮久,记录一下。
贴下09年“想当然”实现的拖动类。
虽然后来看到了许多完备实现,然而面对问题时发觉还是自己东西用着最顺手。
预先解决小问题,碰到大问题就能降低复杂度并大大减轻思想负担。
被工作推着走了这么久,从技术狂热、跃跃欲试到克制热情、应用为王,
竟然已经有很久没有想着去解决一个复杂点的技术问题了。
有些项目觉得已经想的很清楚了,却迟迟不能下手。
今天顺着zuo.com看到许多执行力强人,颇受触动。
生活渐稳定,要多写代码让别人认识自己。
e.g. $("#move_handle").bind("mousedown", {dragedDom: MoveableDom}, Drag.start);
var Drag = { dragedDom : null, difX : null, difY : null, start : function(event) { Drag.difX = parseFloat(Drag.dragedDom.css("left")) - event.pageX; Drag.difY = parseFloat(Drag.dragedDom.css("top")) - event.pageY; $(document).bind("mousemove", Drag.dragging); $(document).bind("mouseup", Drag.end); }, dragging : function(event) { Drag.dragedDom.css("left", event.pageX + Drag.difX); Drag.dragedDom.css("top", event.pageY + Drag.difY); }, end : function(event) { $(document).unbind("mousemove", Drag.dragging); $(document).unbind("mouseup", Drag.end); Drag.dragedDom = null; Drag.difX = null; Drag.difY = null; } };
我认为负责PHP实现的相关程序员今天可以多做一个魂器。
自年初爆出PHP易被攻击的hash设计漏洞,改用了5.4版本。
告别了各种包管理,有时要按需编译。
今天下午安装freetype扩展,试了多种靠谱方案(包括来自chinaunix和stackoverflow的方案)。
始终得到两种结果:
1.无效果,不报错
2.make错误,刷出一屏幕各种函数未定义
抓狂了。
静下心,换个思路。
删除多余包,编译安装PHP5.4.6,打开phpinfo一看,好了。
编译5.6.3不到2分钟,5.4.6超过五分钟;想起gd手册页有人说过
我觉得可能是,某些中间文件编译一次就被缓存起来的缘故。
近两天情绪状态不好,今天本来兴致盎然搞个cms,结果搞到很想死。
写点字记录,今后记得make clean这回事儿。
发微博上了,直接搬过来。
在最近的工作中我无意中找到一个简便易行的文本对象分组方法。设有3w个商品title,分词,记录不重复出现的词及其词频。取出现频率最高的双字词 100个,为每个title建立一个二进制的索引(每一位表示一个词是否出现过),这个索引已经为这批title画好了格子,每格中的数据具有一定相关 度。
用于索引的词汇数量,若一个词也不取,相当于所有数据在一个格子中。若取所有词汇,则格子数量等同于title数量,为3w。词汇的选取,能够控制分组的粒度。优化时一定可以通过调整“索引词汇”,取得较优解。最优解也在词汇组合之中。
这个算法的时间复杂度,全量为o(n),增量为o(1),可保证即时性。其中二进制索引字段支持任两条目间相关度的计算(比如:在两个条目中都出现的词除 以每个条目词汇数目)。后悔当年怎么没有想到这个算法。这是在一个边缘需求中,压力下两个小时实现的。3w数据分为2800组,肉眼看了下组内相关度,效 果明显。
这个东西满足了我的需求。绕过“两两比较,海量计算”的常规思路而且有一定效果。
当时如果用这个方法做比价项目,操作上就简单多了。
一直有点轻微强迫症。昨天丢了100块钱。
回忆,自责,臆断,诛心,懊恼。循环往复。
不过已经能够像以前那样开导自己了。感到重新开始,渐渐的务实。
进公司月余,想找机会申请转正。
a.以薪酬区分coder,在当前层次我得算是弓马娴熟了吧。
我都不争取“一月转正”,那这政策不是形同虚设了么?
b.如果此时不申请,而将来有谁申请并通过了,那自己颜面何存?
程序员本来都已经没有什么别的追求了。
c.何况六个月试用实在太长了,不能忍。
今日无事,抽空抓了些古诗文回来。
有事没事读一读查一查做做交叉索引,比图书馆借书便利多了。
一向说多做少,这次学乖拒绝思考直接抓。
考虑索引一下,类别理出来。
觉得用处还蛮多的。
创意才重要。
而我是好产品。
好到只肯做自己的产品经理。
没有程序员的时候,自学了程序。
现在回到开始的地方,在产品这条战线继续推进。
调动……组织……
目前宾语还是只有我自己。
设计!前端!
要么花钱买要么结成利益共同体,想要自己干的想法太二了。屌丝本位。
1.对现状很满意。
女朋友终于来到身边。
工作流程完善,现有架构有很多东西可以学。
和同样有志于程序的人共事。
2.但无数事实证明,我是那种凡事往最坏处想的杞人忧天强迫症患者。
因为对现状满意, 非常积极的担心会失去这份工作。
回来的路上,一边打kof97,脑子里都在想这件事。
3.我有自己的观点和底线。
会照顾他人的情绪。但如果问心无愧,判断不为外界倾斜。
这次是因为,我知道自己并没有尽全力工作。
4.早上到cnblogs.com看编辑推荐。
午餐时间,Google reader读几篇关心的博客。
下午四点,喷嚏图卦。
以前空闲时才会做这些事,现在有任务还这么干原因有三点:
a. 鳟鱼效应。
新鲜血液易使技术/自信不够强的老员工有压力。而我讨厌被人嫉恨。
同事之间,和和睦睦开开心心做事最重要。
做个纯粹的程序员我就很满意,若顺便做了有益于社会/影响世界的产品就更加好。
有套页面给我做,没走脑子随口说自己肯定比一般程序员写得快,当时就觉得说错话了。
_同事看着不太开心。我让他判断一下时间,他说他做要三天。后来找过来跟我说我不了解框架,写慢点没关系。在我看来,也许他怕我压力太大,也许怕我太积极影响不好吧。
_我决定收着点编码,定了五天,所以才有时间读喷嚏图卦。
代码写得太快,若让boss认为团队之前偷懒,重估生产力,那以后大家日子都不好过。
b.接触到boss一个以前的下属,给描述,一字记之曰狠。
看以前代码,知道一个水平不错的写了很多低层机制的牛人刚刚离职。
全员持股,A轮之前进来,职位不低,为啥要走呢?
看到他凌晨3-4点写的代码。不是修复bug。
新一轮招聘进来,发觉公司人员零落。
听到一些传言,说公司无情东西做好人就逼走。
……
语言和代码立场鲜明,每天一起工作的感觉却不是这样,我还没有自己的判断。
但这些先入的观念的确令我心生防备。我还记得那个每每按时完成,却总得到更多工作和更短工期的coder。
c.我小声说,同工同酬吗?
钱是很好,但我不喜欢加班。
写得更快完成更多的工作维护更多的代码得到更多的bug。(设水平相同则与代码量正相关)
我把生命交给了别人,别人能为我负责吗?
写出来感觉好多了。
工程师不会没有项目做,但我现在不想面对未知。
我是一个病人,每天要和自己战斗。 这么想着反而涌起一种睥睨万物的气魄。
ps:
古人说:远则怒,近则狎,唯女子与小人难养也。
古人标准跟职场规则正好相反,不巧我却是个老派的人。
女人创业,也许的确是态度大于能力,关系重于业务。
我想要经济自由,但几万十几万这种程度不解决问题。
换份工作,做个外包也能赚到。
为此妥协在今天的我看来还不值得。
我会示好,不会讨好。
好好工作,因为我期望自己早日成为酷酷的专业人士。
而非为了谁的施舍。
没看到什么“sphinx最佳实践”,我这种懒人往往是读读文档,实现功能后就不再深究。
最近改了个增量索引引起的bug,借机思考总结出一些问题。写在这里。
现有tag, skill, skill_tag表,一个skill可以对应多个tag。
以id, tag_id, skill_id … …的形式导入sphinx。
通过php sphinxapi:setGroupBy的同时setSelect以此赋予tag_id不同的权重。
结果发现得到的权重与预期不同。
进过排查调试发现原因:从主索引、增量索引中检索数据,出现重复的skill_id。
这里涉及我们实现增量索引的方式。
我们不做合并,每天更新一次主索引,据skill_tag表最后更新时间设定界限,根据界限值每三分钟做一次增量索引。
问题就在于,这个限定条件,并不能限定skill_id在主、增索引中不存在交集。
解决思路只用一个索引,方案有两个:
1. 只做主索引,每三分钟更新一次,数据量不大时可以接受
2. 每三分钟做增量索引,合并进主索引。通用性比较好
===================== 主观的分割线 ===========================
解决这个问题的过程中我犯了几个错误,我惊恐的发现有些错误以前也犯过。
=============我的第一个问题=================
思路:
新入职公司,问题放在眼前。我看到
1) 项目的sphinx取数据时做了大量联表操作,冗余了大量信息。查询语句也是把全文索引当做关系型数据库在用。
2) 技术总监亲自调试了很长时间,没有结论。
我一贯的观点是专用:索引的归索引,DB的归DB。我倾向于只使用sphinx加速文本检索,因为mysql作为关系型数据库,处理各个数量级的数据有一整套成熟方案。sphinx在关系型数据库方面的表现还是未知。
强力同事调试没有头绪,我判断是设计问题,猜测问题出在sphinx遍历数据时忽略了最大值之后的数据。请示后改用我的思路:小而专用的sphinx索引,id运算交给mysql。
方案的问题:
一元分词查询的准确度,显然不如id的关系运算。
换用coreseek进行分词,没有db配合,也不能完美重现程序功能。
上头又不许用“sql+缓存”的策略,因为推倒重来毕竟不现实。
总结:
做事风风火火,缺少深思熟虑和严谨验证。
具体到这个问题,本来很多细节都能够再敲定一下。我也有意识的去克制大动干戈的操作,却仍不足以驾驭犯二的热情。“技术狂热”的状态下,对判断依据的理解有太强的选择性。
我不是所谓的完美主义者,但一直觉得如果同样的错误只犯一次,那今天永远比昨天强。代码写下去,是在向前走。这是我学习方法的基础之一,这点必须保证。所以像这种意识到了却不能阻止其发生的错误,我认为需要写篇文章记录一下。理科生讨厌这种无力感。
=============之后的问题=================
定位是索引的问题,纠正的过程中险些又犯了错。
既然错误的症状是skill_id在主索引和增量索引上有重复,那么重写增量索引的建立逻辑,保证skill_id的严格分界是不是就解决了问题?于是着手改配置文件。
可是一旦限定了skill_id唯一,sphinx就不能及时更新skill_tag的关系变化情况,以tag为主题进行的搜索功能就缺失了。不能这么改。
是不是多建一个索引呢?或者变更业务逻辑使用另外的索引实现?隐约觉得这并不是好的解决方案。
我开始思考,能不能两全?进而思考,这种关系型的数据能否建增量索引?
关系的更新,不外乎add, delele和update,update可由add+delete实现,只有两种操作。
add操作,增量可以实现。delete呢?我们建增量的方式不能改动主索引,必须换方法。这个才是问题的根源。
思路走到这里,问题已经明朗,不由得为自己浅尝辄止的思维习惯感到后怕。
但是还没完。
我在crontab里看到这样一句被注释掉的命令:
#/root/ss/bin/indexer -c /root/ss/conf/xxxxx.conf –merge skill_tag_index skill_tag_delta_index –merge-dst-range deleted 0 0 –rotate
不知道谁因为什么加了注释,它为主索引同步了delete操作,亦即我们方法的缺陷。
这条命令是增量索引的常规做法必备的命令。
因为缺乏这个经验,因为没有切实的去部署那么一次,付出了很大的调试代价。
我从之前磕磕绊绊形而上思索带来的满足感中,一下子落回地面,觉得很空虚。
“十分力做八分事,掌握成熟的解决方案,以期完美的解决问题”,坚持这么做的自己反而尝到了苦果。这一点和上面的问题何其相似啊!
ps:
始终觉得,自高中懒做习题以来,对数学的远离影响了逻辑思维的严谨性。
想不到现在甚至远离了逻辑思维本身。
上面的推理进行的很艰苦,感到变化太多,无法控制。用笔在纸上画图的时候,居然觉得这一切十分陌生。有很久不打球咋上场肌肉颤抖的感觉。
用进废退,上一次深入思考什么东西是在啥时候?
人生能有几个欧洲杯决赛!
不过真的很困,有些脑力不济,做不了复杂的事情。
boss们在外面开会,我在读一本中文版的《集体智慧编程》。
先给需求场景,再讲技术。读起来容易理解也有动力。
sphinx让我能够“阅读”海量数据,这本书将教给我如何“理解”它们。
上个项目用了一个模块化的php爬虫。
这次有机会一展所长,一周时间写了这个。抓取部分用了threads模块,效率还可以。
搭配db服务,实现抓取/更新和统计。作为一个解决方案能够满足要求。
尽管我已经把不同网站间的变化尽力封装进data_picker,但还是觉得不够通用。
1.仍需要编写针对性的代码;2.得到数据在db层面
至多算是个程序员工具,甚至可能只是我的工具。
不知道那些发布自用爬虫出去的人是怎么构架的。
关于perl语言,至今没有通读骆驼书,缺一步查漏补缺的过程。基础不扎实,有时碰到问题,不免怀疑走了弯路。加了群,感觉氛围不是太好。
又有人推荐学python。我觉得py不如pl这么有人文气息,更重要的是pyer缺少pler这种二感啊。
新生成的model : Friends.php
<?php
class Friends extends CI_Model
{
private $ID;
private $rid;
private $frid;
private $gid;
private $source;
private $status;
private $crdt;
private $updt;
public $table_name = 'fs_friends';
private $debug = TRUE;
//
private $mod_params = array();
private $results = array();
private $results_count = 0;
//
function __construct()
{
parent::__construct();
$this->load->database();
$this->load->helpers('memcache');
}
function create($para=array())
{
//sql
$ksql = '';
$vsql = '';
foreach ($para as $key => $val)
{
$ksql .= $key. ',';
$vsql .= '\'' . $val . '\',';
}
$ksql = rtrim($ksql , ',');
$vsql = rtrim($vsql , ',');
//sql
$sql = 'INSERT INTO '. $this->table_name .'(' . $ksql .') ';
$sql .= 'VALUES('.$vsql.')';
if($this->debug)
{
echo '<hr>';
echo $sql;
echo '<hr>';
}
$ret = $this->db->query($sql);
if(! $ret)
{
return FALSE;
}
else
{
return $this->db->insert_id();
}
}
function Modify()
{
$sql = 'UPDATE '. $this->table_name .' SET ';
$count = 0;
foreach ($this->mod_params as $key => $value)
{
if ($count > 0)
$sql = $sql . ', ';
if (is_string($value) == TRUE)
$sql = $sql . $key . '= \'' . $value . '\' ';
else
$sql = $sql . $key . '=' . $value;
$count = $count + 1;
}
$sql = $sql . ', updt = ' . time() ;
$sql = $sql . ' WHERE ID = ' . $this->ID;
if($this->db->query($sql))
return $this->db->affected_rows();
else
return FALSE;
}
// retrieve
function Retrieve($ID)
{
$sql = 'SELECT * FROM '. $this->table_name .' WHERE ID = ' . $ID ;
$query = $this->db->query($sql);
if($query)
return $query->row_array();
else
return FALSE;
}
function GetResultArray() { return($this->results); }
function GetResultCount() { return($this->results_count); }
function GetModParams() { return($this->mod_params); }
/* get prop */
function GetID() { return $this->ID; }
function GetRid() { return $this->rid; }
function GetFrid() { return $this->frid; }
function GetGid() { return $this->gid; }
function GetSource() { return $this->source; }
function GetStatus() { return $this->status; }
function GetCrdt() { return $this->crdt; }
function GetUpdt() { return $this->updt; }
/*set props */
function SetID($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['ID'] = $val; $this->ID = $val; }
function SetRid($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['rid'] = $val; $this->rid = $val; }
function SetFrid($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['frid'] = $val; $this->frid = $val; }
function SetGid($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['gid'] = $val; $this->gid = $val; }
function SetSource($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['source'] = $val; $this->source = $val; }
function SetStatus($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['status'] = $val; $this->status = $val; }
function SetCrdt($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['crdt'] = $val; $this->crdt = $val; }
function SetUpdt($val, $ignore_mod=false) { if ($ignore_mod != TRUE) $this->mod_params['updt'] = $val; $this->updt = $val; }
}
生成脚本,以及配套使用的pdo中间层: init.php
<?php
/*
$db = new db();
$db->Enq(‘use wz_sns;’);
$sql = “desc $tName”;
$colInfo = $db->Eq($sql);
$rows = array();
$rows[] = ‘<?php’;
$rows[] = “class {$cName} extends CI_Model”;
$rows[] = ‘{‘;
foreach($colInfo as $col) {
$rows[] = “ private \${$col[‘Field’]};”;
}
$rows[] = ‘ ‘;
$rows[] = ‘ private $table_name = \’’ . $tName . ‘\’;’;
$rows[] = ‘ ‘;
$rows[] = ‘ private $debug = TRUE;’;
$rows[] = ‘ ‘;
$rows[] = ‘ //‘;
$rows[] = ‘ private $mod_params = array();’;
$rows[] = ‘ private $results = array();’;
$rows[] = ‘ private $results_count = 0;’;
$rows[] = ‘’;
$rows[] = ‘ //‘;
$rows[] = ‘ function construct()’;
$rows[] = ‘ {‘;
$rows[] = ‘ parent::construct();’;
$rows[] = ‘ $this->load->database();’;
$rows[] = ‘ $this->load->helpers(\’memcache\’);’;
$rows[] = ‘ }’;
$rows[] = ‘ ‘;
$rows[] = ‘ function create($para=array())’;
$rows[] = ‘ {‘;
$rows[] = ‘ //sql’;
$rows[] = ‘ $ksql = \’\’;’;
$rows[] = ‘ $vsql = \’\’;’;
$rows[] = ‘ foreach ($para as $key => $val)’;
$rows[] = ‘ {‘;
$rows[] = ‘ $ksql .= $key. \’,\’;’;
$rows[] = ‘ $vsql .= \’\\’\’ . $val . \’\\’,\’; ‘;
$rows[] = ‘ }’;
$rows[] = ‘ $ksql = rtrim($ksql , \’,\’);’;
$rows[] = ‘ $vsql = rtrim($vsql , \’,\’);’;
$rows[] = ‘ //sql’;
$rows[] = ‘ $sql = \’INSERT INTO \’. $this->table_name .\’(\’ . $ksql .\’) \’; ‘;
$rows[] = ‘ $sql .= \’VALUES(\’.$vsql.\’)\’;’;
$rows[] = ‘ ‘;
$rows[] = ‘ if($this->debug)’;
$rows[] = ‘ {‘;
$rows[] = ‘ echo \’<hr>\’;’;
$rows[] = ‘ echo $sql; ‘;
$rows[] = ‘ echo \’<hr>\’;’;
$rows[] = ‘ }’;
$rows[] = ‘ ‘;
$rows[] = ‘ $ret = $this->db->query($sql);’;
$rows[] = ‘ if(! $ret)’;
$rows[] = ‘ {‘;
$rows[] = ‘ return FALSE;’;
$rows[] = ‘ }’;
$rows[] = ‘ else ‘;
$rows[] = ‘ {‘;
$rows[] = ‘ return $this->db->insert_id();’;
$rows[] = ‘ }’;
$rows[] = ‘ }’;
$rows[] = ‘ ‘;
$rows[] = ‘ function Modify()’;
$rows[] = ‘ {‘;
$rows[] = ‘ $sql = \’UPDATE \’. $this->table_name .\’ SET \’;’;
$rows[] = ‘ $count = 0;’;
$rows[] = ‘ foreach ($this->mod_params as $key => $value)’;
$rows[] = ‘ {‘;
$rows[] = ‘ if ($count > 0)’;
$rows[] = ‘ $sql = $sql . \’, \’;’;
$rows[] = ‘’;
$rows[] = ‘ if (is_string($value) == TRUE)’;
$rows[] = ‘ $sql = $sql . $key . \’= \\’\’ . $value . \’\\’ \’;’;
$rows[] = ‘ else’;
$rows[] = ‘ $sql = $sql . $key . \’=\’ . $value;’;
$rows[] = ‘’;
$rows[] = ‘ $count = $count + 1;’;
$rows[] = ‘ }’;
$rows[] = ‘ $sql = $sql . \’, updt = \’ . time() ;’;
$rows[] = ‘ $sql = $sql . \’ WHERE ID = \’ . $this->ID;’;
$rows[] = ‘ if($this->db->query($sql))’;
$rows[] = ‘ return $this->db->affected_rows();’;
$rows[] = ‘ else ‘;
$rows[] = ‘ return FALSE;’;
$rows[] = ‘ }’;
$rows[] = ‘ ‘;
$rows[] = ‘ // retrieve’;
$rows[] = ‘ function Retrieve($ID)’;
$rows[] = ‘ {‘;
$rows[] = ‘ $sql = \’SELECT * FROM \’. $this->table_name .\’ WHERE ID = \’ . $ID ;’;
$rows[] = ‘ $query = $this->db->query($sql);’;
$rows[] = ‘ if($query)’;
$rows[] = ‘ return $query->row_array();’;
$rows[] = ‘ else ‘;
$rows[] = ‘ return FALSE; ‘;
$rows[] = ‘ }’;
$rows[] = ‘ ‘;
$rows[] = ‘ function GetResultArray() { return($this->results); }’;
$rows[] = ‘ function GetResultCount() { return($this->results_count); }’;
$rows[] = ‘ function GetModParams() { return($this->mod_params); } ‘;
$rows[] = ‘ ‘;
$rows[] = ‘ / get prop /‘;
foreach($colInfo as $col) {
$forFunName = ucfirst($col[‘Field’]);
$rows[] = “ function Get{$forFunName}() { return \$this->{$col[‘Field’]}; }”;
}
$rows[] = ‘’;
$rows[] = ‘ /set props /‘;
foreach($colInfo as $col) {
$forFunName = ucfirst($col[‘Field’]);
$rows[] = “ function Set{$forFunName}(\$val, \$ignore_mod=false) { if (\$ignore_mod != TRUE) \$this->mod_params[‘{$col[‘Field’]}’] = \$val; \$this->{$col[‘Field’]} = \$val; }”;
}
$rows[] = ‘ ‘;
$rows[] = ‘}’;
//写入文件
$fh = fopen(“{$cName}.php”, ‘w’);
fwrite($fh, implode(“\n”, $rows));
fclose($fh);
db.php
<?php
/*
class db {
static protected $pdo;
function __construct() {
$this->GetInstance();
}
//获取唯一的数据库连接对象
function GetInstance() {
if (self::$pdo == null) {
self::$pdo = new PDO(__DATABASE_DSN, __DATABASE_USER, __DATABASE_PW);
self::$pdo->exec('SET NAMES UTF8');
// var_dump(“once”);
}
return self::$pdo;
}
//执行sql语句,返回结果矩阵
function Eq($sql) {
$res = self::$pdo->query($sql);
//如果存在,打印错误信息
$this->IsError();
$res->setFetchMode(PDO::FETCH_ASSOC);
return $res->fetchAll();
}
//执行sql语句,返回单行结果
function Eor ($sql) {
$res = self::$pdo->query($sql);
//如果存在,打印错误信息
$this->IsError();
$res->setFetchMode(PDO::FETCH_ASSOC);
$data = $res->fetch();
return $data;
}
//执行sql语句,返回单列结果
function Ec($sql) {
$res = self::$pdo->query($sql);
//如果存在,打印错误信息
$this->IsError();
$res->setFetchMode(PDO::FETCH_ASSOC);
$data = $res->fetchAll(PDO::FETCH_COLUMN, 0);
return $data;
}
//执行sql语句,返回数量(单个结果)
function Es($sql) {
$res = self::$pdo->query($sql);
//如果存在,打印错误信息
$this->IsError();
$res->setFetchMode(PDO::FETCH_NUM);
$data = $res->fetch(PDO::FETCH_COLUMN);
return $data;
}
//执行sql语句,返回影响行数
function Enq($sql) {
$res = self::$pdo->exec($sql);
//如果存在,打印错误信息
$this->IsError();
return $res;
}
//todo:貌似用不到啊,直接用pdo对象吧
//执行sql语句,返回影响行数
function ExecuteNoneQueryWithPrepare($sql) {
}
//调试信息,发布后可关闭
function IsError() {
$errorCode = self::$pdo->errorCode();
if($errorCode != '00000') {
var_dump(self::$pdo->errorInfo());
exit();
}
}
//添加引号
function quote($var) {
return self::$pdo->quote($var);
}
}
还有一个处理模版的perl脚本,作用是做掉init.php中“$rows[] = ‘ xxxxxxxxx’;”这种机械性的工作。
刚发现被自己的sync覆盖掉了(sync很靠谱,主要是刚入职没有公司域账号,后来切换时程序没有保存)。逻辑很简单,就是逐行修改,注意替换单引号和美元符号,生成后最好再使用语法高亮的编辑器肉眼检查一下。
===================失而复得的分割线==========================
2012年6月14日15:19:26
新电脑启用sync,居然找到了。果然靠谱,不枉信你这么多年。有个问题就是没有考虑数组$ar[‘name’]中的单引号,多的话加条规则吧。
#!/usr/bin/perl -w
use strict;
open SFH, ‘<s.php’;
open DFH, ‘>d.php’;
while(<SFH>) {
chomp $;
$ =~ s/\‘/\\‘/g;
$_ =~ s/‘/\‘/g;
my $line = ‘$rows[] = \’’ . $_ . ‘\’’ . “;\n”;
print DFH $line;
}
close DFH;
close SF;
===================失而复得的分割线==========================
其实这个需求很适合使用heredoc语法。
我在使用过程中发现一个无法回避的问题是:heredoc内部转义变量、或heredoc同其他字符串变量连接,会消灭掉除heredoc中“可见”换行效果外的所有换行(测试中涉及文件换行主要使用双引号内的\n,chr(10),chr(13)和chr(10)chr(13))。
换句话说就是,不使用heredoc语法,输出文件能正常换行。
heredoc包含变量,则转义的变量中换行符失效;将heredoc和一个包含换行的字符串变量连接,变量中的换行符失效。
初步的结论是存储heredoc的变量不能简单当做字符串变量使用。
这算不算php的一个bug呢?还有待严谨设计的实验去证明。
======================忍不住要说的分割线==========================
我一直对oo持保留态度(博问)。认为复杂度低的情况引入oo弊大于利。
不止一次在博客微博甚至面试中吐槽。“这种工程技术,是为了让5w 年薪coder胜任20w年薪工作而设计的。”上文中“年薪”替换成“智商”也没问题。
这次项目使用CI框架,又见如此Model。
你说这一坨坨的set,get函数有神马用啊?
你当你是C艹啊?
团队协作嘛,统一标准的好处很明显。我不是也写了生成函数做这事儿了么。
不过还是希望今后php的程序之路中,能早日发现ORM不可替代的便利。
迁移博客到linode vps。
sae(新浪app引擎)没有常规文件io,不能自动更新,不能上传图片。不太方便。
而且最近在公司发觉隔段时间就不能访问(可能由于出口ip单一,访问量过大被限制)。
总之先迁回来了。
分三步
1.代码checkout到vps
2.数据库使用DeferredJob导出(phpmyadmin导出会触及单位时间限制)
3.进入wp后台“设置=>常规”修改域名
额外做一些事情
博客文章中的图片链接还指向sae,在数据库中批量替换
UPDATE
wp_posts
SET
post_content = REPLACE(
post_content,
‘http://dlad.sinaapp.com',
‘https://wobu2.com'
)
WHERE post_content LIKE “%sinaapp%”
AND post_status = ‘publish’
$url = $_SERVER[‘REQUEST_URI’];
header(“Location:https://wobu2.com" . $url);
作为一个伪军,我的门卡信息不能进入考勤系统。
每天早晚要发一封签到邮件,悲催。TAT
但是我发现可以这么干
sendemail -f liyaohui@snda.com -t dlad@wobu2.com -u “上班” -m 1 -s smtp.snda.com -xu xxx-xp xxxxx
======================贱贱的分割线===========================
2012年5月25日12:55:05
早睡早起,吾所欲也。
上面的想法多半是个玩笑,没有真的决定使用。
不过……下雨天打孩子,闲着也是闲着。我还是把它完成了。
限制
公司电脑是绑定ip的,公司邮件也需要内网ip,邮件密码包含密保随机码。
随身设备只有台BB8310,可浏览网页。
我在外网服务器上启用了一个页面。
设置接口,维护一个状态位和一组随机码。
之后在本地虚拟机做了个守护进程
#!/usr/bin/perl -w
use strict;
use LWP;
$| = 1;
my $url = ‘此页面常年提供1.是否发送邮件;2.随机码;3.参数设置接口’;
my $cmd = ‘邮件发送命令’;
my $ua = LWP::UserAgent->new;
while(1) {
my $res = $ua->get($url);
my $content = $res->content;
#解析数据
my @match = split '######',$content;
my $switch = $match[0];
my $rkey = $match[1];
#关闭状态位,并发送邮件
if($switch eq 'on') {
#设置状态位
$res = $ua->get($url . "?参数列表");
$content = $res->content;
#若状态位的确关闭,发送邮件
if($content =~ m/^off/) {
system($cmd . $rkey);
}
}
sleep(60);
}
如此,若不关公司电脑,我能够手机访问指定网址设置随机码,一分钟之内即会发送签到邮件。
最近非常想在自己项目中引入iframe。
我觉得这么干的确很灵活。但势必要引入许多复杂和未知。
一直在考虑iframe的特性我是不是真的用得上。发现对这件事居然没有头绪。
强迫自己分析,iframe的好处有哪些?
y.qq.com
咋见惊为天人。保证页面正常行为的同时,不打断音乐播放器。
mail.163.com
实现了强大的模态窗口。
这两点我用得上,但其实都无关紧要。
我项目的主屏幕是一张地图,默认操作就不刷新页面。模态窗现在的技术已经足够成熟。
另外,我对iframe的特性并不是完全了解。要做成y.qq.com的样子,显然是一个系统工程。
我希望找到支持自己使用“iframe方案”的理由。搜“内嵌iframe的好处”,并未找到深度分析的文章。
游戏作品,开发人员也该享受到乐趣才对。
一个人的项目,有时间折腾,就亲自感受一下吧。
这玩意儿做出来,肯定有人要看呆了!赫赫