2012年12月10日 星期一

CodeIgniter 真正的使用session存取資料


應該不少人知道CI的$this->session其實他走的cookie。
雖然有聽說未來的3.0版有可能會還原成真實的session。
但是在那之前,我們也許會希望不要受到cookie的容量限制。
以及安全的使用session。
下面這份code,就將他存成psession.php並放在libraries目錄下。
然後設定autoload即可。
使用方式就只是改成$this->psession。
他的用法和原本的$this->session功能是一樣的。
檔名:psession.php
===================================================
<?php
class psession {
    
    function __construct(){
        if(!session_id())
            session_start();
    }
    
    function set_userdata($sessionName,$sessionValue){
        $_SESSION[$sessionName] = $sessionValue;
    }
    
    function userdata($sessionName){
        if(isset($_SESSION[$sessionName]))
            return $_SESSION[$sessionName];
        return FALSE;
    }
    
    function unset_userdata($sessionName = FALSE){
        if($sessionName == FALSE){
            session_destroy();
            return TRUE;
        }
        if(isset($_SESSION[$sessionName])){
            session_unset($sessionName);
            return TRUE;
        }
        return FALSE;
    }
}

?>

===================================================

2010年8月28日 星期六

php純view樣版載入器

各位版友大家晚安。
小弟呢!長久以來一直接到很多學生的專題疑難。
他們常常都丟程式碼給我看。
但我每次看到都很吐血。
因為......html和php混在一起實在是太難分難解了。
在眾多的技術都討論了MVC的架構理論。
小弟現在也算是codeigniter的重度患者。
但問題在於,很多時候,又不能馬上叫那些學生立刻去學smarty樣版引擎。
或是立刻上手像是zend framework、cakephp、symfony、codeigniter這些東西。
然後大家就陷入了會寫物件的用framework很高興,不會寫的就純寫肉肉長的php
逐步的虐待自己又無法很順利的切割view和程式。
昨天又是一個專題發問過來,我看了一個不大的50行的程式。
其中echo就佔了快要一半。
然而半年以前,曾經寫過一個樣版載入架構,但是他有幾個大缺點。
載入變數定義方式不佳、採用變數置換內容、無法掛入php程式碼……這些問題。
自從用了ci之後,我就不斷的一直思考關於view的問題。
有沒有什麼是可以做純view載入樣板的方法?
ci的動作方式一直讓我擁入想法,卻一直沒有機會實現他。
但是今天卻讓我有機會去實現這麼一個東西。
當然可能有很多高手有寫出類似或根本就是的東西。
不管怎麼說,這樣一個樣板載入器總是能解決很多想把程式和view做最基礎切割的
設計人員,一個不錯的載入器程式。
底下將會公開這個程式的源碼,當然因為是第一版本的東西。
所以自然而然有我不知道可能的bug也不一定。
或者各位覺得這樣的東西應該要加上怎麼樣的功能或是怎麼樣的限制也可以提出討論。
能讓他的功能更加完整也是相當不錯的。
如果有人會覺得你這就是有參考ci的一些方法,這我不否認的確是有。
但無論如何,總是把他輕巧的參考出來並使用。
所以並非全然是超抄使用。各位如果有看過ci和我這隻程式就明白了。

檔名:template_engine.php
<?php
class template_engine{

    function view($source_page,$variable = '',$return = FALSE){
        $variable = $this->_check_array($variable);
        foreach($variable as $key => $value){
            $$key = $value;
        }
        ob_start();
            eval("?>".file_get_contents($source_page.".php")."<?");
            $buffer_tmp = ob_get_contents();
        ob_end_clean();
        if($return)
            return $buffer_tmp;
        echo $buffer_tmp;
    }

    function _check_array($variable){
        if($variable == null)
            return array();
        if(!is_array($variable)){
            echo 'This variable is not array';
            exit();
        }
        return $variable;
    }

}
?>
使用方法:(會用ci或是一般template engine的朋友就一定會用的啦。)
<?php
require('template_engine.php');
$load = new template_engine;
$frame['topbanner'] = $load->view('topbanner','',TRUE);
$frame['leftmenu'] = $load->view('leftmenu','',TRUE);
$frame['body'] = $load->view('body','',TRUE);
$load->view('mypages',$frame);
?>
有用過template engine應該覺得相當眼熟。是的,他該當就是如此的用法了。
$load->view()中有三個參數
第一個參數是載入的樣版檔名,副檔名強制為php,而這邊只需要輸入主檔名。
第二個參數是陣列,你傳入的陣列鍵名在樣版中會被解成變數。
舉例來說:
$data['name'] = 'sam';
$load->view('body',$data);
則在你的body.php中,你要使用$data['name'],他會變成$name。
所以你的body.php中就是直接寫
<?=$name?>
他就會顯示$data['name']的內容。
第三個參數是決定顯示還是傳回內容。
如果輸入TRUE的話是不顯示,將內容傳回至變數。
如果輸入FALSE或是不輸入的話,則會變成將內容顯示出來。
再來要說明的就是,在你載入的樣版中,所以PHP的程式碼都是可執行的。
但無論如何我們還是遵從template engine的一些不成文的規範如下:
1.使用<?=$name?>而不要使用<?php echo $name?>
2.條件式、迴圈、判斷式中的HTML輸出請讓他成為純HTML而不使用echo也不用大刮號
來列示範圍如下:

使用<?php if(條件):?>及<?php else:?>及<?php endif?>
而不使用<?php if(條件){.....}else{}?>

使用<?php while(條件):?>及<?php endwhile?>
而不使用<?php while(條件){.....}?>

使用<?php for(迴圈):?>及<?php endfor?>
而不使用<?php for(迴圈){.....}?>

使用<?php foreach(陣列方法):?>及<?php endforeach?>
而不使用<?php foreach(陣列方法){......}?>

其他一些遵從framework使用的架構規範都是比較好的做法。

目前這個載入器還沒有很深入的去寫比較多的php程式碼在內。
畢竟是純把他當樣版來使用(他也應當必須是當樣版載入來使用)。
若然有bug或是問題還煩請大家回報。
這樣我可以讓這個程式更加的完善。
有什麼需要追加的功能或不錯的意見也請大家能多多提供給我。

總之我是覺得這對很多初探php和html分開作頁的學習者。
這個程式提供了不錯而且有效的解決方案。

總之,我也是盡力在解決這樣的問題上。
幫助需要的人,也透過這樣的模式,讓大家能早一點上手真正的framework。

這是一個輕巧的程式,卻也是我花了很長的時間一直在思考view這件事之後。
所生產出的第一個我覺得真正有幫助到人的東西。

除了鼓勵為動力,也尚祈批評,以供改進。
如要整個程式含範例檔,請來信:
tkdmaf@gmail.com

2010年5月27日 星期四

關於CodeIgniter的HMVC架構。

之前在CodeIgniter(以下簡稱ci)安裝好HMVC之後。一直以為各自的目錄檔案是各自為政。
所以當時為了解決公用view的問題,而跑去寫了library。
最近在編寫model的資料時,卻無意間因為用了&get_instance()而有了一些奇怪的想法。
也不知怎麼的。就把子目錄的model放到公用的model。沒想到原來ci的設定上,當子目錄的model沒有檔案時,他會去公用的model找檔案。
今天在設計前台的頁面時,看看那個view,突然有了「model」是這樣的話會不會view也是這樣的想法?
經過實測確定,原來只要子目錄下找不到檔案時,model和view都會去公用目錄找檔案。
這下就很明白了。如果有一個頁面是「大家都要用到他」時。就放在公用目錄就好了。
當然啦!如果是數個功能都要使用的頁面還是寫在library比較好。
這樣不用每個功能自己都要寫一份mainframe(如果你喜歡,也是可以的。)

2010年1月28日 星期四

[PHP]查詢欄位資料,並限制在一定的欄位資料量才查詢。

其實這是在ptt看到別人寫的問題。
然後把他物件化實作成功能。
主程式如下:
require("sql_connect.php");
require("class.data_serach.php");
$data_serach = new data_serach("test","sick_member",3);
$sql = $data_serach->sql_text();
如此就會獲得一個可以用來查詢的sql字串,再看使用者怎麼去用這個字串。
其中資料庫名稱和資料表以及需要多少表單的資料量才能進行搜尋,必須在物件成生時就給
予其值。(因為寫入建構子)

物件檔名:class.data_serach.php
class data_serach{
    
    function __construct($database,$table,$mixtimer){
        $this->database = $database;
        $this->table = $table;
        $this->mixtimer = $mixtimer;
        $this->load_field();
        $this->post_check();   
    }
    
    function load_field(){
        $result = mysql_list_fields($this->database,$this->table);
        $field_num = mysql_num_fields($result);
        for ($i = 0;$i <$field_num;$i++){
            $fieldarr[] = mysql_field_name($result,$i);   
        }
    $this->fieldarr = $fieldarr;    
    }
    
    function post_check(){
        foreach($this->fieldarr as $value){
            if (strlen($_POST[$value]) != 0){
            $this->where .= "{$value}='{$_POST[$value]}' AND ";
            $this->timer +=1;
            }
        }
    }    
    
    function sql_text(){
        if (($this->timer >= $this->mixtimer)) return "SELECT * FROM incoming WHERE ".substr($this->where,0,-5);
    }
}

2010年1月24日 星期日

[PHP]欄位同mysql資料庫欄位即可順利新增(增加欄位比對,並將欄位參數化)

這一次的修改本物件的功能。
之前會發生如果表單傳入的name名稱多於資料庫欄位時,會造成資料存入錯誤。
雖然前一個版本加上手動排除多餘欄位,但不甚方便。
這一次更新的版本,新增name名稱與資料庫欄位判斷,會將資料庫沒有的欄位名稱排除。
如此就不會造成欄位不符而回應錯誤。
另外為了能夠支援不同型式的資料來源(get、post或是二者都接受),將不同的函式修正成一個參數型態。
物件方法:
$add_sql = new add_sql("資料庫名稱","資料來源")
//資料來源參數:post = $_POST,get = $_GET,request = $_REQUEST

使用範例1:(以支援$_POST為例)
require_once("class.add_sql.php");
$add_sql = new add_sql("table","post");
$add_sql->sql_save();

使用範例2:(以支援$_GET且額外插入資料為例)
require_once("class.add_sql.php");
$add_sql = new add_sql("table","get");
$add_data -> add_text("guestdate",date("Y-m-d H:i:s"));
$add_sql->sql_save();

物件程式:class.add_sql.php
class add_sql{
    function __construct($table,$PostData){
        $this->table = $table;
        $this->load_field();
        $this->PostData($PostData);
        
    }  
    
    function PostData($PostDataIndex){
      $postarray = array("post" => $_POST , "get" => $_GET , "request" => $_REQUEST);
      $this->SetPostData($postarray[$PostDataIndex]);
    }
    
    function SetPostData($PostData)
    {
        $this->PostData = $PostData;
        $this->dearray();
    }
    
    function load_field(){
        $sql = "SELECT * FROM {$this->table} LIMIT 0,1";
        $result = mysql_query($sql);
        $this->sqlfield = mysql_fetch_assoc($result); 
    }  
    
    function bool_field($keyword){
        foreach($this->sqlfield as $key => $value){
            if ($keyword == $key) return TRUE;
        }    
        return FALSE;
    }
    
    function dearray(){
        foreach($this->PostData as $key => $value){
            if ($this->bool_field($key)) {
                $this->add_text($key,$value);
                
            }  
        }
    }
    
    function add_text($add_field,$add_value){
        $this->field .= $add_field.",";
        $this->data .= "'".htmlentities($add_value,ENT_QUOTES,"utf-8")."',";
     }
  
    function sql_text(){
        $field = substr($this->field,0,strlen($this->field) -1);
        $data = substr($this->data,0,strlen($this->data) -1);
        $sql_stmt =  "INSERT INTO `".$this->table."` (".$field.") VALUES (".$data.")";
        return $sql_stmt;
    }
  
    function sql_save(){
        mysql_query($this->sql_text()) or die("NO Action");
    }  
}

2010年1月18日 星期一

[PHP]只要欄位名稱同資料庫名稱時即可順利存入mysql(增加GET、REQUEST)

這次經過我們「敏捷開發」講師ERIC的指導之下。
更進一步的了解了「多型」、「超級繼承」以及「介面」、虛擬函式等等技術。
所以也同時開發出除了原本針對$_POST,又可以變更成$_GET或是$_REQUEST的做法。
用法:
如果是post的來源:
require("class.get_post_sql.php");
$postdata = new add_post("資料表名稱");
$postdata -> sql_save;

如果是get的來源:
require("class.get_post_sql.php");
$postdata = new add_get("資料表名稱");
$postdata -> sql_save;

如果有post和get的來源:
require("class.get_post_sql.php");
$postdata = new add_request("資料表名稱");
$postdata -> sql_save;

有其他的資料來源(以post為例)
require("class.get_post_sql.php");
$postdata = new add_post("資料表名稱");
$postdata -> add_text("資料欄位","值");
$postdata -> sql_save;

檔名:class.get_post_sql.php
interface add_interface{
  
  function add_text($add_field,$add_value);
  
  function sql_text();
  
  function sql_save();
  
  function dearray();
    
}

abstract class super_add implements add_interface{
   
  function __construct($table){
    $this->table = $table;
    $this->dearray();
  }  
    
  function add_text($add_field,$add_value){
    $this->field .= $add_field.",";
    $this->data .= "'".htmlentities($add_value,ENT_QUOTES,"utf-8")."',";
  }
  
  function sql_text(){
    $this->field = substr($this->field,0,strlen($this->field) -1);
    $this->data = substr($this->data,0,strlen($this->data) -1);
    return "INSERT INTO `".$this->table."` (".$this->field.") 
            VALUES (".$this->data.")";
  }
  
  function sql_save(){
    mysql_query($this->sql_text()) or die("NO SAVE");
  }  
}

class add_get extends super_add{

  function dearray(){
    foreach($_GET as $key => $value){
      if ($key != "submit" && $key != "MM_insert" && $key != "button") {
        $this->add_text($key,$value);
      }  
    }
  }
    
}

class add_post extends super_add{
 
  function dearray(){
    foreach($_POST as $key => $value){
      if ($key != "submit" && $key != "MM_insert" && $key != "button") {
        $this->add_text($key,$value);
      }  
    }
  }
 
}

class add_request extends super_add{
 
  function dearray(){
    foreach($_REQUEST as $key => $value){
      if ($key != "submit" && $key != "MM_insert" && $key != "button") {
        $this->add_text($key,$value);
      }  
    }
  }
 
}

2010年1月5日 星期二

[PHP]chghtml - 置換html樣板內容

程式用途:置換html設定的樣板文字(以#?及?#包起來的文字)。
範例:
以一個留言版的html模板為例其顯示如下:


#?account?#
#?guestdate?#

#?textguest?#

當你的php讀取完需要置換的資料並儲存成陣列之後。
就可以使用chghtml這個物件來置換網頁資料並做最終輸出。
其使用方式如下:
$data = array("account"=>"使用者帳號","guestdate"=>"發表時間","textguest"=>"文章內容");
require("class.chghtml.php");
$chghtml = new chghtml("樣板檔名");
$chghtml -> chgpage($data);
※置換陣列變數:需要定義key及value,若資料來源為資料庫時,模版的文字名稱需要和
資料庫的欄位名稱相同才能順利置換。若為一般來源,key應該要等於模版文字名稱。

顯示結果:

使用者帳號
發表時間

文章內容

物件檔名:class.chghtml.php
class chghtml{
    
  function __construct($load){
    $this->load = file_get_contents($load);
  }
      
  function chgpage($data = array()){
    $this->chgpage = $this->load;
    foreach($data as $key => $value){
      $value = str_replace("\r\n","<br>",$value);
     $this->chgpage = str_replace("#?".$key."?#",
      html_entity_decode($value),$this->chgpage);
    }
  }
  
  function output(){
   return $this->chgpage;
  }
}