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

2019年9月11日 星期三

網頁浮動式固定選單_CSS+JS

RWD風行,所以網站的前端要考慮的層面就多了很多,前端目前缺乏所以得自己來,浮動式固定選單挺常用到,備忘囉!!

CSS
<style>
  .navFixed {
  z-index: 10;         
  position: fixed;     
  top: 0;
  left: 0;
  margin-top: 0;
  min-width: 100%;
  opacity: 0.94;
  transition: opacity .5s ease-out; 
  }
</style>

JS
  <script type="text/javascript">
$(function() {
  $(window).scroll(function() {
    if ($(this).scrollTop() > 495)  {          /* 要滑動到選單的距離 */
       $('.dropdowns').addClass('navFixed');   /* 幫選單加上固定效果 */
    } else {
      $('.dropdowns').removeClass('navFixed'); /* 移除選單固定效果 */
    }
  });
});
  </script> 

HTML
  <div class="navFixed" ></div>

參考來源: https://edwardzou.blogspot.com/2017/09/fixMenu.html

2019年3月12日 星期二

CI cookies, session, cache memo

在CodeIgniter中頻繁使用Model在資料量大使用量高的EC網站是不好的選擇,可是EC網站的資料也不適合用靜態頁來處理,畢竟有許多互動的設計若是使用靜態頁那麼就失去意義了,某些(聯絡我們, 用戶條款)之類的到是很適合。
Ex. $this->output->cache($n);
放置在Controler的 $this->load->view($action, $data); 前。

首先在config/autoload.php裡面需要加入相關的help
$autoload['helper'] = array('cookie');

寫入
set_cookie('cookname', $cookdata, 3600);
取得
get_cookie('cookname')
刪除
delete_cookie('cookname');

於多網站共用Code的使用案例上,可是當使用prefix前綴來避免衝突/讀取錯誤的情事。
※全域設定可在 application/config/config.php 檔案中所設置的前綴  $config[‘cookie_prefix’]
※容量(size)大概4K使用,所以資料量大的話會無法儲存,存放於用戶端的瀏覽器內所以瀏覽器有限制存取時會無法使用。

首先在config/autoload.php裡面需要加入相關的help
$autoload['libraries'] = array('session');

寫入
$this->session->set_userdata('sessionname', $cookdata);
取得
$this->session->userdata('sessionname')
刪除
$this->session->unset_userdata('sessionname');
※ 容量(size)大概較Cookies大些但若是無法儲存則表示資料量超過容量限制,另外資料存放在記憶體內,伺服器記憶體管理務必注意。

cache:
$this->load->driver('cache'));


寫入$this->cache->save('cachename', $cookdata, 300); //300=5min
取得
$this->cache->get('cachename')
刪除
$this->cache->delete('cachename');
※ 使用檔案儲存所以資料量不用擔心,不過因為是FILE所以I/O讀取的效率就偏低。

2019年1月9日 星期三

微信支付 By API 異常排除

近期在套用微信支付API碰到"數位簽章校驗不通過"的回覆困擾許久,程式碼檢查再檢查與文件對應都看不出所以然來,在檢視機台終端交易密鑰的更新Log發現相同程式碼下不同的終端編號會有不同的結果,若干編號就是回校驗不通過。

經查API文件僅敘述簽名檔做好SHA256運算後再以base64編碼置入sign中,此一現象在此網誌所述雷同,於是在base64編碼後在加上urlencode()後傳出,問題就排除了。

$hashValue= hash('sha256', $string, TRUE);
$sign=urlencode(base64_encode($hashValue));

小記:系統整合尤其是透過API交換資料的情況下,這類問題往往很難從單一方面去排除,尤其在另一方(內地? 代理的銀行端? 有聽沒有懂的客戶? )已讀不回或不讀不回下僅能以trial and error方式來排除,恩恩...期間所遭遇個管理層級與客戶層級的質問心酸,只能共勉之...


2019年1月4日 星期五

處理 curl call error(77) error(60) 備忘!


這陣子發生呼叫API無回應但API也沒有LOG(所以是沒有呼叫到API),後來在WEB端的Log檔看到crul回傳 err 77的記錄。

這個狀況因為只出現在特定機器上,所以看來非佈署問題與程式碼bug,新客戶網站後來新增SSL,但只用service nginx reload讓他生效並未執行service php-fpm restart,檢視SERVER運行時間已經百餘日也沒重啟過,所已將php-fpm重啟後就不會再發生相同的錯誤回報。

補充: 頁面使用JQuery(非同步)機制雖然能減少與伺服器端的資料交換量,可若啟用CSRF機制時若timeout時間設定太短而頁面太久沒有reload,會造成瀏覽者有頁面沒反應的情況,這部分在設計時需要檢查回傳值若為token過期狀態,則須強制頁面reload更新token已利正確運行。

使用curl增加設定:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0)

使用file_get_contents增加設定:
$arrContextOptions=array(
"ssl"=>array(
    "verify_peer"=>false,
    "verify_peer_name"=>false,
  ),
);
file_get_contents($target,false,stream_context_create($arrContextOptions));

2018年9月18日 星期二

Codeigniter使用OracleDB 備忘

1. 下載 Oracle Instant Client,建議下載32位元的貌似使用在Windows環境下的PHP的php_oci12c.dll是編譯在32位元的,當然自行下載source code編譯的就依照自己設定的為主。

※ 透過phpinfo()看所安裝的PHP是x86 or 64然後下載相對應的Oracle Client版本回來,不過通常是32位元的就是了。

2. 將下載回來的Oracle Client (建議:Instant Client Package - Basic )解壓縮後的路徑位址( N:\instantclientXX\ ) 新增到系統環境變數內,請記得重新開機以利生效。

3. 至php.ini將php_oci12c.dll前面的分號";"拿掉,然後重啟web server(ex. IIS or Apache)。

4. 在CI的config\database.php
$db['default'] = array(
'dsn' => '',
'hostname' => '(IP or DomainName)/(SID)',
'username' => 'account',
'password' => '******',
'database' => '',
'dbdriver' => 'oci8',
'dbprefix' => '',
'pconnect' => FALSE,
'db_debug' => (ENVIRONMENT !== 'production'),
'cache_on' => FALSE,
'cachedir' => '',
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
'failover' => array(),
'save_queries' => TRUE
);

5. 若依舊是顯示oci_connect() 未定義的錯誤,那麼就再下載含有Net Manager 的 Oracle Client。之前碰到Oracle Client裝64位元但:Instant Client裝x86,這樣PHP是沒法啟用oci8的套件。

備忘:
1. 改Oracle後table & column name都變大寫,好用的AI沒了得改sys_guid() ... 還有很多很多 =.=
2. CI在Sql Query會加雙引號,若使用Oracle須改system\db_driver.php 把雙引號拿掉。
3. CI2使用Oracle是悲劇的(ex. rownum()),後來直接改使用CI3就順多了。

2018年3月20日 星期二

夯名詞:新零售, 區塊鏈, 人工智慧有感

最近聽得多CI BI AI,這類高來高去的名詞,身為一位相對務實的開發人員,對於這些總是環繞在怎麼做到~做到了又如何應用的死循環中。

先有需求再建構/配合模型,自所擁有的管道(軟體服務)蒐集(CI)有用的RAW DATA,送入模型後得到BI(商業智慧),進送入機器學習建構資源庫未來依此來判別(AI),感覺上好像是在消滅自己工作一樣,一但有了AI那麼系統開發作業不就會被代勞嗎(=.= 真是想太多了,不過工程師有個好處,沒有理論支援下產出的工人智慧,對某些人來看也會被美化成人工智慧)。

AI在課堂中最早是從類神經網路的建構,透過訓練方式來歸納出許多的 pattern,這些在依照所配得權重以計算出最合適的結果,恩恩...這樣看來如何取代工作呢? 不過市場上所有產品都是需要包裝的,當軟體要搭上這股熱潮再不打算大改的情況下,只好再透過重新包裝來應付,但這些也是得燒掉多的腦細胞。

新零售也是如此,貌似"無人商店"也得沾上一點邊,亞馬遜所提的概念店面東改西湊(東施效顰的概念),別人有的都加進來沒有的就是優勢? 不過所看的到的都是表象,技術這類的潘朵拉之盒卻得不到;在區塊鏈上因bitcoin而廣受討論,兩個相加起來就是如何去中間話在新零售上,生產->配銷->消費者的概念把中間的"經銷商"由軟體系統取代掉,讓消費者能快速取得新鮮品優的產品(當然能做到價廉就更不可思議了),可現實真是能如此嗎? 大家都覺得經銷商賺得飽飽的(Ex. 專門剝削生產端宰殺消費者的菜蟲?),但是許多事情都有他不為人知的專業在,各個環節所需承擔的風險成本往往是被忽視的,用軟體系統+AI來處理掉中間人學術討論上總是誘人的,回歸現實就傷腦筋囉...

拜讀21世紀資本論(超厚)比起看富爸爸窮爸爸系列來的有感,資本市場講求的看中的或許底蘊有那麼1%重要的,其他99%就不是腦袋硬梆梆只會硬幹的人能去求的,當創造話題的大老們衝在前頭,後頭收尾的工程師們...除了爆些新鮮個肝賺取微薄的OO之外,就只能幻想"有夢最美希望相隨"不是口號的一天,呵呵。

~~有段順口溜流傳許久,繼續做自我看著笑笑即可 ~~
東混西混,一帆風順;  苦幹實幹,撤職查辦;
盡職負責,卻遭指責;  任勞任怨,永難如願;
推拖栽贓,滿排勳章;  屢建奇功,打入冷宮;
不拍不吹,狗屎一堆;  全力以赴,升遷耽誤;
苦苦哀求,互踢皮球;  看緊國庫,馬上解僱;
會捧會現,傑出貢獻;  會鑽會溜,考績特優。

2018年2月9日 星期五

Nginx return 405 error

最近搬移伺服器,WEB伺服器也同步將Apache改成Nginx,客戶回報標籤列印軟體出現異常無法同步更新,Debug後看到回傳405錯誤,可該URL直接呼叫卻是能取得資料的,爬了些文看到解法...

於conf檔中新增error_page 405 =200 $request_uri;後重啟nginx排除掉問題。

location / {
        error_page 405 =200 $request_uri;
        try_files $uri $uri/ /petel/index.php;
 }

至於後來想想為什麼要用POST方式而不使用GET方式取呢? 往常POST請求也可以做到GET請求的回覆,所以從程式碼共用/使用的方向來想也挺合理的,只不過Apache沒出這種問題吧。


2018年2月2日 星期五

透過CKEditor或Summernote上傳iphone拍的圖片顯示被轉向問題

Bootstrap的RWD設計很方便,不過開發狀況上要考慮的點就挺多的,客戶反映說手機上圖時顯示是反的,但是圖下載下來是正的,乍聽之下挺神奇的不是事實卻是如此。

爬文得知在iphone手機拍攝照片時,會取決於拍照按鈕位置來存檔,所以在圖片的Orientation的狀態上就可能是旋轉的,不過在PC檢視上通常會自動轉回來可是瀏覽器就...參考網誌

另外因為手機的鏡頭跟效能越來越強,所以照片的解析度SIZE變超大,看起來是很舒服不過在WEB應用上就挺占頻寬的,簡單的壓縮功能就一併去實現囉。

//圖檔壓縮與旋轉
function image_resize($targetFile){
if (file_exists($targetFile)){
$img_array = getimagesize($targetFile);
$isResize = false;
$ratio = 512;
if ($img_array[0] > $ratio){
$config['width'] = $ratio;
$height = $img_array[1] / ($img_array[0] / $ratio);
$config['height'] = intval($height);
$isResize = true;
} else if ($img_array[1] > $ratio){
$config['height'] = $ratio;
$width = $img_array[0] / ($img_array[1] / $ratio);
$config['width'] = intval($width);
$isResize = true;
}
if ($isResize){
$this->load->library('image_lib');
$config['image_library'] = 'gd2';
$config['source_image'] = $targetFile;
$config['maintain_ratio'] = TRUE;

//because iphone photo maybe save rotation by sensor
$exif = @exif_read_data($targetFile);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
  case 8:
   $config['rotation_angle'] = '90';
   break;
  case 3:
   $config['rotation_angle'] = '180';
   break;
  case 6:
   $config['rotation_angle'] = '270';
   break;
}
$this->image_lib->initialize($config);
$this->image_lib->rotate();
}
$config['rotation_angle'] = '0';
$this->image_lib->initialize($config);
$this->image_lib->resize();
}

return true;
} else {
return false;
}

}

2017年10月18日 星期三

CKEDITOR在Bootstrap Model中功能視窗跳到背景的FIX

套用RWD頁面很方便,但有些眉眉角角就得特別處理,CKEDITOR很好用兩個勾稽在一起,熊熊發現不是那麼的圓滿,當然官方也是都有解的,要找而已...Memo囉。

大體來講這個問題出在版面上,所以調整上還是不脫CSS跟JS的配合。
解決方式:
CSS
<style type="text/css">
    /* (style-metronic)modal conflict with popup of ckeditor (fix) */
.modal-backdrop {
    z-index: 1040 !important;
}
.modal {
    z-index: 1050 !important;
}
</style>

JS
<script>
// CKEditor Link input not working in bootstrap modal (fix)
$.fn.modal.Constructor.prototype.enforceFocus = function () {
    var $modalElement = this.$element;
    $(document).on('focusin.modal',
        function (e) {
            var $parent = $(e.target.parentNode);
            if ($modalElement[0] !== e.target &&
                !$modalElement.has(e.target).length &&
                !$parent.hasClass('cke_dialog_ui_input_select') &&
                !$parent.hasClass('cke_dialog_ui_input_text')) {
                $modalElement.focus();
            }
        });
};
</script>

2017年6月29日 星期四

PHP的file_get_contents 逾時操作

在PHP中file_get_contents蠻常用到的,需要注意的地方大概就是在php.ini裡需要將allow_url_fopen = on,還有就是User Agent偽裝一下

ini_set('user_agent','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0')

不過最近發現到如果呼叫的url過大,就有一定的機率回500錯誤  Orz...

解決方法:
GET:

  $opts = array(  
     'http'=>array(  
          'method'=>"GET",  
          'timeout'=>600,  
       )  
   );  
  $context = stream_context_create($opts);  
  file_get_contents($target_url, false, $context);

POST:

function Post($url, $post = null)  
{  
    $context = array();  
   
    if (is_array($post)) {  
        ksort($post);  
   
        $context['http'] = array (  
            'timeout'=>600,  
            'method' => 'POST',  
            'content' => http_build_query($post, '', '&'),  
         );  
    }  
   
    return file_get_contents($target_url, false, stream_context_create($context));  
}  
   
$data = array (  
    'name' => 'test',  
    'email' => 'test@gmail.com',  
    'submit' => 'submit',  
 );  
Post('http://www.example.com', $data);  

加上TimeOut時間就能避免了,不過就是等久了些使用者會不耐煩。在JQuery的非同步執行下~等久了有若干機會造成DB的Deadlock狀態(透過呼叫API同步資料再搭配系統操作...)。

PS. 建議使用curl或fsockopen來處理,file_get_contents用起來簡單但是其缺點也是挺無奈地,萬一主機商不給改php.ini 或是資料量大或運算/執行較久的頁面,那Debug起來不方便。



2017年1月5日 星期四

用資料用JSON編碼搭配POST方式的交換機制~備忘

與異質平台整合(如金流)碰上資料交遞上的方法,有時資料封裝得做JSON編碼不是直接參數名送出,因此寫個MEMO幫助記憶...

傳送時...

1. 首先是資料傳遞的FUNC ,$Url是目的地、$post就是交換的資料,若要改成GET則調整CURLOPT_CUSTOMREQUEST設定即可。timeout時間故意調長,因為碰上timeout錯誤時很殘念的。

function PostData($Url, $post){
 $ch = curl_init($Url);
 $headers = array(
   'Content-Length:'.strlen($post),
   'Content-type: application/json'
 );
 //print_r($headers);
 $options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_CUSTOMREQUEST=>"POST", 
CURLOPT_POSTFIELDS=> $post,
CURLOPT_HTTPHEADER=> $headers,
CURLOPT_TIMEOUT=>500,
CURLOPT_CONNECTTIMEOUT=>5
 );
 curl_setopt_array($ch, $options);
 $result = curl_exec($ch);
 if(curl_errno($ch)!=0){
  trigger_error(curl_error($ch));
 }
 curl_close($ch);
 return $result;
}

2. 傳遞參數封裝,做成陣列即可...弄複雜些給個陣列包陣列的sample

$params_data = array( 
 'order_no' =>  $order_no,
 'amt' =>  $amt,
 'result_url' =>  $result_url
);

$order_data = array (
 'sender' => "rest",
 'ver' => "1.0.0",
 'tx_type' => 1,
 'params' => $params_data 
);

3. 開始傳遞
PostData($URL, json_encode($order_data));

接收時....

1. 首先...因為不知道傳回來的是啥變數名,只知道是個JSON串,所以通通一起收php://input是蠻方便的方式。
$post_data = file_get_contents("php://input");

2. 拆解JSON取得資料,原則上卡關較久的是array裡面的array資料讀取。
$j_result = json_decode($post_data);
$data = array(
   'order_no'=> $j_result->params->order_no,
   'sender'=> $j_result->sender,
 );


2016年10月5日 星期三

codeigniter csrf機制設定

串接金流後...想找些避免被有心人士誤用的頁面稽核機制,除了原有的那些措施之外,有文章推薦可啟用在 CI 2.0的 csrf(Cross Site Request Forgery) protection 功能。

設定 application\config\config.php將csrf打開

$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;

接著在View中如果有需要提交的Form則使用form_open(action, variable array)來寫就會直接產生相關的Code,真方便。

不過...如果有接收金流的Return Url時,會出現不給接收的Message(謎之聲~當然因為金流公司不會送相關的稽核Code過來。
解法:

設定 application\config\config.php中改寫為

if (stripos($_SERVER["REQUEST_URI"],'controler name/function name') === FALSE) {
  $config['csrf_protection'] = TRUE;
else 
  $config['csrf_protection'] = FALSE; 

這樣就能有例外情況了。

另外如果不想使用form_open()要手動來的話~找到的範例如下。
$(function(){
    $('#btn').click(function(){
        $.ajax({
            type:'POST'
            ,url:'/ajax' //ajax接收的server端
            ,data:$('#form').serialize()+'&csrf_test_name='+ getCookie('csrf_test_name')
            ,success:function(data){
            alert(data.msg);
            }
            ,dataType:'json'
        });
    });
});

function getCookie(name){
    var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
    if(arr != null) return unescape(arr[2]); return null;

}

2016年8月25日 星期四

phpmailer 無法寄信狀況排除的備忘

首先...先測試伺服器連線是否正常

yum install telnet <- 安裝telnet套件

telnet DomainName 25 ... 要有回應,輸入Quit跳開

其次可能是SELinux擋掉,所以使用

getsebool httpd_can_sendmail ... 必須是ON

如果是OFF則使用 setsebool httpd_can_sendmail=1

貌似歧途...
有網友提到可能是openssl造成,前提必須是認證使用TLS或SSL
透過php -i檢查是否有支援openssl,如果沒有就安裝並將openssl.so enable.

CodeIgniter 網址列 index.php去除備忘

之前嘗試失敗的今天成功了,備忘一下...主要差別在httpd.conf AllowOverride沒設成 ALL所致。現在URL看起來清爽多了。

1. ../.htaccess增加
DirectoryIndex index.php
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

2. 在../application/config/config.php
$config['index_page'] = ''; 原:'index.php'

3. vim httpd.conf
LoadModule rewrite_module modules/mod_rewrite.so => 去掉#
AllowOverride None=> AllowOverride All

At Ubuntu 16.04

aptitude reinstall apache2.2-common
a2enmod headers
sudo a2enmod rewrite
service apache2 restart

2016年7月26日 星期二

CodeIgniter套用language備忘

在CI預設FrameWork是沒加上語系表,不過語系表方便多國語言套用~這很好用就Memo一下!!

在language新增相關語系資料夾 etc: en, zh ...

在config
  : autoload
  $autoload['model'] = array('Appconfig', ...

  :config
  $config['language'] = 'zh';

  :hooks
  $hook['post_controller_constructor'] = array(
                                'class'    => '',
                                'function' => 'load_config',
                                'filename' => 'load_config.php',
                                'filepath' => 'hooks'
                                );

在hook
  新增load_config.php

function load_config(){
    $CI =& get_instance();
    foreach( $CI->Appconfig->get_all()->result() as $app_config )
    {
        $CI->config->set_item( $app_config->key, $app_config->value );
    }
    
    //Set language from config database
    //Loads all the language files from the language directory
    
    if ( $CI->config->item( 'language' ) )
    {
        $CI->config->set_item( 'language', $CI->config->item( 'language' ) );
        
        $map = directory_map('./application/language/' . $CI->config->item( 'language' ));

        foreach($map as $file)
        {
            if ( substr(strrchr($file,'.'),1) == "php")
            {
                $CI->lang->load( str_replace( '_lang.php', '', $file ) );    
            }
        }
    }
    
    //Set timezone from config database
    if ( $CI->config->item( 'timezone' ) )
    {
        date_default_timezone_set( $CI->config->item( 'timezone' ) );
    }
    else
    {
        date_default_timezone_set( 'America/New_York' );
    }
}
  
在model
  新增appconfig.php

class Appconfig extends CI_Model {
function exists($key)
{
$this->db->from('app_config');
$this->db->where('app_config.key',$key);
$query = $this->db->get();

return ($query->num_rows()==1);
}

function get_all()
{
$this->db->from('app_config');
$this->db->order_by("key", "asc");
return $this->db->get();
}

function get($key)
{
$query = $this->db->get_where('app_config', array('key' => $key), 1);

if($query->num_rows()==1)
{
return $query->row()->value;
}

return "";

}

function save($key,$value)
{
$config_data=array(
'key'=>$key,
'value'=>$value
);

if (!$this->exists($key))
{
return $this->db->insert('app_config',$config_data);
}

$this->db->where('key', $key);
return $this->db->update('app_config',$config_data);
}

function batch_save($data)
{
$success=true;

//Run these queries as a transaction, we want to make sure we do all or nothing
$this->db->trans_start();
foreach($data as $key=>$value)
{
if(!$this->save($key,$value))
{
$success=false;
break;
}
}

$this->db->trans_complete();
return $success;

}

function delete($key)
{
return $this->db->delete('app_config', array('key' => $key)); 
}

function delete_all()
{
return $this->db->empty_table('app_config'); 
}
}