Posts Tagged ‘PHP’

Nginx + PHP FastCGI on Ubuntu 傻瓜式 安装 配置 指南


17 9月
最近在公司都用的ubuntu,升级到10.0.4后发现PHP自动就到5.3了,但是某些杯具项目只能在5.2上面跑,于是折腾了很久,最后选择删光原有的环境装了Zend Server... 好吧,那是另外一个故事了。 大家知道我是个“最新版本控”,所以5.3还是要玩的,于是想到了Nginx这东东一直想弄还没机会搞,于是有了这篇傻瓜式记录。之前也看了张宴之类的大师怎么装这个环境,不过貌似超复杂,像我这在linux水平很初级的同学基本看完就晕了。 于是google了一下,嘿,还真找到了一些英文的资料,于是挑重点的翻译在此,以备不时之需。废话至此,以下正文: 我首先装的是nginx,很容易,一句话: aptitude install nginx 然后FastCgi: aptitude install php5-cgi 恭喜,如果没有报错的话,一切就完成大半了。超傻瓜吧。。。 实验一下: php-cgi -b 127.0.0.1:9000 有报错的话自己处理,反正我没出问题。 好,下面是关键部分,怎么让这东西自动启动。反正作为新手的我对这种感觉还是很神奇的。 vi /etc/init.d/php-fastcgi 把下面这些复制过去:
  1. #!/bin/bash
  2. BIND=127.0.0.1:9000
  3. USER=www-data
  4. PHP_FCGI_CHILDREN=15
  5. PHP_FCGI_MAX_REQUESTS=1000
  6.  
  7. PHP_CGI=/usr/bin/php-cgi
  8. PHP_CGI_NAME=`basename $PHP_CGI`
  9. PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND"
  10. RETVAL=0
  11.  
  12. start() {
  13.       echo -n "Starting PHP FastCGI: "
  14.       start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS
  15.       RETVAL=$?
  16.       echo "$PHP_CGI_NAME."
  17. }
  18. stop() {
  19.       echo -n "Stopping PHP FastCGI: "
  20.       killall -q -w -u $USER $PHP_CGI
  21.       RETVAL=$?
  22.       echo "$PHP_CGI_NAME."
  23. }
  24.  
  25. case "$1" in
  26.     start)
  27.       start
  28.   ;;
  29.     stop)
  30.       stop
  31.   ;;
  32.     restart)
  33.       stop
  34.       start
  35.   ;;
  36.     *)
  37.       echo "Usage: php-fastcgi {start|stop|restart}"
  38.       exit 1
  39.   ;;
  40. esac
  41. exit $RETVAL
加上执行权限: chmod +x /etc/init.d/php-fastcgi 跑跑看: /etc/init.d/php-fastcgi start 都没问题的话: update-rc.d php-fastcgi defaults 大功告成。 改nginx配置:(/etc/nginx/nginx.conf) 加上类似这样的东西:
server {
        listen          80;
        server_name     example.com;

        access_log      /var/log/nginx/example.com.access_log;
        error_log       /var/log/nginx/example.com.error_log warn;

        root            /var/www/example.com/public;

        index           index.php index.html;
        fastcgi_index   index.php;

        location ~ \.php {
                include /etc/nginx/fastcgi_params;
                keepalive_timeout 0;
                fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_pass    127.0.0.1:9000;
        }
}

ok,一切完成。

参考文章:
http://tomasz.sterna.tv/2009/04/php-fastcgi-with-nginx-on-ubuntu/
http://wiki.nginx.org/NginxHttpFcgiModule
——————————补充———————————— 有关权限,原来用apache的时候只要再httpd.conf里面改user和group就可以控制启动服务的用户和组了。 但是,用nginx+fastcgi的时候,需要改2个地方,nginx的那个都能想到,另外就是上面那段/etc/init.d/php-fastcgi脚本开头的,user也要改,我今天就忘记改了,被妖了半天,杯具。。。

Sphinx conf infix, Sphinx api total vs total found, quorum match vs extended2 mode


14 5月
最近公司使用sphinx中碰到的一些问题,做下记录。
针对类似搜索“南京”时,无法搜出带有“南京西路”的数据问题的解决方案。
第一步设置相应的.conf文件,修改如下属性:
enable_star = 1 #开启传说中的wildcard syntax模式,详见手册9.2.19. enable_star
min_infix_len  = 1 #设置最短匹配词长,详见手册9.2.16. min_infix_len
infix_fields = estate_name,estate_address #要启用infix的字段,必须填!因为infix会加大开销,如果不填这个字段,会对所有字段做infix,那将是很恐怖的开销!详见手册9.2.18. infix_fields
最后一个参数,手册上没有提到的,如果没有设置正确会对中文造成无解的属性:
charset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z,\ A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6,\ U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101,\ U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109,\ U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F,\ U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, \ U+0116->U+0117,U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D,\ U+011D,U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, \ U+0134->U+0135,U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, \ U+013C,U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, \ U+0143->U+0144,U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, \ U+014B,U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, \ U+0152->U+0153,U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159,\ U+0159,U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, \ U+0160->U+0161,U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, \ U+0167,U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, \ U+016E->U+016F,U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175,\ U+0175,U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, \ U+017B->U+017C,U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, \ U+0430..U+044F,U+05D0..U+05EA, U+0531..U+0556->U+0561..U+0586, U+0561..U+0587, \ U+0621..U+063A, U+01B9,U+01BF, U+0640..U+064A, U+0660..U+0669, U+066E, U+066F, \ U+0671..U+06D3, U+06F0..U+06FF,U+0904..U+0939, U+0958..U+095F, U+0960..U+0963, \ U+0966..U+096F, U+097B..U+097F,U+0985..U+09B9, U+09CE, U+09DC..U+09E3, U+09E6..U+09EF, \ U+0A05..U+0A39, U+0A59..U+0A5E,U+0A66..U+0A6F, U+0A85..U+0AB9, U+0AE0..U+0AE3, \ U+0AE6..U+0AEF, U+0B05..U+0B39,U+0B5C..U+0B61, U+0B66..U+0B6F, U+0B71, U+0B85..U+0BB9, \ U+0BE6..U+0BF2, U+0C05..U+0C39,U+0C66..U+0C6F, U+0C85..U+0CB9, U+0CDE..U+0CE3, \ U+0CE6..U+0CEF, U+0D05..U+0D39, U+0D60,U+0D61, U+0D66..U+0D6F, U+0D85..U+0DC6, \ U+1900..U+1938, U+1946..U+194F, U+A800..U+A805,U+A807..U+A822, U+0386->U+03B1, \ U+03AC->U+03B1, U+0388->U+03B5, U+03AD->U+03B5,U+0389->U+03B7, U+03AE->U+03B7, \ U+038A->U+03B9, U+0390->U+03B9, U+03AA->U+03B9,U+03AF->U+03B9, U+03CA->U+03B9, \ U+038C->U+03BF, U+03CC->U+03BF, U+038E->U+03C5,U+03AB->U+03C5, U+03B0->U+03C5, \ U+03CB->U+03C5, U+03CD->U+03C5, U+038F->U+03C9,U+03CE->U+03C9, U+03C2->U+03C3, \ U+0391..U+03A1->U+03B1..U+03C1,U+03A3..U+03A9->U+03C3..U+03C9, U+03B1..U+03C1, \ U+03C3..U+03C9, U+0E01..U+0E2E,U+0E30..U+0E3A, U+0E40..U+0E45, U+0E47, U+0E50..U+0E59, \ U+A000..U+A48F, U+4E00..U+9FBF,U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF, \ U+2F800..U+2FA1F, U+2E80..U+2EFF,U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF, \ U+3040..U+309F, U+30A0..U+30FF,U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF, \ U+3130..U+318F, U+A000..U+A48F,U+A490..U+A4CF
额,不要惊慌,照抄就行了,把中文的都包括进去就ok了。
完了后,停掉searchd,重建索引就好。
之后,在搜索的时候,就可以使用类似'*南京*'、'*南京'、'南京*'之类的query,去当类似sql 的like用了,OVER。
——————————我是分割线———————————————— 当我们使用API从sphinx执行了一个查询之后,接口会返回一个数组。在这个数组中存在total_found和total两个值。 当查询出的结果数小于sphin中配置的最大返回结果数(默认为1000)时,这两个值是相等的。 而查询出的结果数大于sphin中配置的最大返回结果数(默认为1000)时,total_found的值是在sphinx中所有满足搜索条件的结果数,而total返回的是sphin中配置的最大返回值。 因此,在分页等需要所有满足搜索条件的结果数的时候,应该使用total_found的值。 ——————————我这个分割线又来了———————————— 在使用@(column1,column2,column3) "关键词1 关键词2 关键词3 关键词4 关键词5 ... 关键词N"/2这种参数的时候,搜索模式应该设置为SPH_MATCH_EXTENDED模式,而不能用传说中效率更高的SPH_MATCH_EXTENDED2模式,否则将会发生不可预料的事情。。。(沿用sphinx官方风格比喻,就是可能屏幕里面跳出来一只大猩猩,对着你仍酒桶。) END P.S. 很多其他sphinx的常见问题在官方FAQ中都有,比如filter中要用or的话,怎么解决,FAQ中就很牛叉。膜拜一下。 ————————————2010/5/18补充—————————————————— 发现上周提出的infix方式与现有分词索引的方式起了比较大的冲突(用了infix就基本无法用分词了),于是顺道回顾了一下张宴大师的博客,发现他原来早碰到过这个问题了。而他的解决方案明显非常不错。直接贴了: 1、一元分词和中文分词的结合:  ①、一元分词位于索引更新模块。Sphinx索引引擎对于CJK(中日韩)语言(必须是UTF-8编码)支持一元切分,假设【反恐行动是国产主视角射击网络游戏】这段文字,Sphinx会将其切成【反 恐 行 动 是 国 产 主 视 角 射 击 网 络 游 戏】,然后对每个字建立反向索引。如果用这句话中包含的字组成一个不存在的词语,例如【恐动】,也会被搜索到,所以搜索时,需要加引号,例如搜索【"反恐行动"】,就能完全匹配连在一起的四个字,不连续的【"恐动"】就不会被搜索到。但是,这样还有一个问题,搜索【"反恐行动游戏"】或【"国产网络游戏"】就会搜索不到。对于这个问题,采用位于搜索查询模块的中文分词来处理。 sphinx.conf配置文件中关于UTF-8中文一元分词的配置如下: ...省略... index t_source_main { source                  = t_source_main path                    = /data0/search/sphinx/data/t_source_main docinfo                 = extern mlock                   = 0 morphology              = none min_word_len            = 1 charset_type            = utf-8 min_prefix_len          = 0 html_strip              = 1 charset_table           = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F ngram_len               = 1 ngram_chars             = U+3000..U+2FA1F } ...省略... ②、中文分词位于搜索查询模块。搜索“反恐行动游戏”、“国产网络游戏”,先调用独立的中文分词系统,分别切分为“反恐行动 游戏”、“国产 网络游戏”,这时候,再给以空格分隔的词语加上引号,去Sphinx搜索【"反恐行动" "游戏"】或【"国产" "网络游戏"】,就能搜索到这条记录了。中文分词词库发生增、删、改,无需重建整个Sphinx搜索索引。 henry解释:也就是说,做索引的时候,不用词库去分词,而是沿用sphinx原来的一元分词法。在搜索的时候才用分词去做词组的完全匹配搜索。另外一个原因,用原版的一元分词索引速度也要快很多,在他的博文中提到:   “我的环境是10000转的SAS硬盘,如果换成15000转的硬盘,速度要更快,Sphinx官方给出的索建引速度为10Mbytes/秒。原版的sphinx一元分词创建索引速度在5.5M/秒以上,而打了LibMMSeg中文分词补丁的Sphinx创建索引速度只有300KB/秒,所以采用原版的sphinx 0.9.9能够保证频繁更新情况下的索引实时性。一元分词的索引的数据量会大一些,但可以通过sphinx分布式索引来解决搜索效率问题。”   希望对大家有所借鉴,原文地址http://blog.s135.com/sphinx_search/

zendframework session memcached 应用改进


26 2月
曾经转载过的一篇文章中提到的使用方法,似乎对其中某台memcached服务器down掉后的处理比较欠缺一些,貌似会报出异常导致无法正常运行,可能是原文作者当时memcached还处于一个比较早的阶段,还未有相应的错误处理,经研究后将其修改如下,解决了相应问题:
  1. <?php
  2. require_once ‘Zend/Session.php’;
  3. require_once ‘Zend/Config.php’;
  4.  
  5. class Zend_Session_SaveHandler_Memcached implements Zend_Session_SaveHandler_Interface
  6. {
  7.     const LIFETIME          = ‘lifetime’;
  8.     const OVERRIDE_LIFETIME = ‘overrideLifetime’;
  9.     const MEMCACHED            = ‘memcached’;
  10.     protected $_lifetime = false;
  11.     protected $_overrideLifetime = false;
  12.     protected $_sessionSavePath;
  13.     protected $_sessionName;
  14.     protected $_memcached;
  15.     /**
  16.      * Constructor
  17.      *
  18.      * $config is an instance of Zend_Config or an array of key/value pairs containing configuration options for
  19.      * Zend_Session_SaveHandler_Memcached . These are the configuration options for
  20.      * Zend_Session_SaveHandler_Memcached:
  21.      *
  22.      *
  23.      *      sessionId       =>  The id of the current session
  24.      *      sessionName     => The name of the current session
  25.      *      sessionSavePath => The save path of the current session
  26.      *
  27.      * modified            => (string) Session last modification time column
  28.      *
  29.      * lifetime          => (integer) Session lifetime (optional; default: ini_get('session.gc_maxlifetime'))
  30.      *
  31.      * overrideLifetime => (boolean) Whether or not the lifetime of an existing session should be overridden
  32.      *      (optional; default: false)
  33.      *
  34.      * @param Zend_Config|array $config      User-provided configuration
  35.      * @return void
  36.      * @throws Zend_Session_SaveHandler_Exception
  37.      */
  38.     public function __construct($config)
  39.     {
  40.         if ($config instanceof Zend_Config) {
  41.             $config = $config->toArray();
  42.         } else if (!is_array($config)) {
  43.             /**
  44.              * @see Zend_Session_SaveHandler_Exception
  45.              */
  46.             require_once 'Zend/Session/SaveHandler/Exception.php';
  47.  
  48.             throw new Zend_Session_SaveHandler_Exception(
  49.                 '$config must be an instance of Zend_Config or array of key/value pairs containing '
  50.               . 'configuration options for Zend_Session_SaveHandler_Memcached .');
  51.         }
  52.  
  53.         foreach ($config as $key => $value) {
  54.             do {
  55.                 switch ($key) {
  56.                     case self::MEMCACHED:
  57.                         $this->createMemcached($value);
  58.                         break;
  59.                     case self::LIFETIME:
  60.                         $this->setLifetime($value);
  61.                         break;
  62.                     case self::OVERRIDE_LIFETIME:
  63.                         $this->setOverrideLifetime($value);
  64.                         break;
  65.                     default:
  66.                         // unrecognized options passed to parent::__construct()
  67.                         break 2;
  68.                 }
  69.                 unset($config[$key]);
  70.             } while (false);
  71.         }
  72.     }
  73.  
  74.     /**
  75.      * 创建memcached连接对象
  76.      *
  77.      * @return void
  78.      */
  79.     public function createMemcached($config){
  80.                 $this->_memcached = new Memcache;
  81.                 foreach ($config as $value){
  82.                         $this->_memcached->addServer($value['host'], $value['port'], $value['persistent'],
  83.                                                         $value['weight'], $value['timeout'],
  84.                                                         $value['retry_interval'],
  85.                                                         $value['status'],
  86.                                                                                 array($this,'_callback_memcache_failure'));
  87.                 }
  88.     }
  89.  
  90.         public function _callback_memcache_failure($host,$port){
  91.                 $this->_memcached->setServerParams($host, $port,5,15,false);
  92.         }
  93.  
  94.     public function __destruct()
  95.     {
  96.         Zend_Session::writeClose();
  97.     }
  98.    /**
  99.      * Set session lifetime and optional whether or not the lifetime of an existing session should be overridden
  100.      *
  101.      * $lifetime === false resets lifetime to session.gc_maxlifetime
  102.      *
  103.      * @param int $lifetime
  104.      * @param boolean $overrideLifetime (optional)
  105.      * @return Zend_Session_SaveHandler_Memcached
  106.      */
  107.     public function setLifetime($lifetime, $overrideLifetime = null)
  108.     {
  109.         if ($lifetime < 0) {
  110.             /**
  111.              * @see Zend_Session_SaveHandler_Exception
  112.              */
  113.             require_once 'Zend/Session/SaveHandler/Exception.php';
  114.             throw new Zend_Session_SaveHandler_Exception();
  115.         } else if (empty($lifetime)) {
  116.             $this->_lifetime = (int) ini_get('session.gc_maxlifetime');
  117.         } else {
  118.             $this->_lifetime = (int) $lifetime;
  119.         }
  120.  
  121.         if ($overrideLifetime != null) {
  122.             $this->setOverrideLifetime($overrideLifetime);
  123.         }
  124.  
  125.         return $this;
  126.     }
  127.     /**
  128.      * Retrieve session lifetime
  129.      *
  130.      * @return int
  131.      */
  132.     public function getLifetime()
  133.     {
  134.         return $this->_lifetime;
  135.     }
  136.     /**
  137.      * Set whether or not the lifetime of an existing session should be overridden
  138.      *
  139.      * @param boolean $overrideLifetime
  140.      * @return Zend_Session_SaveHandler_Memcached
  141.      */
  142.     public function setOverrideLifetime($overrideLifetime)
  143.     {
  144.         $this->_overrideLifetime = (boolean) $overrideLifetime;
  145.  
  146.         return $this;
  147.     }
  148.     public function getOverrideLifetime()
  149.     {
  150.         return $this->_overrideLifetime;
  151.     }
  152.     /**
  153.      * Retrieve session lifetime considering
  154.      *
  155.      * @param array $value
  156.      * @return int
  157.      */
  158.     public function open($save_path, $name)
  159.     {
  160.         $this->_sessionSavePath = $save_path;
  161.         $this->_sessionName     = $name;
  162.  
  163.         return true;
  164.     }
  165.     /**
  166.      * Retrieve session expiration time
  167.      *
  168.      * @param * @param array $value
  169.      * @return int
  170.      */
  171.     public function close()
  172.     {
  173.         return true;
  174.     }
  175.  
  176.     public function read($id)
  177.     {
  178.         $return = '';
  179.  
  180.         $value = $this->_memcached->get($id);                        //获取数据
  181.  
  182.         if ($value) {
  183.             if ($this->_getExpirationTime($value) > time()) {
  184.                 $return = $value['data'];
  185.             } else {
  186.                 $this->destroy($id);
  187.             }
  188.         }
  189.  
  190.         return $return;
  191.     }
  192.  
  193.     public function write($id, $data)
  194.     {
  195.         $return = false;
  196.  
  197.         $insertDate = array('modified' => time(),
  198.                               'data'     => (string) $data);
  199.  
  200.            $value = $this->_memcached->get($id);                        //获取数据
  201.  
  202.         if ($value) {
  203.             $insertDate['lifetime'] = $this->_getLifetime($value);
  204.  
  205.             if ($this->_memcached->replace($id,$insertDate)) {
  206.                 $return = true;
  207.             }
  208.         } else {
  209.             $insertDate['lifetime'] = $this->_lifetime;
  210.  
  211.             if ($this->_memcached->add($id, $insertDate,false,$this->_lifetime)) {
  212.                 $return = true;
  213.             }
  214.         }
  215.  
  216.         return $return;
  217.     }
  218.  
  219.     public function destroy($id)
  220.     {
  221.         $return = false;
  222.  
  223.         if ($this->_memcached->delete($id)) {
  224.             $return = true;
  225.         }
  226.  
  227.         return $return;
  228.     }
  229.  
  230.     public function gc($maxlifetime)
  231.     {
  232.         return true;
  233.     }
  234.  
  235.     protected function _getLifetime($value)
  236.     {
  237.         $return = $this->_lifetime;
  238.  
  239.         if (!$this->_overrideLifetime) {
  240.             $return = (int) $value['lifetime'];
  241.         }
  242.  
  243.         return $return;
  244.     }
  245.  
  246.     protected function _getExpirationTime($value)
  247.     {
  248.         return (int) $value['modified'] + $this->_getLifetime($value);
  249.     }
  250. }
  251.  
  252. //使用方法也做了相应的调整:
  253. // Memcached Config
  254. $_MemcachedConfig = array(
  255.     'memcached'=> array(
  256.         array(
  257.             'host'=>'www.yoohouse.com',
  258.             'port'=>12000,
  259.                 'persistent'=>true,
  260.                 'weight' => 1,
  261.                     'timeout' => 5,
  262.                     'retry_interval' => 15,
  263.                     'status' => true
  264.         ),
  265.         array(
  266.             'host'=>'www.yoohouse.com',
  267.             'port'=>12001,
  268.                 'persistent'=>true,
  269.                 'weight' => 1,
  270.                     'timeout' => 5,
  271.                     'retry_interval' => 15,
  272.                     'status' => true
  273.         )
  274.     ),
  275.     'lifetime' =>86400
  276. );
  277.  
  278. // Zend Session 设置、启动。Memcached使用。
  279. Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_Memcached($_MemcachedConfig));
  280. Zend_Session::start();
  281.  
  282. //同一个config数组还可以同时用于zend_cache:
  283. // Zend Cache 缓存设置,Memcached使用。
  284. $frontendOptions = array(
  285.    'lifeTime' => 7200,
  286.    'automatic_serialization' => true
  287. );
  288. $backendOptions = array(
  289.     'servers' => $_MemcachedConfig['memcached']
  290. );
  291. $cache = Zend_Cache::factory('Core',
  292.                              'Memcached',
  293.                              $frontendOptions,
  294.                              $backendOptions);
以上,如有问题欢迎指教

Q: PHP中数组查找key快还是查找value快?


26 2月
前两天被人问到这个问题,貌似sb了一几。 回头仔细想想貌似于情于理的确是key要快点,好比内存池,key就是指针,value就是其中指向的内容,把搜索臆想为一个简单的顺序查找算法,那么一定是先到key然后再进去到value,value已经是第二级了,那显然只查第一级要快许多了。 事实结果也是如此,虽然没有去深究php的两个函数底层是怎么写的,但查到的资料表明,array_key_exist,要比in_array效率高十几甚至几十倍呢。 看来偶在这种快速反应的时候,还是有很大欠缺的,心里素质不高呀。。。

Zendframework Feed


25 6月
参考:http://www.developer.com/lang/article.php/10924_3807001_1
  1. public function populargamesAction()
  2. {
  3.  
  4.     // Create array to store the RSS feed entries
  5.     $entries = array();
  6.    
  7.     // Retrieve the 25 most popular games
  8.     $game = new Game();
  9.     $rankings = $game->getLatestSalesRanks(25);
  10.    
  11.     // Cycle through the rankings, creating an array storing
  12.     // each, and push the array onto the $entries array
  13.     foreach ($rankings AS $ranking) {
  14.         $entry = array(
  15.           'title'       => "{$ranking->title}
  16.                           ({$ranking->platform})",
  17.           'link'        => "http://www.gamenomad.com/games/
  18.                            {$ranking->asin}",
  19.           'description' => "Sales Rank: #{$ranking->rank}",
  20.         );
  21.         array_push($entries, $entry);
  22.     }
  23.    
  24.     // Create the RSS array
  25.     $rss = array(
  26.       'title'   => 'GameNomad: Popular Games',
  27.       'link'    => 'http://www.gamenomad.com/games/ranks',
  28.       'charset' => 'ISO-8859-1',
  29.       'entries' => $entries
  30.     );
  31.    
  32.     // Import the array
  33.     $feed = Zend_Feed::importArray($rss, 'rss');
  34.    
  35.     // Write the feed to a variable
  36.     $rssFeed = $feed->saveXML();
  37.    
  38.     // Write the feed to a file residing in /public/rss
  39.     $fh = fopen($this->config->feed->popular_games, "w");
  40.     fwrite($fh, $rssFeed);
  41.     fclose($fh);
  42.    
  43. }

Memcached Zendframework SESSION 應用(转)


24 6月
在zend framework中,已经可以将session存储在数据库中了,不过还不支持memcache,我简单得实现了一下。 下面是SaveHandler,文件名为 :Memcached.php ,将其放在 /Zend/Session/SaveHandler 目录下,代码如下(需要有php_memcache支持,因为字符长度限制,我把部分注释去掉了):
  1. <?php
  2. require_once 'Zend/Session.php';
  3. require_once 'Zend/Config.php';
  4.  
  5. class Zend_Session_SaveHandler_Memcached implements Zend_Session_SaveHandler_Interface
  6. {
  7.     const LIFETIME          = 'lifetime';
  8.     const OVERRIDE_LIFETIME = 'overrideLifetime';
  9.     const MEMCACHED            = 'memcached';
  10.     protected $_lifetime = false;
  11.     protected $_overrideLifetime = false;
  12.     protected $_sessionSavePath;
  13.     protected $_sessionName;
  14.     protected $_memcached;
  15.     /**
  16.      * Constructor
  17.      *
  18.      * $config is an instance of Zend_Config or an array of key/value pairs containing configuration options for
  19.      * Zend_Session_SaveHandler_Memcached . These are the configuration options for
  20.      * Zend_Session_SaveHandler_Memcached:
  21.      *
  22.      *
  23.      *      sessionId       => The id of the current session
  24.      *      sessionName     => The name of the current session
  25.      *      sessionSavePath => The save path of the current session
  26.      *
  27.      * modified            => (string) Session last modification time column
  28.      *
  29.      * lifetime          => (integer) Session lifetime (optional; default: ini_get('session.gc_maxlifetime'))
  30.      *
  31.      * overrideLifetime => (boolean) Whether or not the lifetime of an existing session should be overridden
  32.      *      (optional; default: false)
  33.      *
  34.      * @param Zend_Config|array $config      User-provided configuration
  35.      * @return void
  36.      * @throws Zend_Session_SaveHandler_Exception
  37.      */
  38.     public function __construct($config)
  39.     {
  40.         if ($config instanceof Zend_Config) {
  41.             $config = $config->toArray();
  42.         } else if (!is_array($config)) {
  43.             /**
  44.              * @see Zend_Session_SaveHandler_Exception
  45.              */
  46.             require_once 'Zend/Session/SaveHandler/Exception.php';
  47.  
  48.             throw new Zend_Session_SaveHandler_Exception(
  49.                 '$config must be an instance of Zend_Config or array of key/value pairs containing '
  50.               . 'configuration options for Zend_Session_SaveHandler_Memcached .');
  51.         }
  52.  
  53.         foreach ($config as $key => $value) {
  54.             do {
  55.                 switch ($key) {
  56.                     case self::MEMCACHED:
  57.                         $this->createMemcached($value);
  58.                         break;
  59.                     case self::LIFETIME:
  60.                         $this->setLifetime($value);
  61.                         break;
  62.                     case self::OVERRIDE_LIFETIME:
  63.                         $this->setOverrideLifetime($value);
  64.                         break;
  65.                     default:
  66.                         // unrecognized options passed to parent::__construct()
  67.                         break 2;
  68.                 }
  69.                 unset($config[$key]);
  70.             } while (false);
  71.         }
  72.     }
  73.  
  74.     /**
  75.      * 创建memcached连接对象
  76.      *
  77.      * @return void
  78.      */
  79.     public function createMemcached($config){
  80.       $mc = new Memcache;
  81.       foreach ($config as $value){
  82.         $mc->addServer($value['host'], $value['port']);
  83.       }
  84.       $this->_memcached = $mc;
  85.     }
  86.  
  87.     public function __destruct()
  88.     {
  89.         Zend_Session::writeClose();
  90.     }
  91.    /**
  92.      * Set session lifetime and optional whether or not the lifetime of an existing session should be overridden
  93.      *
  94.      * $lifetime === false resets lifetime to session.gc_maxlifetime
  95.      *
  96.      * @param int $lifetime
  97.      * @param boolean $overrideLifetime (optional)
  98.      * @return Zend_Session_SaveHandler_Memcached
  99.      */
  100.     public function setLifetime($lifetime, $overrideLifetime = null)
  101.     {
  102.         if ($lifetime < 0) {
  103.             /**
  104.              * @see Zend_Session_SaveHandler_Exception
  105.              */
  106.             require_once 'Zend/Session/SaveHandler/Exception.php';
  107.             throw new Zend_Session_SaveHandler_Exception();
  108.         } else if (empty($lifetime)) {
  109.             $this->_lifetime = (int) ini_get('session.gc_maxlifetime');
  110.         } else {
  111.             $this->_lifetime = (int) $lifetime;
  112.         }
  113.  
  114.         if ($overrideLifetime != null) {
  115.             $this->setOverrideLifetime($overrideLifetime);
  116.         }
  117.  
  118.         return $this;
  119.     }
  120.     /**
  121.      * Retrieve session lifetime
  122.      *
  123.      * @return int
  124.      */
  125.     public function getLifetime()
  126.     {
  127.         return $this->_lifetime;
  128.     }
  129.     /**
  130.      * Set whether or not the lifetime of an existing session should be overridden
  131.      *
  132.      * @param boolean $overrideLifetime
  133.      * @return Zend_Session_SaveHandler_Memcached
  134.      */
  135.     public function setOverrideLifetime($overrideLifetime)
  136.     {
  137.         $this->_overrideLifetime = (boolean) $overrideLifetime;
  138.  
  139.         return $this;
  140.     }
  141.  
  142.     public function getOverrideLifetime()
  143.     {
  144.         return $this->_overrideLifetime;
  145.     }
  146.     /**
  147.      * Retrieve session lifetime considering
  148.      *
  149.      * @param array $value
  150.      * @return int
  151.      */
  152.     public function open($save_path, $name)
  153.     {
  154.         $this->_sessionSavePath = $save_path;
  155.         $this->_sessionName     = $name;
  156.  
  157.         return true;
  158.     }
  159.     /**
  160.      * Retrieve session expiration time
  161.      *
  162.      * @param * @param array $value
  163.      * @return int
  164.      */
  165.     public function close()
  166.     {
  167.         return true;
  168.     }
  169.  
  170.     public function read($id)
  171.     {
  172.         $return = '';
  173.  
  174.         $value = $this->_memcached->get($id);                        //获取数据
  175.  
  176.         if ($value) {
  177.             if ($this->_getExpirationTime($value) > time()) {
  178.                 $return = $value['data'];
  179.             } else {
  180.                 $this->destroy($id);
  181.             }
  182.         }
  183.  
  184.         return $return;
  185.     }
  186.  
  187.     public function write($id, $data)
  188.     {
  189.         $return = false;
  190.                      
  191.         $insertDate = array('modified' => time(),
  192.                               'data'     => (string) $data);
  193.                              
  194.            $value = $this->_memcached->get($id);                        //获取数据
  195.  
  196.         if ($value) {
  197.             $insertDate['lifetime'] = $this->_getLifetime($value);
  198.            
  199.             if ($this->_memcached->replace($id,$insertDate)) {
  200.                 $return = true;
  201.             }
  202.         } else {
  203.             $insertDate['lifetime'] = $this->_lifetime;
  204.  
  205.             if ($this->_memcached->add($id, $insertDate,false,$this->_lifetime)) {
  206.                 $return = true;
  207.             }
  208.         }
  209.        
  210.         return $return;
  211.     }
  212.  
  213.     public function destroy($id)
  214.     {
  215.         $return = false;
  216.  
  217.         if ($this->_memcached->delete($id)) {
  218.             $return = true;
  219.         }
  220.  
  221.         return $return;
  222.     }
  223.  
  224.     public function gc($maxlifetime)
  225.     {
  226.         return true;
  227.     }
  228.  
  229.     protected function _getLifetime($value)
  230.     {
  231.         $return = $this->_lifetime;
  232.  
  233.         if (!$this->_overrideLifetime) {
  234.             $return = (int) $value['lifetime'];
  235.         }
  236.  
  237.         return $return;
  238.     }
  239.  
  240.     protected function _getExpirationTime($value)
  241.     {
  242.         return (int) $value['modified'] + $this->_getLifetime($value);
  243.     }      
  244. }
  245.  
  246. 配置(可以添加多台memcache服务器,做分布式):
  247. $config = array(
  248.     'memcached'=> array(
  249.         array(
  250.             'host'=>'192.168.0.1',
  251.             'port'=>11211
  252.         )
  253.     ),
  254.     'lifetime' =>123334
  255. );
  256. //create your Zend_Session_SaveHandler_DbTable and
  257. //set the save handler for Zend_Session
  258. Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_Memcached($config));
  259. //start your session!
  260. Zend_Session::start();
原文地址 http://hi.baidu.com/billdkj/blog/item/049d04f0b2a896c47831aa1c.html

php excel 操作类 整理


23 6月
php-excel-reader是目前我所知的最好的php读取excel数据的开源类,可以做到读取带各种格式的excel文件。详见文档。 另写入类:php-excel备用(尚未使用过,不知效果如何)。 在读写excel 2003前的版本的xls文件上,曾经一度使用一个excel_class.php,但长年缺少维护感觉有点太老了,而且不太符合php5的面向对象的感觉。故弃用。 对于excel2007的文档的读写,可用PHPExcel,同样暂时还没机会使用过。但似乎此开源项目维护得不错,暂做记录。

貓熊寶寶幼齒園

姜經緯的博客