顯示具有 PHP 標籤的文章。 顯示所有文章
顯示具有 PHP 標籤的文章。 顯示所有文章

星期四, 10月 19, 2017

升級PHP7及Phalcon3已知問題


PHP 7

  1. COUNT field incorrect or syntax error
    placeholders must have unique names even if they have the same value
    不確認是PDO還是Phalcon,但知道placeholder不可重覆
    
    $sql = "SELECT * FROM m
    WHERE m.prod_market_sdate <= :nowDate         
    AND m.prod_market_edate >= :nowDate
    $statement = $db->prepare($sql);
    $result = $db->executePrepared(
    $statement,
    array(
    'nowDate' => date("Y-m-d H:i:s", time())
    ),
    array()
    );
    Reference: https://stackoverflow.com/questions/34089614/count-field-incorrect-or-syntax-error
  2. Static property
    
    - $this->$fileErr => $self::fileErr


Phalcon 3

  1. 不可以有重覆的andWhere
    雖然不應該有這問題...
    不過有時候條件太多,看走眼...
    
    $builder->andWhere("name = 'Peter'");
    $builder->andWhere("name = 'Peter'"); //重覆會有錯
    

星期一, 12月 14, 2015

加強json_encode的xss 防禦

由於常把資料從db拉出來,再整個json_encode丟給前端
因此要一個個filter還挺累的
如果可以直接對encode過的string filter最好了~

幸好json_encode有好用的參數
完整參數如下
json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS);
PHP官網有完整範例,以下截錄
$a = array('',"'bar'",'"baz"','&blong&', "\xc3\xa9");

echo "Normal: ",  json_encode($a), "\n";
echo "Tags: ",    json_encode($a, JSON_HEX_TAG), "\n";
echo "Apos: ",    json_encode($a, JSON_HEX_APOS), "\n";
echo "Quot: ",    json_encode($a, JSON_HEX_QUOT), "\n";
echo "Amp: ",     json_encode($a, JSON_HEX_AMP), "\n";
echo "Unicode: ", json_encode($a, JSON_UNESCAPED_UNICODE), "\n";
echo "All: ",     json_encode($a, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE), "\n\n";

Normal: ["","'bar'","\"baz\"","&blong&","\u00e9"]
Tags: ["\u003Cfoo\u003E","'bar'","\"baz\"","&blong&","\u00e9"]
Apos: ["","\u0027bar\u0027","\"baz\"","&blong&","\u00e9"]
Quot: ["","'bar'","\u0022baz\u0022","&blong&","\u00e9"]
Amp: ["","'bar'","\"baz\"","\u0026blong\u0026","\u00e9"]
Unicode: ["","'bar'","\"baz\"","&blong&","e"]
All: ["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026","e"]
Reference
Example #2 A json_encode() example showing some options in use

星期五, 10月 23, 2015

擴充Phalcon的filter過濾 xss 攻擊


其實直接用htmlentities or htmlspecialchars就可以了
不過因為一些問題,所以得加上一些參數
見這篇 到底要用htmlenties 還是htmlspecialchars

如果各自使用htmlentities 又容易漏參數
於是想寫個helper類的來幫助

後來想想,幹脆直接擴充phalcon的filter,再透過di統一取得
如此一來就能規範大家用相同的設定也挺不錯的

service.php的設定
$di->setShared("filter", function(
    $filter = new \Phalcon\Filter();
    // Using an anonymous function
    $filter->add('xss', function ($value) {
        $flags = ENT_QUOTES;
        $encoding = "UTF-8";
        $doubleEncode = false;
        return htmlspecialchars($value, $flags, $encoding, $doubleEncode);
    });
    return $filter
));

使用方法
$filter = $di->get("filter");          //取得filter
 
//統一透過filter,寫法能夠一致
$filter->sanitize($value, "xss");      //自寫的,用specialchars
$filter->sanitize($value, "string");   //用htmlentities,不建議用
$filter->sanitize($value, "int");
$filter->sanitize($value, "email");

星期三, 10月 21, 2015

到底要用htmlenties 還是htmlspecialchars

基本上... 要看情況,但先寫通用的結論,就是用htmlspecialchars()
但是!!!! 要加幾個參數,完整如下
htmlspecialchars("i'm 魚乾'", ENT_QUOTES, "UTF-8", false)

先說明後面三個parameters,再說明為何不用htmlentities

  • param 2: $flags = ENT_QUOTES
    避免SQL Injection,所以一律對單引號做轉換
  • param 3: $encoding = "UTF-8",
    encoding一定要加,免得被不同版本的PHP影響
    5.4 預設"UTF-8"
    5.6 是吃default_charset設定
  • param 4: $double_encode = false
    避免重覆encode, ex: &的&會重覆encode


為何不用htmlentities

因為特殊字元會有亂碼問題
htmlentities遇到認不出文字,會轉成亂碼or特殊字
echo htmlentities('魚乾') . PHP_EOL;                 //é­▒ä¹¾ ö
echo htmlspecialchars('魚乾 ö'). PHP_EOL;            //魚乾 ö

//雖然可以decode還原,但如果直接看DB資料時總怪怪的

中文字加上固定的encoding就ok了,但有些字還是會被encode
echo htmlentities('魚乾 ö') . PHP_EOL;                    //é­▒ä¹¾ ö
echo htmlentities('魚乾 ö',ENT_QUOTES,"UTF-8") . PHP_EOL; //魚乾 ö 為會轉為  &ouml;
echo htmlspecialchars('魚乾 ö'). PHP_EOL;                 //魚乾 ö

結論:
內容並不是我們想轉換的特殊字,所以遇到特殊字就不要理,這是htmlspecialchars的理念
那何時適用htmlentities?
就... 你要encode特殊字的時候....
何時會需要... 存的media不支援特殊字時...吧...




星期一, 7月 20, 2015

列出排序後的圖檔

說明:
每個分類會有對應的圖檔,原本利用id當檔名存
但因介接系統只認檔名,所在在相同檔名下,更換圖檔內容不會觸發介接系統更新圖
因此利用filename加timestamp來觸發(跟css, js加上?v=xxx同義)

做法:
資料夾下會有多個圖檔,而圖檔的filename會夾timestamp,
在不靠其他persistent data的做法下(記在db or file),就直接sort timestamp當最新的圖檔


  1. 取得所有jpg圖
  2. $files = glob("/path/to/directory/*.jpg");
    --
    Array
    (
        [0] => /path/to/directory/1.jpg
        [1] => /path/to/directory/2.jpg
        [2] => /path/to/directory/3.jpg
    )
    
  3. 加上其他圖檔格式(靠GLOB_BRACE)
    $images = glob("files/*.{jpg,gif,png}", GLOB_BRACE);
    
  4. 還有大小寫問題 >_<
    $images = glob("files/*.{[jJ][pP][gG],[gG][iI][fF],[pP][nN][gG]}", GLOB_BRACE);
    


  5. 排序部份靠php,完整的寫法如下(如果還要其他圖檔格式,就自己加囉)
    $images = glob("files/*.{[jJ][pP][gG],[gG][iI][fF],[pP][nN][gG]}", GLOB_BRACE);
    $sorted = rsort($images); //由大到小
    


Reference
Using PHP's glob() function to find files in a directory

星期二, 3月 24, 2015

排程與apache建立共用folder


由於透過排程建立image資料夾丟圖片
而後台(人工)作業也會透過apache建立資料夾丟圖片
但權限不同(owner不同),造成無法丟入圖檔
最麻煩的是Server被禁止無法在php裡執行chmod

想了幾個做法
  1. 透過localhost/shell啟動apache/[cron-user]建立folder  (failed)
    原本想用排程透過curl呼叫"建立folder"的PHP (owner 為apache)
    但因為一樣是建立自己的帳號,反而是自己無權限丟檔  o_Q
  2. 排程執行固定執行Shell (work around)
    可以,但因為要改對方建立的folder,所以得要有root權限,不太好的解法 
  3. 透過apache執行排程 (solution)
    原本想建立apache user來寫排程,但Admin不同意
    後來看到可以sudo為apache來寫排程,這樣一來都是owner都是apache~ YA~
    sudo -u apache crontab -e

星期日, 3月 08, 2015

PHP到底有沒有DB Connection Pooling

一直沒搞懂到底PHP有沒有Connection Pooling...
看了Persistent connections,又有人說不要用
沒事就被打個槍,還是好好研究一下

先簡單的來說有什麼做法(linux下)
  1. PHP的MSSQL extension
    1. 就是常見的pconnect,不建議
  2. PHP的PDO extension
    • 做法
      • 將connection cache下來,當其他的php script request,再重覆使用
        寫法如下
        <?php
        $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
            PDO::ATTR_PERSISTENT => true
        ));
        實驗結果PDO可以的ATTR_PERSISTENT ,還可關掉ODBC的pooling
    • 討論
      • PHP官網指出,如果有ODBC做pooling的話,就用ODBC做,因為可讓同process其他的模組使用
  3. ODBC Connection Pooling(unixODBC)
    • 做法
      • 存在Web Server裡,供給Web Server Process使用
      • 前提是使用的ODBC driver及library要有支援
      • PDO_ODBC及unixODBC v2.0後都有支援Connection Pool
    • 另外利用ODBC的還有以下,但各自有沒有再實作pooling沒研究
      • Microsoft ODBC
      • Easysoft ODBC
  4. freeTDS
    • 做法:利用linux process管理connection
    • 怪可怕的,如果process掛了,那connection就GG了
    • 而且只接受TDS 4.2, 也不接受ntext

Summary

看起來利用ODBC比較做是比較建議的做法
另外就不用再用PDO做persistent,因為會被cache住,不會還給ODBC.

  • 使用Pooling注意事項
    勿改變connection 狀態,例如改default db,造成使用同組db帳密的request會讀取錯誤


Reference
Connections and Connection management
ODBC Connection pooling

星期二, 10月 08, 2013

git commit前做coding style檢查

雖然規定團隊Coding Standard要follow PSR規範
不過實在不容易一項項比對~ 再說改都是小地方,實在不知怎麼盯起
聽朋友推薦神器~ git hooks!!!

在commit前,會觸發相關的script檢查
因此只搭PSR定義的script就可以強制規範Coding Standard
這真是太棒了!!!

  • 安裝三步驟
    1. install git
      # yum install git
    2. install PHP Code Sniffer
      # pear install PHP_CodeSniffer
    3. setup script
      裝好PHP_CodeSniffer後,到git專案的資料夾下找.git/hooks資料夾
      # cd project/.git/hooks
      # vi pre-commit #記得要chmod 755 pre-commit
      可以在不同時機點觸發script,這邊就指定pre-commit時,相對也有post-commit,按這看更多
      #!/usr/bin/php
      <?php
      
      $output = array();
      $return = 0;
      exec('git rev-parse --verify HEAD 2> /dev/null', $output, $return);
       
      // Get GIT revision
      $against = $return == 0 ? 'HEAD' : '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
       
      // Get the list of files in this commit.
      $output = array();
      exec("git diff-index --cached --name-only {$against}", $output);
       
      $filename_pattern = '/\.php$/';
      $exit_status = 0;
       
      // Loop through files.
      foreach ($output as $file) {
          if ( ! preg_match($filename_pattern, $file)) {
              // don't check files that aren't PHP
              continue;
          }
       
          // If file is removed from git do not sniff. 
          if ( ! file_exists($file))
          {
              continue;
          }
       
          $lint_output = array();
          // Run the sniff
          exec("phpcs --standard=PSR2 --warning-severity=0 " . escapeshellarg($file), $lint_output, $return);
          if ($return == 0) {
              continue;
          }
          echo implode("\n", $lint_output), "\n";
          $exit_status = 1;
      }
       
      exit($exit_status);
  • 使用方法
    很簡單,commit前,就會觸發,如果有未符合規範,就出現如下的訊息

    一行行修吧 = =+

    如果只是驗證單一隻程式的話,就以直接在console下
    也不用一定得透過commit觸發script
    # phpcs --standard=PSR2 --warning-severity=0 [檔案名稱]

後來發現原來早就有這東西了~ 而且還滿多運用的~
現在看團隊每次commit前,就得先努力的code修成符PSR規範
心理莫明的覺得好爽~~ 哈哈

使用過程遇到的問題
  • .git/hooks/pre-commit: No such file or directory
    找好久,一直看不出問題...
    後來查是換行符號問題!!!當初朋友給的時候是從linux的檔案複製容到,直接貼到windows下txt裡...
    把\r去掉就好了...
    # cp .git/hooks/pre-commit /tmp/pre-commit
    # tr -d '\r' < /tmp/pre-commit > .git/hooks/pre-commit

    References
    Pre Commit hook git error

星期一, 8月 12, 2013

Install ssh2 for PHP without YUM on RHEL

為了裝個ssh2 for php 得額外安裝一堆...
幸好rpmfind還挺好用的...
不然都要放棄了...

安裝流程照官網上寫的 - CentOS 6.2 64bit Installation Steps
  1. download the libssh2 package from http://libssh2.org, command as following:
    tar vxzf libssh2-1.4.2.tar.gz
    cd libssh2-1.4.2
    ./configure
    make
    make install
  2. download the php-ssh2 package from http://pecl.php.net/package/ssh2:
    tar vxzf ssh2-0.11.3
    cd ssh2-0.11.3
    phpize
    ./configure --with-ssh2
    make
    make install

    and the ssh2.so file will copy into /usr/lib64/php/modules
    check it.
  3. modify the php.ini

    vi /etc/php.ini

    add the "extension=ssh2.so" to the extension part of php.ini
  4. check the environment of php, use phpinfo();
  5. enjoy

主要兩個套件
但相依很多,缺什麼裝什麼,所以實際上是倒過來裝
遇一個殺一個了... 要有耐心... 套件就到rpmfind上找
  • libssh
    1. libssh2-1.4.2-1.el6.i686.rpm
    2. libgcrypt-1.4.5-9.el6_2.2.i686
    3. gcc-c++-4.4.7-3.el6.x86_64.rpm
    4. libstdc++-devel-4.4.7-3.el6.i686.rpm
  • ssh2
    1. ssh2-0.12.tgz
    2. php-devel-5.1.6-39.el5_8.i386.rpm
      下phpize需要

心得...
有yum好幸福,沒yum好痛苦...(還按韻ㄝ)
光一堆dependency就快放棄了...
還要找版本相融的rpm來裝...
只能靠deadline來逼自己一步步下去
不過套件找齊後,一步步裝回去還挺有成就感的...

星期日, 6月 30, 2013

MD5被破解了,要改用SHA

過去很常用MD5做訊息摘要,近來發現某些地方會用SHA做摘要
google了一下,發現MD5因hash不夠強而被破解了,能夠偽造相同的訊息摘要
大致問題如下
  1. MD5的hash值,google就會找到了,
    本來沒在意這點,不過有時會用在儲存密碼上
    這就容易被反推,記得幾年前也有朋友用google MD5去找密碼...
  2. 相同的訊息摘要
    MD5本來就不以安全為出發點,只是做摘要用,因此hash不夠強,會發生兩個不同的message,但產生相同的hash碼
  3. 利用MD5做檔案特徵碼也有相同的問題
    SHA的訊息摘要的長度更長,因此較不會發生碰撞,也更為安全
    不過相對MD5,運算也相對較慢,所以適合用在摘要小段訊息
    檔案還是用MD5比較快

PHP寫法
$data = "魚乾的筆記本";
$key = "fishjerk";

$sig = md5($data, true);  // = hash('md5', $data);
//Output 32個字元特徵碼: 9fc745260dedf115ec7b62fa811f0698

$sig = hash_hmac('sha256', $data, $key ); //跟hash('sha256')的差別是多了$salt改變特徵碼
//Output 64個字元特徵碼: 7b8ddbde1cc031945d23d82af786a83048e40efff7c1194ed9ea6c6f0fae39b2

$sig = hash_hmac('sha512', $data, $key );
//Output 128個字元特徵碼: 8cb44d44e52b443fa3095a06668dd6e31b8ce973f3b4f353d40ca35b47605dc41ff3ab003f375aee5ed1a14456e2b783d1f98543cc111822ea63d26d1427ea61


SHA有5種演算法,SHA-0 ~ SHA-5
目前 SHA-0 及 SHA-1 也都被破了
SHA-2 以上還沒出現有效的攻擊,SHA256 及 SHA512 即為 SHA-2

過去上密碼學時,都沒注意到原來SHA是Secure Hash Algorithm 縮寫
都說是Secure了,還在用MD5玩~ (羞)
難怪之前用 facebook 金流時,人家也用sha256

References

星期二, 3月 26, 2013

HessianPHP 中文亂碼問題

HessianPHP出了2.0,原則上v1.0才算有中文亂碼bug
但用2.0時,還是有遇到,雖然不是bug,不過總是先懷疑是別人的問題~ 哈哈
  • HessianPHP 2.0 解決方法
    install mbstring
    yum install php-mbstring
    哈 我就說過不是bug了... 只是mbstring沒用而已
    不過還有個小地方要設定,不然還是一樣亂碼~
    //php.ini
    mbstring.internal_encoding = UTF-8 

    不過本來以為沒設mbstring的encoding的話
    就手動寫utf8_decode(string), 沒想到一樣是亂碼~
  • HessianPHP 1.0 解決方法
    修改 HessianPHP的Protocol.php
    function readString(){
        return utf8_decode($string); //return $string;
    }

星期二, 7月 31, 2012

log4php結合FirePHP

firephp很好用,那怎麼跟log4php結合咧
download: 下載 利用ci寫的


由於ci使用library都得用new實體化
而log4php透過static method(getLogger)取得logger
用起來總是卡卡... 應該說會卡住...
所以寫成library

  1. FirePHP appender
    簡單說,就是多寫個FirePHP的Appender
    這樣log4php就可以使用FirePHP
    class LoggerAppenderFirePHP extends LoggerAppender {
         ...
        public function append(LoggerLoggingEvent $event) {
           if($this->layout !== null) 
               return;
    
           $ci = & get_instance();
           $level = $event->getLevel();
           if($level->isGreaterOrEqual(LoggerLevel::getLevelError())) {
           $ci->fb->error($this->layout->format($event));
           } else if ($level->isGreaterOrEqual(LoggerLevel::getLevelWarn())) {
           $ci->fb->warn($this->layout->format($event));
           } else {
           $ci->fb->info($this->layout->format($event));
          }
         
       }
    }
    p.s. 因為是套用在codeigniter下... 所以有出現個get_instance() XD
  2. config
    <configuration xmlns="http://logging.apache.org/log4php/">
            <appender name="firephp" class="LoggerAppenderFirePHP">
                    <layout class="LoggerLayoutPattern">
                            <param name="ConversionPattern" value="%m"/>
                    </layout>
            </appender>
            <root>
                    <appender_ref ref="firephp" />
            </root>
    </configuration>
  3. logging
        $this->load->library('Log4php');
    
        $this->log4php->log('info',"[behavior] info");
        $this->log4php->log('error',"error");
        $this->log4php->log('warn',"warn");
    結果如下



星期一, 7月 30, 2012

install memcache for php

本想說這東西就yum一下就好了...
沒想到重裝時,還真卡住了,想不起來怎麼裝的
還是乖乖寫筆記吧

  • 架memcache server
    1. 事前準備
      yum install libevent
      yum install libmemcached libmemcached-devel
    2. 裝memcache server
      yum install memcached
    3. Start Memcached server
      memcached -d -m 512 -l 127.0.0.1 -p 11211 -u nobody
      d = daemon, m = memory, u = user, l = IP to listen to, p = port)
  • php存取memcache
    1. 事前準備
      利用pecl安裝,如果沒有的...
      yum install php-pear
    2. 安裝memcache
      pecl install memcache
    3. 設定php.ini
      將extension寫入php.ini
      extension=memcache.so
    4. 設定memcache server位置
      $memcache = new Memcache; 
      $memcache->connect('127.0.0.1', 11211) or die ("Could not connect"); //connect to memcached server   
      $mydata = "i want to cache this line"; //your cacheble data   
      $memcache->set('key', $mydata, false, 100); //add it to memcached server   $get_result = $memcache->get('key'); //retrieve your data   
      var_dump($get_result); //show it
就這麼簡單...

Reference

10 baby steps to install Memcached Server and access it with PHP


星期三, 5月 23, 2012

php array轉xml, json

轉json就沒什麼好說的了,想說轉xml應該也是很簡單的東西,不過還真遇到一些問題
  1. array to xml
    原本在google了一段code後,後來發現有中文xml會掛掉因為有不合法字元,
    後來找到以下的code有編碼過,才知道原是編碼的問題
    function toXml($data = array(), $structure = NULL, $basenode = 'xml'){
       // turn off compatibility mode as simple xml throws a wobbly if you don't.
       if (ini_get('zend.ze1_compatibility_mode') == 1)
       {
          ini_set('zend.ze1_compatibility_mode', 0);
       }
    
       if ($structure == NULL)
       {
       $structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />");
       }
    
       // loop through the data passed in.
       $data = $this->_force_loopable($data);
       foreach ($data as $key => $value)
       {
          // no numeric keys in our xml please!
          if (is_numeric($key))
          {
             // make string key...
             //$key = "item_". (string) $key;
             $key = "item";
          }
    
          // replace anything not alpha numeric
          $key = preg_replace('/[^a-z_]/i', '', $key);
    
          // if there is another array found recrusively call this function
          if (is_array($value) OR is_object($value))
          {
             $node = $structure->addChild($key);
             // recrusive call.
             $this->_format_xml($value, $node, $basenode);
          }
          else
          {
            // Actual boolean values need to be converted to numbers
            is_bool($value) AND $value = (int) $value;
    
            // add single node.
            $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8");
    
             $UsedKeys[] = $key;
    
             $structure->addChild($key, $value);
          }
       }
    
       // pass back as string. or simple xml object if you want!
       return $structure->asXML();
    }
    
    function _force_loopable($data){
       // Force it to be something useful
       if ( ! is_array($data) AND ! is_object($data))
       {
          $data = (array) $data;
       }
    
    return $data;
    }
    
  2. 下header
    browser才會當成xml,而不是html
    $array = array(...);
    header('Content-type: application/xml;charset=utf-8');
    exit(toXml($array)) ;
    

結合一下兩者,利用同一個function回覆
//給header用
$_supported_formats = array(
                'xml' => 'application/xml',
                'rawxml' => 'application/xml',
                'json' => 'application/json',
                'jsonp' => 'application/javascript',
                'serialize' => 'application/vnd.php.serialized',
                'php' => 'text/plain',
                'html' => 'text/html',
                'csv' => 'application/csv'
        );


function response($data, $format = 'json'){
    header('Content-type: '.$this->_supported_formats[$format]);
    switch (strtolower($format)){
        case 'xml':                                
                exit($this->toXml($data));
        case 'json':
        default:
            exit(json_encode($data));
    }
}

星期四, 2月 09, 2012

利用 php 本身寫 error log 及 error/warning/notice message

  • error_reporting
    設定php回發生錯誤的等級
    error_reporting(0);  // Turn off all error reporting
    ini_set('error_reporting', E_ALL);  // Same as error_reporting(E_ALL);
  • error_log
    bool error_log ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] )
    Sends an error message to the web server's error log or to a file.
    需寫入file,因此需指定file path
    用法
    //log to file
    ini_set('error_log', dirname(__FILE__) . '/error_log.txt');  
    
    // Send notification through the server log if we can not
    // connect to the database.
    if (!Ora_Logon($username, $password)) {
        error_log("Oracle database not available!", 0);
    }
    
    // Notify administrator by email if we run out of FOO
    if (!($foo = allocate_new_foo())) {
        error_log("Big trouble, we're all out of FOOs!", 1,
                   "operator@example.com");
    }
    
    // another way to call error_log():
    error_log("You messed up!", 3, "/var/tmp/my-errors.log");
    
  • error/warning/notice message
    定義log level多配合log4php,不過也可透過trigger_error
    即可靠php本身達成此效果
    trigger_error("Notice Message",E_USER_NOTICE);
    trigger_error("Warning Message",E_USER_WARNING);
    trigger_error("Error Message",E_USER_ERROR);
    如此就不用再掛log4php,就能方便帶訊息
也就是說error_report 是設定php觸發回報錯誤的等級
如果想利用此機制寫自定的訊息就可透過trigger_error
而error_log就自己想log什麼就log什麼

error_report設定篇
開啟是否顯示error及log的等級
  • 在php.ini中設定
    display_errors = On 
    
  • 在.php中設定
    每次要到php.ini設定就太累了,這邊有方法可以直接在.php裡,直接設定log,這樣開發起來就方便多了,且不會動到整體環境
    ini_set('display_errors', 1);   //turn on display error on screen
    ini_set('log_errors', 1);     //turn on log error
    error_reporting(E_ALL); //log all errors and warnings


常見常數定義
列出常見的幾個,其他看官網Predefined Constants
Constant Description Note
E_NOTICERun-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script.
E_STRICTEnable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.Since PHP 5 but not included in E_ALL until PHP 5.4.0
E_ALLAll errors and warnings, as supported, except of level E_STRICT prior to PHP 5.4.0.

References

星期四, 12月 15, 2011

active record使用memcached

一直用sql當memcached的key跑的順順的
不過最近在用ci在開發,發現用的active record不知抓什麼來當key
研究了一下,發現有last_query()可取出sql string
不過又看了一下發現是先execute後,才會有的query

而cache當然是要跑之前做,不然就沒有意義了
又serach了一下,發現有_compile_select()
差別當然在有執行跟沒執行,以下是片斷程式碼
有引用tomschlick寫好給ci用的memcached-library
 $key = $this->db->_compile_select();
$this->load->library('Memcached_library','','memcached');
$results = $this->memcached->get($key);

// If the key does not exist it could mean the key was never set or expired
if ($results) 
     echo 'hit';
else{
     echo 'miss';
     $results = $this->db->get()->row_array();
     $this->memcached->add($key, $results);
}
不過每個有用db的程式這樣寫太麻煩了
原本想改寫ci的db driver,看起來有點麻煩,先求有吧
所以先簡單的寫在helper裡,有空再來研究改寫driver
_compile_select());
        $ci = & get_instance();
        $ci->load->library('Memcached_library','','memcached');
        $results = $ci->memcached->get($key);

        // If the key does not exist it could mean the key was never set or expired
        if ($results) {

                $ci->fb->info('[memcache] hit', "info");
        }else{

                $ci->fb->warn('[memcache] miss', "memcached");
                $results = $db->get()->row_array();
                $ci->memcached->add($key, $results);
        }

        $db->_reset_select();  //clear sql query string
        return $results;
}
References Getting CodeIgniter Active Record's current SQL code

星期一, 12月 12, 2011

檢查遠端的檔案是否存在

這方法還不錯,只回傳header,不看body
function remoteFileExists($url) {
    $curl = curl_init($url);

    //don't fetch the actual page, you only want to check the connection is ok
    curl_setopt($curl, CURLOPT_NOBODY, true);

    //do request
    $result = curl_exec($curl);

    $ret = false;

    //if request did not fail
    if ($result !== false) {
        //if request was ok, check response code
        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);  

        if ($statusCode == 200) {
            $ret = true;   
        }
    }

    curl_close($curl);

    return $ret;
}

$exists = remoteFileExists('http://stackoverflow.com/favicon.ico');
if ($exists) {
    echo 'file exists';
} else {
    echo 'file does not exist';   
}
Reference

星期二, 12月 06, 2011

CodeIgniter - db active record常用指令

  • basic
    • 取得config中,名為group_one的db
      $DB1 = $this->load->database('group_one', TRUE); //給true才會產生實體給$DB1
      $this->db->select('title')->from('mytable')->where('id', $id)->limit(10, 20);
      
      p.s. 給true才會回傳個db object
    • 取sql string
      • last_query()
        執行的過程中,最後的一個sql query string
      • _compile_select()
        目前sql條件的sql query string,尚未實際執行
  • select
    $this->db->select('title, content, date'); //不下的話就是*
    $query = $this->db->get('mytable');
    foreach ($query->result() as $row)
    {
        echo $row->title;
    }
    
  • from、join
    $this->db->from('mytable');
    $this->db->select('*');
    $this->db->from('blogs');
    $this->db->join('comments', 'comments.id = blogs.id');
    
    $query = $this->db->get();
    
    // Produces:
    // SELECT * FROM blogs
    // JOIN comments ON comments.id = blogs.id
  • where 
    //法1.
    $query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);
    $this->db->or_where('id >', $id);  // Produces: WHERE name != 'Joe' OR id > 50
    
    //法2
    $this->db->select('title')->from('mytable')->where('id', $id);
    
  • insert
  • 新增欄位為now()的方法
    $data = array (
       'customer_id'=> $customer_id,
       'total' => $totalprice
      );
      $this->db->set('order_date', 'NOW()', FALSE);
      $this->db->insert('omc_orders', $data);


Reference

星期二, 10月 18, 2011

php轉碼問題

利用iconv轉碼會有轉不回來的問題
可用mbstring來轉碼 就不會有問題了
當然apache要先安裝mbstring
  • 安裝
    yum install php-mbstring
  • big5轉utf8
    mb_convert_encoding($msg, "UTF-8", "BIG-5");
  • 配合自動偵測,統一轉utf8
    要注意要自己加上可能的碼,不然可能會找不到
    $encoding = mb_detect_encoding($this->content, "UTF-8,BIG-5,GB2312, ASCII, ISO-8859-1");
    $msg = mb_convert_encoding($msg, "UTF-8", $encoding);
    

星期四, 10月 13, 2011

php處理url函式

  • 組url字串
    利用http_build_query
    <?php
    $data = array('foo'=>'bar',
                  'baz'=>'boom',
                  'cow'=>'milk',
                  'php'=>'hypertext processor');
    
    echo http_build_query($data) . "\n";
    echo http_build_query($data, '', '&');
    
    //前置詞
    $data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
    echo http_build_query($data, 'myvar_');  
    --
    foo=bar&baz=boom&cow=milk&php=hypertext+processor
    foo=bar&baz=boom&cow=milk&php=hypertext+processor
    myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor
    
  • 解url字串
    利用parse_str
    <?php
    $str = "first=value&arr[]=foo+bar&arr[]=baz";
    parse_str($str);
    echo $first;  // value
    echo $arr[0]; // foo bar
    echo $arr[1]; // baz
    
    parse_str($str, $output);
    echo $output['first'];  // value
    echo $output['arr'][0]; // foo bar
    echo $output['arr'][1]; // baz