phpstorm 快捷键

phpstorm是个很好用的PHP开发工具,工欲善其事必先利其器,熟悉下软件的操作快捷键能提高工作效率。

ctrl+shift+n 查找文件
ctrl+j 插入活动代码提示
ctrl+alt+t 当前位置插入环绕代码
alt+insert 生成代码菜单

ctrl+q 查看代码注释
ctrl+d 复制当前行
ctrl+y 删除当前行
shift+F6 重命名
ctrl+shift+u 字母大小写转换
ctrl+f 查找
ctrl+r 替换
F4 查看源码
ctrl+shift+i 查看变量或方法定义源
ctrl+g 跳转行
ctrl+alt+F12 跳转至当前文件在磁盘上的位置
alt+down 查看下一个方法
alt+up 查看上一个方法
ctrl+alt+l 重新格式化代码
ctrl+shift+down statement向下移动
ctrl+shift+up statement向上移动
alt+shift+down line向下移动
alt+shift+up line向上移动
ctrl+/ 行注释
ctrl+shift+/ 块注释

ctrl+shift+n 打开工程中的文件
ctrl+b 跳到变量申明处
ctrl+[] 匹配 {}[]
ctrl+shift+]/[ 选中块代码

ctrl+x 剪切行
ctrl+shift+v 复制多个文本
alt+left/right 标签切换
ctrl+p 显示默认参数
ctrl+F12 在当前类文件里快速查找方法

那些最好的轮子 – PHP篇

 关于不要重复造轮子的二三事一文中,交代了一些背景和想法。本篇则完全是一些干货,列举一些我用过或者即将会用的PHP轮子,基本都符合我对好轮子的定义:开源、许可证宽松、容易集成的PHP项目,目有些已经集成在EvaEngine里面,希望能帮助别人少走弯路。

日志还会陆续补充更新,同时欢迎推荐补充。

 

Databse 数据库ORM

 

Doctrine 2

  • License : MIT
  • Source Code
  • Allo点评:Doctrine是功能最全最完善的PHP orM,社区一直很活跃,对NoSQL也非常迅速的作出了跟进与支持。但之所以没有说Doctrine是最好的,是因为我对PHP究竟有没有必要使用如此庞大的ORM还心存疑虑,平心而论Doctrine的入门门槛实在有些高,尤其是DBAL的提出,更是要把开发者牢牢绑定在Doctrine这艘大船上,用与不用,还是要仔细权衡。

 

RedBeanPHP

  • License : New BSD
  • Source Code
  • Allo点评:相比起Doctrine,RedBean轻巧的简直要飞起来,这两个轮子就是一组最好的比照,是大而全,还是小而精,根据项目选择吧。

 

Documents & Testing 文档与测试

 

phpDocumentor 2

  • License : MIT
  • Source Code
  • Allo点评:老牌php文档生成工具。

 

Faker

  • License : MIT
  • Source Code
  • Allo点评:Faker是一个很神奇的项目,会自动生成拟真的数据,包括用户资料、长文本、IP、日期等等,在网站上线前测试时非常好用。

 

Datetime 时间处理

 

Carbon

  • License : MIT
  • Source Code
  • Allo点评:虽然PHP5内置的Datetime类已经足够应付一般需求,不过Carbon所提供的一些更人性化的处理则更符合实际需求,如果是时间相关的项目应该考虑使用。

 

File System 文件系统

 

Gaufrette

  • License : MIT
  • Source Code
  • Allo点评:文件系统几乎是所有项目都会遇到的问题,Gaufrette为常见的文件系统提供了一套统一接口,包括本地文件/FTP/Dropbox/GridFS/Zip/AmazonS3等等,是大型系统必备的组件。

 

Front-end 前端性能

 

Assetic

  • License : MIT
  • Source Code
  • Allo点评:Assetic可以说生来就是为了多模块的项目而存在的,有了Assetic,可以将分散在各模块中的前端文件编译、合并、压缩。可以让开发人员专注于代码的编写而不是前端文件的生成。

 

lessphp

  • License : MIT
  • Source Code
  • Allo点评:LESS编译器的php版本。不过对于复杂的LESS项目,比如bootstrap,编译的结果与NodeJS原版还是有差异,只能做为Assetic的一个补充。

 

minify

  • License : MIT
  • Source Code
  • Allo点评:PHP版本的CSS/JS压缩器。

 

发布于 分类 网站技术于那些最好的轮子 – PHP篇留下评论

关于不要重复造轮子的二三事

 “不要重复造轮子 Stop Trying to Reinvent the Wheel,可能是每个程序员入行被告知的第一条准则。我自己也会对新人反复灌输这个概念,写程序其实是一个最能“偷懒”的工作:你现在费力实现的每一个功能,可能早已经有极好的解决方法贡献在开源社区,如果可以直接用现成的,那节省下来的时间是不是可以用来偷懒呢?极端的说法,哪怕是那位把所有开发外包给沈阳一家公司的哥们,如果撇开道德以及商业安全,只要能贡献优质的代码和健壮的功能,对于一个项目来说,这样做其实没任何问题。

找轮子存在的问题

虽然不要重复造轮子的准则被反复提到,但是以我个人的经验,这个准则实践起来其实很有难度,因为:

  1. “不要重复造轮子”意味着首先需要找到一个可以用的轮子,而且我们一般希望是能最好的轮子才可以一劳永逸。这就对个人的信息检索能力有非常高的要求。
  2. 找到了一个轮子,但这个轮子好不好用,需要时间来论证。能一眼判断一个项目的质量以及易用性,这其实需要大量项目经验的积累。
  3. 好轮子不是你想用,想用就能用的。要想将一个开源项目整合到自己的项目中,需要对这个项目有比较深的了解。开源项目的文档质量参差不齐,当使用轮子时,只看文档往往是不够的,还需要阅读源代码甚至深度修改定制。更不要说大部分开源项目根本没有中文文档。

所以现实情况往往是:新人不懂得检索方法,找不到轮子;好不容易找到一个轮子,学了半天不会用;好不容易能运行,很多地方与需求不一致,但是又不会改;一来二去,最后还是变成自己写轮子,同时还得出一个结论:别人的轮子都不好用,还是要坚持自己造轮子。

这种情况的最佳体现,就是曾经有一段时间遍地开花的PHP框架。每一个写框架的人都认为自己写的框架才是最好的轮子,甚至是很多PHP新人,对几个成熟框架浅尝辄止后,也纷纷投身写框架的行列。成品大部分看过去却是大同小异,只是语法层面更符合作者本人的习惯,而缺乏大量的测试以及文档社区,最终的结果就是一个半成品然后无疾而终。

这个例子可能有马后炮之嫌,毕竟PHP的造框架运动是由当时的背景和多方面的因素造成的,目前因为有了PHP-FIG制订的规范,PHP的框架的资源已经慢慢集中在Zend FrameworkSymfonyCakePHPYiiCodeIgniter这样少数几个成熟框架之下了。更多的符合PSR规范的模块类库在取代新框架不断涌现,这对整个PHP社区都是好事情。

话题稍微扯的有点远,不过核心的意思还是为了说明,找轮子本身其实是一件不容易的事情。而我对上面问题的解决方法是:找轮子的任务不要交给新人,而是要由经验丰富,信息检索能力强的编程人员负责,最好是项目的构架人员。团队成员找到的轮子最好也由构架人员拍板,用还是不用。对于团队新人,最重要的任务还是编程基本功、文档阅读能力以及如何用好已经拍板的轮子。

怎样才算是好轮子

个人认为好轮子应该具备以下的特征:

  1. 开源,并且License宽松。
  2. 有文档,代码规范,接口友好,最好有实际用例。
  3. 社区相对活跃。
  4. 松耦合,定制容易。

至于同时找到好几个轮子需要选择的情况,可能要根据项目的实际情况进行取舍:有些轮子侧重于大而全,希望解决大部分问题,但是细节上处理不够细致;有些轮子小而精,专注解决一个问题,但是不具备好的通用性。但只要合适好用,都是一个好轮子。

我自己认可的一些好轮子列举在这里:

如何找到好轮子

如何找到好轮子其实在上面问题中已经很清楚了,你应当具备:

  1. 信息检索能力
  2. 外文资料阅读能力
  3. 代码阅读能力以及平时的积累

对于第一条,个人的信息检索能力是无法一蹴而就的,不过如果是还在等待我对此再说出一二三而不是去自己检索寻找方法的朋友,基本上已经没救了。

这里唯一需要说的是,如果想用百度那货去找技术资料的还是省省吧。

外文资料阅读能力也非一日之功,不过个人倒是有个小窍门,如果想要获得一些项目的HelloWorld入门教程或者服务器的配置,可以将检索语言限定为日语,因为日文用户的教程往往秉承了日本细致入微的精神,包括项目背景、需要的环境安装等等一些对初学者才有用的知识,在日文的技术资料中往往也会写的很清楚。

至于平时的积累,可能程序员都知道GithubSourceForgeGoogle Code这些优秀的项目托管网站。但是积累的意思并不是说有时间上去看两眼或者随便收藏一下这么简单。

比如我自己侧重PHP方面的项目,我的一个做法是找到Github下所有Follower大于300的PHP项目(其实一共不到200个其中很多还是php框架),然后一个一个像扫货一样,对其进行了解以及记录。

我的另一个做法是查看知名PHP框架,看看他们用了哪些轮子,比如在Symfony Reference中,你就能淘到Asseticmonolog 这样的好货。

最后一个办法是在Github上Follow一些活跃的作者,比如我的Following中就会显示我的Stars和Forks,里面自然也是我认为值得收藏关注的项目。

PHP NOTICE级错误提示对程序性能影响的研究

我是个有代码洁癖的人,写出来的程序上线后不想见到任何错误 ,而且我也认为错误信息虽然被屏蔽了,但是应该会影响性能的,曾想去验证我这个想法,但还没去验证过,今天正好看到一文章是说这个情况,验证了我的观点,于是摘录如下:

很多人开发php的时候喜欢关掉一部分的错误提示,尤其是Notice级别的提示,这样做可以省去一些严格判断的代码。而平时开发喜欢开着E_ALL级别的我今天在接手同事的项目时,看着满屏幕Notice错误时突然想到了1个问题:

在关掉错误提示时,那么程序代码中大量的notice级别错误是否会造成PHP性能下降,从而使关闭错误输出成为一个掩耳盗铃的做法呢?
下面我来用性能测试来证明这个推论:
测试1:
在关闭错误显示的情况下,测试未初始化变量和已初始化变量在10000000次循环中的性能
变量已初始化的循环代码如下:
PHP代码
  1. $start = getmicrotime();  
  2. error_reporting(E_ALL | E_STRICT);  
  3. ini_set('display_errors', false);  
  4. ini_set('log_errors', false);  
  5. $var=1;  
  6. for ($i=0; $i < 10000000; $i++) {   
  7.     $foo=$var;  
  8. }  
  9. $end = getmicrotime();  
  10. echo $end – $start;  
  11.   
  12. function getmicrotime(){  
  13.     list($usec,$sec)=explode(" ",microtime());  
  14.     return ((float)$usec+(float)$sec);  
  15. }  
变量未初始化的循环代码如下:
PHP代码
  1. $start = getmicrotime();  
  2. error_reporting(E_ALL | E_STRICT);  
  3. ini_set('display_errors', false);  
  4. ini_set('log_errors', false);  
  5.   
  6. for ($i=0; $i < 10000000; $i++) {   
  7.     $foo=$var;  
  8. }  
  9. $end = getmicrotime();  
  10. echo $end – $start;  
  11.   
  12. function getmicrotime(){  
  13.     list($usec,$sec)=explode(" ",microtime());  
  14.     return ((float)$usec+(float)$sec);  
  15. }  
测试成绩:
初始化:平均 5.28 秒
未初始化:平均 17.2 秒
性能差距:3.25倍
 
测试2:
在关闭错误显示的情况下,测试数组索引使用引号和非引号引用在10000000次循环中的性能
数组有引号索引代码如下:
PHP代码
  1. $start = getmicrotime();  
  2. error_reporting(E_ALL | E_STRICT);  
  3. ini_set('display_errors', false);  
  4. ini_set('log_errors', false);  
  5.   
  6. $array=array('foo'=>'baa');  
  7. for ($i=0; $i < 10000000; $i++) {   
  8.     $foo=$array['foo'];  
  9. }  
  10. $end = getmicrotime();  
  11. echo $end – $start;  
  12.   
  13. function getmicrotime(){  
  14.     list($usec,$sec)=explode(" ",microtime());  
  15.     return ((float)$usec+(float)$sec);  
  16. }  
 数组无引号索引代码如下:
PHP代码
  1. $start = getmicrotime();  
  2. error_reporting(E_ALL | E_STRICT);  
  3. ini_set('display_errors', false);  
  4. ini_set('log_errors', false);  
  5.   
  6. $array=array('foo'=>'baa');  
  7. for ($i=0; $i < 10000000; $i++) {   
  8.     $foo=$array[foo];  
  9. }  
  10. $end = getmicrot

面试时,如何向公司提问?

 原文:http://voltsteve.blogspot.com/2011/12/assessing-company-questions-you-need-to.html

原作者:硅谷招聘经理Steve Buckley

  很多人将面试看作一种单向选择,事实上,面试是一种双向选择:不仅是公司挑选你,也是你挑选公司。面试就是为双方提供互相了解的机会,公司在评估你,你也在评估公司。
  面试官也知道这一点,所以他们有心理准备,期待你提出问题,并且会做出回答。所以,面试时不要浪费向公司提问的机会。而且,你主动提问,表明你比较重视这个职位,会加深面试官对你的印象,可能会提高面试的成功率。
 
有一些注意点,你需要知道:
  1. 面试之前,一定要做准备,多了解公司的情况。
  2. 你提出的问题,应该围绕"这份工作是否合适我"这个中心点,其他与应聘关系不大的问题,不宜多问。
  3. 提问的时候,要自然放松,不要害羞,就把它当作普通的聊天。你要表现出对公司的真诚兴趣。
  4. 提问要直接了当,不要绕圈子。提出问题之后,你要保持安静,让面试官多说话。
  5. 面试官回答的时候,你可以做笔记,或者事先询问能不能做。笔记必须简短,你的大部分时间,要用来全神贯注倾听面试官的回答,并与其有眼神的交流。
  6. 面试结束后一周内,最好打一个电话或发一封邮件,了解公司对你的反馈意见。即使面试失败,你不妨也问一下原因,这会有助于你以后的面试。
 
下面是一些你可以问的典型问题。
 
问题一:你们为什么要招聘这个职位?
Q1: Why are you currently recruiting for this position?
这个问题会使得面试官开始谈论当前的项目,或者谈论前一位离职人员。无论哪种情况,都会让你了解,一些与你最密切相关的公司情况。
 
问题二:你们的新员工多吗?
Q2: Do you have many new staffs?
这个问题起一个过渡作用,使得谈话导向公司内部的情况。但是,它本身也能说明一些问题。如果公司成立已经超过四年,又没有新项目,但是新员工却很多,这往往说明公司文化不是很健康。
 
问题三:你们公司(团队)目前面临的最大挑战是什么?
Q3: What are the biggest challenges your team are facing right now?
如果面试官开始谈论一些具体的技术问题,这很好;如果他的回答是项目时间紧迫,或者需要更多的资金,那你就要小心一点了,公司管理上面可能有问题。
 
问题四:什么新技术(编程语言)是你们未来希望采用的?
Q4: What technologies/languages would you like to see your team adapt to that aren't currently being utilised?
如果你申请的是技术职位,面试官恰巧又是技术负责人,那么这个问题将会非常合适。你会对公司的技术路线有所了解和准备,一旦入职,就能更好地适应公司的需要。
 
问题五:在业务方面,有没有什么地方是你们不满意的,未来想要改进的?
Q5: Few companies, if any, are 100% satisfied with the way their business is operating. If you could simply flick a switch to fix it, what one thing would you change?
很少有公司,会百分之百满意自身的现状,即使那些状况很良好的公司也是如此。这个问题可以让你对公司管理层的关注重点和担忧之处,有所了解。
 
问题六:我申请的这个职位,对公司的业务有何影响?
Q6: If you struggle to fill the position I have applied for, what impact would that have on the business?
这个问题会让你了解自己在公司的角色,以及你的岗位对公司是否重要。
(全文完)
 
根据国情及我的经验,我增加几个到人事面那该问的问题,如有不当,请各位指正:
 
1、社保什么时候开始交?
很正规的单位是入职就交,有些单位是转正后补交试用期的(其实这样做是违法),尽量要求公司就交社保,试用期不给交的单位别考虑了。
2、五险一金齐全吗?有没有公积金?
在公积金不是必缴的城市有公积金的单位福利都应该不错。
3、加班怎么处理?
加班按规定算加班工资是最好的,有些单位是调休,连调休都不给的单位就别考虑了(高管岗位不适用,高管本身就有他的特殊性)。
4、发工资按时吗?
相关法规规定工资是要在10号之前发上月的工资,有些单位会稍晚几天,但是只要按时发,不拖欠也还可以接受,经常拖欠的,说明公司财务状况不好,或者不重视员工权益。

 

无限分类的树状迭代方法

 用RecursiveIteratorIterator类来实现,详见代码:

PHP代码
  1. <?php header('Content-Type: text/html; charset=utf-8');?>  
  2.    
  3. <style>  
  4.    
  5.     ul {list-style-type: circle}  
  6.    
  7. </style>  
  8.    
  9. <?php  
  10. $array = array(   
  11.     "苹果" => array (   
  12.         "一代" => array(   
  13.             "苹果1""苹果1S"   
  14.         ),   
  15.         "二代" => array(   
  16.             "苹果2"array(   
  17.             "苹果2 8G","苹果2 16G"   
  18.         ),   
  19.         ),   
  20.         "三代" => array()   
  21.     ),  
  22.     "三星" => array(   
  23.             "galaxy S4""galaxy S5"   
  24.         ),   
  25. );  
  26.    
  27. class RecursiveListIterator extends RecursiveIteratorIterator {   
  28.    
  29.     public $tab = " ";   
  30.    
  31.     public function beginChildren() {   
  32.         if (count($this->getInnerIterator()) == 0) { return; }   
  33.         echo str_repeat($this->tab, $this->getDepth()), "<ul>
    "
    ;   
  34.     }   
  35.    
  36.     public function endChildren() {   
  37.         if (count($this->getInnerIterator()) == 0) { return; }   
  38.         echo str_repeat($this->tab, $this->getDepth()), "</ul>
    "
    ;   
  39.         echo str_repeat($this->tab, $this->getDepth()), "</li>
    "
    ;   
  40.     }   
  41.    
  42.     public function nextElement() {   
  43.         // 显示叶子节点  
  44.         if ( ! $this->callHasChildren()) {   
  45.             echo str_repeat($this->tab, $this->getDepth()+1), '<li>'$this->current(), "</li>
    "
    ;   
  46.             return;   
  47.         }   
  48.    
  49.         // 显示分支标签   
  50.         echo str_repeat($this->tab, $this->getDepth()+1), '<li>'$this->key();   
  51.         echo (count($this->callGetChildren()) == 0) ? "</li>
    "
     : "
    "
    ;   
  52.     }   
  53. }   
  54.    
  55. $it = new RecursiveListIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST); &