Mac 安装LAMP

Mac 集成环境MAMP.

http://www.mamp.info/en/downloads/

发表在 其它 | 留下评论

我的Drupal之路

之前的我

10年刚刚毕业出来以后学校将我分配到慈溪的一家网站公司,主要负责扣图,拍照片. 上传图片等打杂工作,在一次机会看到公司有同事在使用PHP编程觉得蛮有意思(其实是蛮牛B的, 学了可以装一下),于是就开始我的PHP之路,当时我任何东西都是自己手写,爱好各种牛X的技术。比如那时jQuery比较流行,于是就用JQuery做了很多的效果,这是我第一个网站: http://www.cxlxtx.com/. 纯手工开发的网站,任何一段代码函数, 可以说是我学习PHP的一个结晶。

之后工作换到了宁波,在宁波的公司里面学了不少东西(GIT, Linux, Codeigniter. OOP.. 等强大又装B的东西). 公司里面都是技术狂,跟着技术狂一起工作你懂的,不努力都难。我读过Codeigniter源代码,这是一个简单又是当时MVC框架的一个代表作之一,从中我的PHP功底提升得非常大。

来到上海

12年8月后, 我离开了那家公司第一次来上海这边找工作,上海是个好城市, 来到上海这边我最希望能在这边先找份工作稳定下来, 信心满满的我面试了很多家基本都过了. 我完全就是想先稳定一下。在找工作的第三天,也是我快做选择的时候. 我决定再去某某招聘网站上看看工作。很熟悉的输入了PHP招聘,又一页一页的往后面翻。突然看到有公司招Drupal(由于上家公司两位比较大牛的师傅一直提起这个东西很了不起,所以早在思想里面根深蒂固). 无意识下就点了过去。简直亮瞎了我的双眼。招Drupal研发工程师, 你可以不会Drupal. 我们公司提供免费培训。这么好的事怎么就落在了我的身上,就这样我接到了这家公司的面试通知.

关于面试

刚进公司准备面试,客服人员告诉我老板正在开会需要我等一下。操! 我看到了什么。老板是老外! 我当时吓尿了. 我当时英语真的极差跟没学过似的。我怕太尴尬当时本来就打算走了. 一系列的心理斗争以后老板开完会了。老板在和我说中文,我当时惊呆了。当然以我强厚的PHP功底面试是非常成功的,给我出的几个PHP面试题我都做得很棒,为了能得到这份工作我要了一份最低的工资。 就这样我成功面试上了这份工作,就这样我认识我的Drupal导师大卫 – 法国人

培训

面试时老板告诉我叫我第二天10点准时来公司(第二天还是周末),我们要培训, 第二天我来得很早, 9点就来到公司了, 大卫10半才到公司(后来才了解到法国人拖延症比较严重, 经过多次这样的事, 我吸取教训,知道大卫说的10点就是10点半。以此类推 + 半个小时)。

我的第一天培训开始了,大卫先是给我讲了核心模块的介绍还有关于Drupal内容的添加和使用还有内容类型的基本使用, 我只能说头晕眼花,由于我英文不好。而大卫又是一半中文一半英文,跳得比较严重. 不大容易适应. 幸运的是我坚持下来了. 接下来的时间就是正常上班,周6培训Examples模块, hook的使用, Menu、Form、Field、Entity、Rules、Views、Theme等模块的学习和扩展的开发。每学一样东西大卫都会叫我们写一个案例. 基础学完了以后, 就是去学习一些简单模块的。大卫希望我们只要看一下源代码就知道这个模块是做什么的. 大概是3个月的左右的时间吧。 我觉得终于算是一个真正的Drupal开发者了。

第一个模块(Baidu map)

http://drupal.org/project/baidu_map

一次机会了解到官方竟然还没有百度地图这个模块, 于是决定开发这个模块, 当然此模块不是我可以凭空想出要怎么开发的。 任何一件好的作品都会先有一个beta版(来自黑客与画家),这次我参考的模块是alimap(作者希望之翼)当时这个模块还没有提交。我参考了他的功能和实现,采用了强大的Copy和Paste后,再将所有的文件名从alimap改成了baidu_map, 然后参考官方baidu_map的API。开始修改每一个接口的代码使其符合百度地图的标准, 此模块的算是可以正常运行了。到现在为止我只花了一个星期,总算心花怒放。还来了一次小小的自虐(我总算开发出我的第一个模块了)。接着大卫替我审核,然后我们就一起修改这个模块,后来发现开发一个模块最麻烦的不是写代码,而是:

  1. 注释、代码标准和Drupal的标准. 只要这样才能过大卫的关
  2. 官方的审核代码(此处最少需要一个月), 流程非常复杂

大卫在审核我代码的时候他会问我每一段代码为什么要这样写?是否符合标准, 比如一段百度地图官方提供的APP KEY. 在我的眼里就是一段字符串。但是我们有准备写正则表达式来验证此App Key是否符合标准,此时大卫就问我: 这段App key只有小写字母吗? 会不会只有A-D或者a-d? 或者只是只有大写字母(连官方都没有给出这样的文档)。一切的一切. 通过了后才会进行下一步。加上大卫的拖延者和工作上的事此模块总共用了三个月才提到到官方。

此模块只是有感悟比较深的作品之一,我还开发过其它的模块比如(Views Number Field Calc). 此模块是用于计算Views 两个字段的结果,并其结果支持排序和过滤。

我还成为了Nice menus的管理员,这是大卫为我申请的,后来由于Nice menus作者好像不干了。官方的人就直接把作者改成了我的名字. 通过这个模块的维护我也算是彻底了解了开源精神和Drupal这么强大的作品是怎么来的。

之后又成为了Views Slideshow的管理员

关于Drupal模块中文社区

www.drupalmodule.cn
当时作为一个像我这样的新手,遇到一个新的模块我觉得我最需要的就是一段简单的文字告诉这个模块是做什么,好让我开始去研究模块。但是我觉得好的中文资料实在不怎么样, 或者就是乱成一团。此网站开始的目的就是可以让新手们能够快速了解和使用一个新模块, 自己弄了足足3天才把这个网站做完和上线。经过自己的努力上面已经有了快拉近200个模块的使用和介绍。

关于Drupal聚会

在圈子里面还有一个最好的就是聚会,每隔一段时间都会有一次聚会,在聚会中我认识了龙马、希望之翼这样的大神。当然我更愿意叫他们大哥,每次聚会都会有人来分享东西(我也参加过多次分享)。 聚会我觉得最重要的是结交朋友,每次都能认识很多不同的新朋友。

关于工作

工作是很严谨的,在工作中的大忌不到万不得已不得修改核心代码和第三方模块的代码,一切都得按照官方的标准来,比如你遇到一个问题,你需要去官方找一下这个问题有没有解决,找一下有没有相应的Patch. 如果这个问题还不存在那么你需要给官方提出这个问题。然后跟进.必要的时候你需要去阅读核心代码来解决一个问题,有时只是一个小问题。但是大卫需要你用正确的方法来做, 我只有说跟着大卫在一起工作是非常开心的事, 那种做事的态度, 你会找到真正做程序员的乐趣。

关于大卫

他是我最尊敬的人,也是我的导师,是一位非常好的导师。大卫的拖延症比较严重,做事非常认真仔细,他很在乎一个符号要怎么写更好? 或者这里的字体可以要加粗一下会更好, 每一件我们看起来非常的事在他眼里面却是很重要. 要达到非常标准他才满意。 就拿一件普通的事来说吧,如果他叫你做一个功能。你使用下三烂的手段快速实现,他会直接你骂一顿.就是因为如此我刚刚开始的时候还抱怨过他怎么这么罗嗦,后来我才知道他是对的. 这也是我最欣赏他的地方,能学到很多东西. 不仅仅是技术。还有想问题的方法和思想。

发表在 Drupal | 留下评论

Drupal 获取js后面的Query字符串

当你把开你的页面, 你总是可以看到每一个js文件后面都会有这样的一个ID: ?nac714

  1. <script type="text/javascript" src="http://localhost/example/misc/drupal.js?nac714"></script>

这是id在每次清空Drupal缓存的时候会重新生成, 当重新生成了浏览器就会认为你的文件更新了, 从而重新去下载你的js缓存

使用以下这段代码可以获取到当前的这个缓存ID

  1. variable_get('css_js_query_string', '0');
发表在 Drupal | 评论关闭

德雷福斯模型自我定位和技能获取过程

德雷福斯模型

德雷福斯模型是一种衡量人们工作方法和能力,反省并提高专业技能的层级模型。用于自己我水平的定位, 它把你所在技能领域水平划分成为五个阶段.

新手

新手在该技能领域经验很少甚至没有经验. 这里提到经验, 指的是通过实施某项技术促进了思维的改变.举个反例, 可以能一个开发人员声称拥有10年工作经验, 但实际上只是一年的经验重复了9次, 那么这就不算是经验.
新手非常在乎他们能否成功. 没有太多经验指导他们, 他们不知道自己是对是错, 新手不是特别想要学习, 他们只是想实现一个立竿见影的目标, 他们不知道如何应付错误. 所以出错的时候他们非常慌乱. 他们做事需要一份完整的指令清单, 一份参照物和规则.

高级新手

一旦过了新手阶段, 人们开始以高级新手的角度看待问题. 高级新手能够开始多多少少摆脱固定的规则. 他们可以独自尝试任务. 但仍然难以解决问题.
他们想要快速的获取解决问题的信息. 不想为一些问题寻根究底或者重新去学习一下以前的基础知识. 高级新手能够根据过去的经验, 逐步在正确的情境中采纳建议, 但比较吃力. 同时他们开始形成一些总体的原则. 但不是”全貌”. 他们没有全面的理解, 而且的确不想有.

胜任者

胜任者能够建立问题概念模型, 并有效地使用它们. 他们可以独立解决自己遇到的问题, 并开始考虑如何解决新的问题. 那些他们之前从来没有遇到的问题, 他们开始寻求专家的意见, 并有效利用.
处于这一水平的人通常被认为”有主动性”和”足智多谋”, 他们是团队里的好人, 既可以指导新手, 也不会经常骚扰专家

精通者

精通水平的从业者需要全面的思维, 他们将围绕这个技术, 寻找并想了解更大的框架. 对于简化的信息, 他们会非常泪丧.
处于精通水平的从业人员有一项重大突破. 他们能够纠正以往不好的工作表现,他们会反思以前是如何做的. 并修改其做法. 期望下次做得更好

专家

专家是各个领域知识和信息的主要来源。他们总是不断地寻找更好的方法和方式去做事。他们有丰富的经验,可以在恰当的情境中选取和应用这些经验。他们著书、写文章、做巡回演讲。他们是当代的巫师。
专家凭直觉工作, 并不需要理由. 他们总是可以用直觉告诉你这个问题出现在哪里, 这带来一些非常有趣的影响, 并提出了一些重要的问题

技能获取过程

  • 模仿: 原模原样的照抄
  • 吸收: 思考其中的意义
  • 创建: 达到更深入的理解
发表在 做更好的自己, 其它, 程序员的思维修炼 | 一条评论

PHP 目录查找. 支持多层目录

现在我有一个需求, 需要一个目录中找出. index.html 或者 index.htm文件,

  1. /**
  2.  * 目录扫描. 返回数组.
  3.  */
  4. function _directory_map($source_dir, $directory_depth = 0, $hidden = FALSE) {
  5.   if ($fp = @opendir($source_dir)) {
  6.     $filedata = array();
  7.     $new_depth = $directory_depth - 1;
  8.     $source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  9.  
  10.     while (FALSE !== ($file = readdir($fp))) {
  11.       // Remove '.', '..', and hidden files [optional]
  12.       if (!trim($file, '.') OR ( $hidden == FALSE && $file[0] == '.')) {
  13.         continue;
  14.       }
  15.  
  16.       if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir . $file)) {
  17.         $filedata[$file] = _directory_map($source_dir . $file . DIRECTORY_SEPARATOR, $new_depth, $hidden);
  18.       }
  19.       else {
  20.         $filedata[] = $file;
  21.       }
  22.     }
  23.  
  24.     closedir($fp);
  25.     return $filedata;
  26.   }
  27.   return FALSE;
  28. }
  29.  
  30. /**
  31.  * 扫描Index.html
  32.  */
  33. function search_html_index($dirarrays, $current_dir, $scan_file) {
  34.   static $result = false;
  35.   foreach ($dirarrays as $dir => $name) {
  36.     if (is_array($name)) {
  37.       search_html_index($name, $current_dir . $dir . '/',  $scan_file);
  38.     }
  39.     else {
  40.       if(array_search($name, $scan_file) !== FALSE) {
  41.         $index = array_search($name, $scan_file);
  42.         $result = $current_dir . $scan_file[$index];
  43.       }
  44.       if ($result) {
  45.         break;
  46.       }
  47.     }
  48.   }
  49.   return $result;
  50. }
  51.  
  52.  
  53. ## 执行程序
  54.  
  55. $extpath = './mydir/';
  56.  
  57. $file = search_html_index(_directory_map($extpath), $extpath, array(
  58.               'index.html',
  59.               'index.htm'
  60.             ));
  61.  
  62. var_dump($file);
发表在 PHP | 评论关闭

Web 缓存

中文文档: http://www.cnblogs.com/xyjsw/archive/2010/01/27/1657825.html
英文文档: https://www.mnot.net/cache_docs/#DEFINITION

疑问1: 如果缓存了还会问服务器发起请求吗?

答:不会, 当缓存了客户端就不用再向服务器发送请求了. 直接判断缓存中的过期时间就好了
304的是代理缓存啊,是在服务器端做缓存的,服务器端会缓存完整的页面
304的是代理缓存啊,是在服务器端做缓存的,服务器端会缓存完整的页面 
304本身是表示资源没有变化,不管是不是用了缓存

会发起请求, 比如一个css在本地有缓存,会向服务器发起请求,如果缓存还有效,那么直接返回 304,但不进行内容的传输.
另类回答: 服务器端可以设置过期时间,发送到客户端浏览器的时候,会带入头信息里面,浏览器根据头信息判断是否过期,如果是强制刷新的应该是浏览器会忽略过期时间

疑问2. http://demo.com/style.css?ver=1.2.3 比如第一次向服务器发请一个这样的请求. 保存的缓存是 Style.css还是 style.css?ver=1.2.3 ?

答: 缓存是style.css?ver=1.2.3

问: http://demo.com/style.css?ver=1.2.3 如果第二次再发起这样的请求为什么会强制更新缓存?

答: 不会. 1.2.3这个参数当变化的时候会重新更新缓存

问: 服务器端的缓存是保存在哪? 内存还是文件? 比如PHP中的header函数

回答: apc 默认是磁盘 ,  memcache 是内存, php header是浏览器缓存, 代理缓存某种意义上也是浏览器的缓存吧,因为内容已经从应用服务器出来了。

问: 如果我对当前页面设置了缓存, 只是缓存DOM吗? 还是会缓存当前页面的资源(Image, CSS, Javascript和Video ETC… )

等待回答.
发表在 其它 | 评论关闭

jQuery 图片加载重试

  1. <!DOCTYPE html>
  2. <html>
  3.   <head>
  4.     <meta charset="UTF-8">
  5.     <title>DEMO</title>
  6.     <script type="text/javascript" src="../jquery-1.11.1.min.js" isjquery="jquery"></script>
  7.     <script type="text/javascript">
  8.     $(function() {
  9.       var imgs = $("img");
  10.       for (i = 0; i < imgs.length; i++) {
  11.         $(imgs[i]).attr("original", $(imgs[i]).attr("src"));
  12.         $(imgs[i]).attr("src", "loading.gif");
  13.       }
  14.  
  15.         imgs.each(function() {
  16.          var self = $(this);
  17. //       var imgsrc = self.attr("original");
  18.           loadimg(self);
  19.         });
  20.  
  21.         function loadimg(self) {
  22.           if (!self.loaded) {
  23.             $("<img />")
  24.                     .bind("load", function() {
  25.                       self.loaded = true;
  26.                       $(self)
  27.                               .attr("src", $(self).attr("original"));
  28.                     })
  29.                     .attr("src", $(self).attr("original"))
  30.                     .error(function() {
  31.                       // 如果发生错误了就重新加载. 每2秒重试一次
  32.                       setTimeout(function(){
  33.                         loadimg(self);
  34.                       }, 2000);
  35.                     });
  36.           }
  37.         }
  38. })
发表在 JavaScript | 评论关闭

Mysql 忘记密码

编辑/etc/my.cnf, 在[mysqld]的段中加上一句:skip-grant-tables

  1. [mysqld]
  2. datadir=/var/lib/mysql
  3. socket=/var/lib/mysql/mysql.sock
  4. skip-grant-tables

重新mysql

  1. #/etc/init.d/mysqld restart

进入mysql修改密码

  1. #mysql
  2. mysql> use mysql;
  3. mysql> UPDATE user SET Password = password ('newpassword') WHERE User = 'root' ;

最后删除/etc/my.cnf中的skip-grant-tables并且重启mysql

发表在 Linux | 评论关闭

Drupal 8 开发API

https://www.drupal.org/developing/api/8

路由
配置
插件
Javascript
区块(Block)
缓存(Cache)
Entity APi
表单
菜单(Menu)
迁移
第三方库(JS, CSS)
数据序列化
Services and dependency injection in Drupal 8
状态
Typed Data
验证 API
Tour API

发表在 Drupal 8 | 评论关闭

Git 删除commit提交

  1. git reset HEAD~1      #删除上一次提交的
  2. git reset ORIG_HEAD  #回退到上一步
  3. git reset HEAD ./  将存在缓冲区的内容删除
发表在 Git | 评论关闭