星期六, 6月 05, 2010

系統分析設計與實作 Week 9

Iteration 1
目的:將需求轉實作
=>要求都要配Controller
整合是持續性的在做整合

軟體開發方法
  1. Data-Orented
    易陷入細節,不易抓出圖
  2. Service-Oriented
    延展、彈性、重複利用


測試 unittest
功能性 => Controller
單元性 => Unit test, Business Object

User方面有UAT(User Acceptance Test)使幅者接受度測試

設計資料庫
設計表格
4大類 (人,事(event)/時,地物)
  1. 抓名詞(需求陳述中抓)
    但片斷,不易看到全貌,需求明確,才能完整
  2. 抓核心
    訂烏龜系統=>訂的event
    門禁管理=>刷卡的event (書UML.P148)
    儘可能容變動的需求
需求不再是主導系統的唯一來源
Enterprise => Transaction
Sub query易隱念企業邏輯,反而影響維

Q & A
  1. UML必要畫?
    UML是個語言,語言是用來溝通,所以獨立一個人開發時,基本上不用畫
  2. 交接時?
    需要時再畫,多一張就多需要維護成本
  3. 如何引導客戶提出需求
    客戶分1.Domain Expert可用活動圖(作業流程)或火箭圖
    2.Operator 直接用畫面UI溝通
    流程圖最好能當場畫,讓使用者確認,避免誤解
  4. CURD
    利用actor當授權

系統分析設計與實作 Week 7

烏龜訂購系統
phase 2 萃取穩定的結構共用元素(企業物件)
  1. middle ware
  2. controller
一開始不容易馬上判斷出來,可先放controller,再透過重構方式「逐漸萃取」
ex. 「計算訂購總額」應該放哪
hint: 推理,不要強記
「計算訂購總額」理論上放在訂購object上,但應該抽出到BO(企業物件),當共用的元素
過去,放store_procedure或script都不算好
但一開始要不容易抽,所以折衷先放controller
將來重構放到business object
=>將可共用的企業規則抽出

交易事件
人,(事/時),地,物
  1. 界定範圍
    利用UC,一般抓到5,6成就夠了
    • User Case View
    • Locial View
      -UC Realization
      -Class Model (配合codegen)
    UC都是片斷,有滿足即可,不要流程,至於滿足的程度依"Session"來判斷
  2. 撰寫UC敘述
    把「容易變」的跟「不容易變」的分開
    共用的可抽出來放
    =>產出Document
  3.  
  4. 實現UC (logical view realization)
    用UC Diagram當doc type
    *橋接實作,即建Conroller
  5. 建Controller
    設計可能會漏掉,由實作(feedback)去做調整,補足或修正Controller, UC Description
    隨時都在調,因此文件要少、精簡,過程中都是只是最後文件的snapshot

16.1.3.資訊系統的分層結構
  • 表達層(Presentation):UI
  • 中間層:CO(Control Object)
    DAO: 將DB存取細節放至DAO,任何跟DB有關的存取透過小弟DAO解決
    Adapter:外部系統的鏈結
    軟體主結構即抽出的概念性物件BO
  • 資料層:Database

三大物件
  1. Controller
  2. Boundary
    實體變動
  3. BO
    應付Domain變動,一開始不易抓,先放controller

循序圖不是要表達精細,重點在完成某功能時,反應run time的流程
EA做Sequence Diagram時,拉物件會要選擇"Simple link or Instance", 選instance,因為是物件
隱含的method用加雙斜線 ex.到db抓資料=>//select

不用每個UC都畫Sequence,只畫比較需要的
何謂需要
programmer無法看出必要的method(無共識時)
UI, Controller 應分開獨立的Project

系統結構面
Jobcason將結構分為
控制
實體
邊界
目的:好分類->好維護
結構只對developer有好處(好維護),User只看畫面

---
為何叫物件導向
都是用類別在定義,為何不是類別導向
心中想像的是物件在互動,而利用class描述出來,
ex. 作曲做的是音樂,但是得利用五線譜「作曲」記錄

安裝PHPUnit

phpunit官網:http://www.phpunit.de/

有兩個主要的版本,依php版本決定
  • PHPUnit 3.7 requires PHP 5.3.3
  • PHPUnit 3.8 requires PHP 5.4.7


兩種方法
  1. 直接使用phpunit
    https://github.com/sebastianbergmann/phpunit/

    <php
    include "phth to PHPUnit";
    class StackTest extends PHPUnit_Framework_TestCase
    {
        public function testPushAndPop()
        {
            $stack = array();
            $this->assertEquals(0, count($stack));
     
            array_push($stack, 'foo');
            $this->assertEquals('foo', $stack[count($stack)-1]);
            $this->assertEquals(1, count($stack));
     
            $this->assertEquals('foo', array_pop($stack));
            $this->assertEquals(0, count($stack));
        }
    }
    ?>
  2. 安裝phpunit
    wget https://phar.phpunit.de/phpunit.phar
    chmod +x phpunit.phar
    mv phpunit.phar /usr/local/bin/phpunit
    vi composer.json
    {
    "require-dev": {
    "phpunit/phpunit": "3.7.*"
    }
    }
    composer install
    程式裡加上
    require 'vendor/autoload.php';

其他PHPUnit官網寫很清楚,而且很多觀念教學,真棒

Zend View 常用動作

  1. jquery觸發submit
    $('form:first').trigger("submit");
  2. url路徑
    //根目錄 - 從web root到public
    $this->baseUrl('course/add'); //參數加入即會自動補
    =>/myweb/public/course/add
  3. 目前url
    $this->url(array('controller'=>'course','action'=>'add')); //如果當前的url是在同一個controller下的話,可以不用給controller參數
    =>/myweb/public/course/add/
  4. Controller, Action Name及參數
    $request = Zend_Controller_Front::getInstance()->getRequest();
    $controllerName = $request->getControllerName();
    $actionName = $request->getActionName();
    $paramArray = $request->getParams();
    $params = '';

    foreach($paramArray as $key => $value)
      $params .= $key . "/" . $value;
  5. 添加CSS 和 JS
    //將js,css放在public裡的js,css資料夾
    <script type="text/javascript" src="<?php echo $this->baseUrl('js/jquery-xxx.min.js');? >" >
    </script?>
    <link rel="stylesheet" type="text/css" href="<?php echo $this->baseUrl('css/xxx.css'); ? >" >
References
Zend - Get everything after base Url (Controller, Action, and any params)

zend DB 常用動作

直接對Zend_Db操作
  • 新增DB連線
    $db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'course'
    ));
  • 下sql語法
    $stmt = $db->query('SELECT * FROM course');
    
    //Zend_Db提供fecth(),可抓出row object
    while($row = $stat->fetch()){
        echo $row['name'];
    }
  • 替換sql語法裡的參數
    $sql = 'SELECT * FROM course WHERE nam = ? AND status = ?';
    $stmt = new Zend_Db_Statement_Mysqli($db, $sql); //mysql就用mysqli
    $stmt->execute(array('demo course','display'));

宣告多個DB
  • 宣告(configs/application.ini)
    //db1
    resources.multidb.course.adapter = "PDO_MYSQL"
    resources.multidb.course.host = "localhost"
    resources.multidb.course.username = "root"
    resources.multidb.course.password = "ok1234"
    resources.multidb.course.dbname = "course"
    resources.multidb.course.driver_options.1002 = "SET NAMES utf8"
    resources.multidb.teegle.default = true
    
    //db2
    resources.multidb.admin.adapter = "PDO_MYSQL"
    resources.multidb.admin.host = "localhost"
    resources.multidb.admin.username = "root"
    resources.multidb.admin.password = "ok1234"
    resources.multidb.admin.dbname = "admin"
    resources.multidb.admin.driver_options.1002 = "SET NAMES utf8"
  • 選擇db
    $resource = $this->PluginResource('multidb');
    $resource->init();
    $db = $resource->getDb('course'); //取得course db
    $db->select()
        ->from( ... ) //多個from
        ->where( ... );

對Zend_Db_Table下指令
  • 設定table
    Zend_Db_Table::setDefaultAdapter($db);
    $courseTable = new Zend_Db_Table('course');
  • 在fetchAll裡加參數
    $resultSet  = $table->fetchAll(
            $table->select()
               ->where('status = ?', 'NEW') //有多個where就再下一次where(xx)
               ->order('id ASC')
               ->limit(10, 0)
    );
    
    //塞進array
    $entries   = array();
    foreach ($resultSet as $row) {   
        $object = row->id; // or row['id'];
        $entries[] = $object;
    }
  • 讓DbTable物件 讀非預設DB
    DbTable會預設讀config裡設定的"db"
    如果要讀一個db怎麼辦咧?
    1.註冊db
    在Bootstrap.php裡,註冊想要讀的db
    //application/Bootstrap.php
    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        $resource = $this->getPluginResource('multidb'); //假設存放在multidb裡,參考如何設定多個db
        $resource->init(); //初始化,不然不會動
    
        //註冊要讀取的DB - admin
        $admin = $resource->getDb('admin');
        Zend_Registry::set("admin", $admin);
    }
  • 2.改寫DbTable的建構子 方法一 就在DbTable的class下,override construct 把要給DbTable的物件參數中的'db'改成目前要讀的db
    class Application_Model_DbTable_User extends Zend_Db_Table_Abstract { 
        protected $_name = 'user'; 
        //方法一     
        public function __construct($config=array()){
            $this->read  = Zend_Registry::get('admin');
            $this->write = Zend_Registry::get('admin');
            $config['db'] = Zend_Registry::get('admin');                       
            return parent::__construct($config);
        }  
    
        //方法二  
        protected function __setupDatabaseAdapter(){ 
        } 
    }
    join
    //Build this query: 
    //  Select p."product_id",p."product_name", l.* 
    //  From "products" AS p JOIN "line_items" AS l 
    // ON p.product_id = l.product_id  
    $select = $db->select()->from (array('p'=> 'products'), 
    array('product_id','product_name'))->join(array('l' => 'line_items'), 'p.produt_id = l.product_id');
References
Zend Framework Certification Study Guide

星期五, 6月 04, 2010

jqueryui button

原來disable不是改tag屬性... (會失敗)
試了好久才發現要丟參數
利用.button( "disable" ), enable就一樣囉

星期二, 6月 01, 2010

星期二, 5月 25, 2010

jqgrid - search

我怎麼照官網做 都沒有search的結果
看官網的php 也不像會有search的結果...

最後還是上網找

server.php (同官網範例,就在下sql那段 加入這個)
$where = "WHERE 1=1 " . constructWhere();
$SQL = "SELECT ... FROM xxx $where ORDER BY $sidx $sord LIMIT $start , $limit";
...

//--------------------------
function constructWhere(){
  $wh = "";
  $searchOn = $_REQUEST['_search'];
  if($searchOn=='true')
  {
   $fld = $_REQUEST['searchField'];

   //過濾欄位,填入會用到search的欄位
   if(!( $fld=='id' || $fld =='name'))
   {
    $fldata = $_REQUEST['searchString'];
    $foper = $_REQUEST['searchOper'];

    //construct where
    $wh .= " AND " . $fld;
    switch ($foper) {
      case "bw":
        $fldata .= "%";
        $wh .= " LIKE '" . $fldata."'";
        break;
      case "eq":
        if(is_numeric($fldata)) {
          $wh .= " = " . $fldata;
        }else{
          $wh .= " = '" . $fldata."'";
        }
        break;
      case "ne":
        if(is_numeric($fldata)) {
          $wh .= " <> " . $fldata;
        }else{
          $wh .= " <> '" . $fldata . "'";
        }
        break;
      case "lt":
        if(is_numeric($fldata)) {
          $wh .= " < " . $fldata;
        } else {
          $wh .= " < '" . $fldata."'";
        }  
        break;
      case "le":
        if(is_numeric($fldata)) {
          $wh .= " <= " . $fldata;
        }else {
          $wh .= " <= '" . $fldata."'"; 
        }
        break;
      case "gt":
        if(is_numeric($fldata)) {
          $wh .= " > ".$fldata;
        } else {
          $wh .= " > '".$fldata."'";
        }
        break;
      case "ge":
        if(is_numeric($fldata)) {
          $wh .= " >= ".$fldata;
        } else {
          $wh .= " >= '".$fldata."'";
        }
        break;
      case "ew":
        $wh .= " LIKE '%".$fldata."'";
        break;
      case "ew":
        $wh .= " LIKE '%".$fldata."%'";
        break;
      default :
        $wh = "";
    }
  }
  return $wh;
}

Reference
忘了哪看的了...

接收完成的callback function
jQuery("#tbSearch").jqGrid({
  datatype:function(postdata) {
  jQuery.ajax({
  url: "server.php", //原本寫在外面的,現在外面那個就參考用
  data:postdata,
  datatype:"json",
  complete:function(xmldata,stat){
   if(stat=="success") {
    //xmldata是XMLHttpRequest, 所以如果是datatype的話,就要 xmldata.responseXML
    alert(xmldata.responseText);
   }
  }
});
},
...

Reference
Data Manipulation
jqGrid 的多字段查詢

星期二, 5月 18, 2010

zend - 關連table

我也不知道怎麼做出來的
一開始明明就照著教學做
可是怎麼做都說有錯
什麼No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname"
不然就什麼 No reference from table $thisClass to table $tableClassname"
說xx table裡找不到reference關係...

最後進到Zend/library/Db/Table/Abstract.php一步步查
先看建構子有存進去了
最後一路看到getReference()
因為會說沒有rule 所以就先把那段解註掉
if ($ruleKey !== null) {
...
}

再看foreach ($refMap as $reference)...這段
明明有哇... 再把註解全拿掉時...
神奇的事發生了...
一切的值都有了 也不會有例外
這... 到底發生什麼事了...= =?

過程中 我是有一直亂改值測試...
可是... 最後成功的值...應該是一樣的
嗯哉~~ 總之先記錄下來.... 免得又遇到了

說明
table "GroupTee"裡有teeid,需要跟table "Tee"的主鍵id做關連
table grouptee
<?php
class Application_Model_DbTable_GroupTee extends Zend_Db_Table_Abstract
{
protected $_name = 'group_tee_rt';
protected $_dependentTables = array('Application_Model_DbTable_Tee'); // 對應到關連的 Table Class
}


table tee
<?php
class Application_Model_DbTable_Tee extends Zend_Db_Table_Abstract
{
protected $_name = 'tee'; //real table name

protected $_referenceMap= array(
'TeeName' => array( //rule名稱
'columns' => array('id'), //tee的pky
'refTableClass' => 'Application_Model_DbTable_GroupTee', //參考GroupTee
'refColumns' => array('teeid') //GroupTee裡的teeid
)
);
}


contoller或應用的地方
$tbGroupTee = new Application_Model_DbTable_GroupTee();
$group = $tbGroupTee ->fetchRow('id=1'); //取得第1個group
$grouptee = $group->findDependentRowset('Application_Model_DbTable_Tee','TeeName');
Zend_Debug::dump($grouptee, $label = "grouptee", $echo = true);



References
初探 Zend_Db_Table Relationships
One To Many Relationship with Zend Framework

星期日, 5月 16, 2010

dokuwiki - gcalendar

不知大家拿來做什麼用
公司是拿來當工作日誌用...
所以有分預定計劃,實際執行及Deadline
而event type當沒沒這麼巧的有這幾樣
不過可自定event type

作法
1.連結內容
=== 預定計劃 ===
*2010-5-3 - 2010-5-4 teegle
=== 實際執行 ===
*2010-5-3
=== Deadline ===
*2010-5-4


2.增加event type
到events.css增加與引用名稱相同的class名
path: [dokuwiki資料夾]/lib/plugins/gcalendar/user/events.css
/* 就是自己增加css的class */
.預定計劃
{
 color:grey; //改字型色彩
}
.實際執行
{
 background-image:url(images/gear.gif); //自行定義圖示
}
.Deadline
{
 color:red;
 bold:true;
 background-image:url(images/deadline.gif); //自行定義圖示
}


3.上傳圖片
就看自己寫到哪就傳到哪個資料夾囉
預設位置是[dokuwiki資料夾]/lib/plugins/gcalendar/user/images

結果如下
嗯 圖示的大小為15*16...
圖有點過大 不過效果還不錯...


Reference:dokuwiki - gcalendar

星期六, 5月 15, 2010

常用的10個jqgrid提示

網路上看的10 JQGrid Tips learned from my experience,再補點自己常遇到的

  1. Changing JQGrid width and height
    "//自動調寬度
    jQuery("#list2").jqGrid({
    autowidth: true, 
    ...
    //手動設定
    $("#list2").setGridWidth(200,true); //忘了true是什麼


    ColModel的屬性

    jQuery("#list2").jqGrid({
    ...
    colModel: [
    {
     name: 'rowid',  //將欄位名稱
     index: 'rowid asc, createddate', //click此欄位的排序會依據的order
      width: 50,
     sorttype: "int",
      align: "center",
     key:true, //將欄位設為pk
     search:true, //是否提供search
     hidden:false, //讓此欄位隱藏
    ...
  2. Grid without unnecessary scroll area
  3. Error due to missing locale file
  4. Callback function
    • loadComplete //ajax完成後的事件
      loadComplete: function(){
      var ids = jqgrid.jqGrid('getDataIDs'); //取得所有ids  
      alert(ids.length);
    • gridComplete //將所有資料讀進grid後的事件
    gridComplete及loadComplete差異
    $("#list").clearGridData();會觸發gridComplete
    利用ajax讀入資料時,jqgrida會先清掉grid內容,但不會觸發gridComplete,而讀完資料時,先後觸發gridComplete及loadComplete
    其他event
  5. Using pagers only for buttons (or icons)
  6. Hiding unwanted buttons in navigation bar
  7. Hiding the inline search by default
  8. Having your own icons for navigation bar buttons
  9. Removing title bar close button
  10. Adding toolbar    

常用指令
  • Get data from selected row
    var id = jQuery("#list2").jqGrid('getGridParam','selrow'); 
    if (id) {
        var ret = jQuery("#list2").jqGrid('getRowData',id); //3.6的方法
        //var ret = jQuery("#list2").getRowData(id);  //3.5以前的方法
        alert("id="+ret.id+" invdate="+ret.invdate+"...");
    } else {
        alert("Please select row");
    } 
  • 刪除
    //設定刪除事件
    $("#bDelete").click(function(){
    // Get the currently selected row
    toDelete = $("#mygrid").jqGrid('getGridParam','selrow');
    
    // You'll get a pop-up confirmation dialog, and if you say yes,
    // it will call "delete.php" on your server.
    $("#mygrid").jqGrid(
    'delGridRow',
    toDelete,
    { url: 'delete.php',
    reloadAfterSubmit:false}
    );
    });
    post資料有[oper] => del,[id] => 88
    Custom delete button in jqGrid

    //直接在navigator裡設刪除事件
    jQuery("#list2").jqGrid({
    ...
    }).navGrid('#pager2', {
    view: true,
    edit: true,
    add: false,
    del: true
    },{
       //依序view
    },{
        /edit
    },{
        //add
    },{
        //delete options 
        url: 'delete.php', //response的url
    
        //submit前驗證,其他看p.s.1
         beforeSubmit : function(id, formid) {
            if (id) {
               var ret = jQuery("#list2").jqGrid('getRowData',id);
               if (!(ret.xxx == "" )
                {
                    return [false,"xxx皆為空白才可以刪除"]; //false會顯示錯誤訊息
                }
            } else {
                return [false,"Please select row"];
            }
            return [true,""]; //true才會繼續
       
    }


    //刪除第12行row
    var su=jQuery("#list5").jqGrid('delRowData',12);
    if(su) 
        alert("Succes. Write custom code to delete row from server"); 
    else
        alert("Allready deleted or not in list"); 
    //清空grid內容
    $("#list1").clearGridData();


References

星期三, 5月 12, 2010

zend - 常見錯誤訊息

  • Action xxx does not exist and was not trapped in __call().
  • 大小寫都試過,最後換個全小寫名稱是成功了 還不知到底是什麼問題
  • Invalid controller specified (CourseTee)
    因為controller的名稱為2個字組合Course, Tee, 但zend不支援什麼駝峰字母,所以真正的名稱被改為Course-Tee 當利用zf create controller CourseTee時 會自動建立controolerview/script/course-tee
  • Zend沒有report error
  • Firefox 回報"伺服器要將此網址重新導向的要求無法完成"

星期二, 5月 11, 2010

jqueryui - dialog

在關閉dialog時 => $(this).dialog('close');
jqueryui會將input的內容清掉...
所以會抓不到.....
氣死... 搞好久才發現...

星期二, 4月 27, 2010

Zend Controller- 常用動作

  1. Debug
    Zend_Debug::dump($row, $label = "current row", $echo = true);
  2. 不render view or layout
    • no render
      $this->_helper->viewRenderer->setNoRender();
    • disable layout
      $this->_helper->layout->disableLayout();
  3. BaseUrl, Controller or Action Name
    透過request取得
    $this->_request->getControllerName()
    ->getActionName()
    ->getParams() //取post或get之類的參數
    ->getBaseUrl()

  4. 轉頁動作
    • redirector,forward
      //給同一controller的 action (ex.index)
      $this->_redirect('Controller/actionA'); //要給完整的Controller及Action
      //=$this->_helper->redirector('actionA');  //如果直給action,會轉給此controller下的action
    • 轉給controllerA的actionA
      $this->_helper->redirector('controllerA/actionA');
      this->_forward('actionA', 'controllerA', null, array('param1' => 'xxx'));

    • $this->_redirect與$this->_helper->redirector的不同? Ans:_redirect需包("controller/action"), redirector可只下("action") ex.在TeeController下 $this->_redirect('index'); //會跑到Index/index,而不會是Tee/index $this->_redirect('Tee') // $this->_helper->redirector('index'); $this->_redirect('Tee/add'); // $this->_helper->redirector('add');
    • 保留訊息給redirect後的頁面
      //set
      $flashMessenger = $this->_helper->getHelper('FlashMessenger');
      $flashMessenger->addMessage($message);

      //get
      $message = $flashMessenger->getMessages(); //array
      if(count($message) == 0 )  
         $this->view->message = "";
      else
         $this->view->message = $message[0];
      }
    • 也可指定Namespace,透過setNamespace即可,範例如下 $flashMessenger->setNamespace('actionErrors');
    • redirect 給參數
      //add parameters
      $controller = 'index';$action = 'message'; $module = null;
      $parameters = array(    'para1' => 'test1',    'para2' => 'test2' );
      $this->_helper->redirector(action , controller , $module, parameters );

      //get parameters
      public function toNextPageAction(){
         $para1 = $this->getRequest()->getParam('para1');
         $para2 = $this->getRequest()->getParam('para2');
      }
    //宣告Registry變數 Zend_Registry::get("course", $course);
  5. 在controller裡,加入Header資訊
    • 加入Meta
      $this->headMeta()->appendName('keywords', 'framework, PHP, productivity');
    • js,css路徑(如果要直接在view裡加入看這)
      $this->view->headLink()->appendStylesheet(‘css/homepage.css');
      $this->view->headLink()->appendStylesheet($baseUrl.'/css/admin/tinybrowser.css');
      $this->view->headScript()->appendFile('/' . $file_uri);
    • 最後要echo資訊到header
      <html>
      <head>
        <?= $this->headTitle() ?>
        <?= $this->headMeta() ?>
        <?= $this->headScript() ?>
        <?= $this->headLink() ?>
        <?= $this->headStyle() ?>
      </head>
      <body>
        <?= $this->layout()->content ?>
      </body>
      </html>

zend 建立CRUD

Zend Framework version: 1.10
參考:Tutorial: Getting Started with Zend Framework 1.10

針對IndexController建立CRUD action
URLAction method
http://localhost/public/IndexController::indexAction()
http://localhost/add /IndexController::addAction()
http://localhost/edit /IndexController::editAction()
http://localhost/delete /IndexController::deleteAction()
分別輸入以下指令:
  • %zf create action add Index
  • %zf create action edit Index
  • %zf create action delete Index
這時除了建立各action的page外,還會自動在IndexController建立各action的動作
所以說如果是要針對UserController,最後的Index就改成User
以下是IndexController的內容
//controllers/IndexController.php
class IndexController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
}

public function indexAction()
{
// action body
}

public function addAction()
{
// action body
}

public function editAction()
{
// action body
}

public function deleteAction()
{
// action body
}
}

vm二三事

VMware Tools
啥是VMware Tools
安裝在vm裡的虛擬os裡的套件

優點
  • 驅動vm裡面os顯卡等,像CentOS只能640 x 480和800 x 600
  • 可直接用滑鼠拖曳傳檔
  • 滑鼠可跨主機與vm視窗移動
  • 複製的東西可以在主機與vm視窗共用

 
安裝:
如何在CentOS安裝VMWare Tools?

組合exe,dll成單一執行檔 - ILMerge

寫好的程式常會include一些dll檔,每次copy給同事,就會發現漏掉dll沒給
查了一下 原來.net下有ILMerge 這好東西
下載:ILMerge

寫法
將aaa.exe跟bbb.dll及ccc.dll合併成Merged.exe
ILMerge.exe /out:Merged.exe aaa.exe bbb.dll ccc.dll
當然要先設環境變數囉
一般預設路徑C:\Program Files\Microsoft\ILMerge

另還有GUI的
不過還是直接在建置事件那設定完最快了
每次compile完 就完成了...真是好東西
到Visul Studio的專案屬性裡的建置事件,如下圖












Error Code
  • 1: 發現是缺了要合併的檔案,補上就ok了
    • 不過有時也有其他問題,要log下來才知道 其他

Reference:
介紹好用工具:ILMerge (將多的 .NET 組件合併成單一組件)

zend - 建立layout

參考:Create A Layout
顧名思義就是套版型,Zend利用將網頁的header,body,footer拆開,方便header及footer可共用,不同的地方(即body),拆給MVC架構完成,所以最後要合併起來
Zend提供了二種做法:
Step1先從資料庫取出資料,Step2再轉成要呈現的資料


某些action不要有layout
將menu鏈結放在layout 則每頁都會有鏈結
但某些情況下,如嵌ifrmae 就不想再出現menu鏈結
就可以在該action下 加入這行
public function xxxAction(){
$this->_helper->layout->disableLayout();
}


加入在controller裡定義的標題資訊
在controller定義好要加入的標題檔資訊後,在layout加入echo的程式
<html>
<head>
  <?= $this->headTitle() ?>
  <?= $this->headMeta() ?>
  <?= $this->headScript() ?>
  <?= $this->headLink() ?>
  <?= $this->headStyle() ?>
</head>
<body>
  <?= $this->layout()->content ?>
</body>
</html>

星期一, 4月 26, 2010

zend 建立form

參考:Create A Form
跟使用者互動就透過form啦
1.建立form
指令:% zf create form Guestbook
Creating a form at application/forms/Guestbook.php
Updating project profile '.zfproject.xml'


// application/forms/Guestbook.php
class Application_Form_Guestbook extends Zend_Form
{
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');
 
        // Add an email element
        $this->addElement('text', 'email', array(
            'label'      => 'Your email address:',
            'required'   => true,
            'filters'    => array('StringTrim'),
            'validators' => array(
                'EmailAddress',
            )
        ));
 
        // Add the comment element
        $this->addElement('textarea', 'comment', array(
            'label'      => 'Please Comment:',
            'required'   => true,
            'validators' => array(
                array('validator' => 'StringLength', 'options' => array(0, 20))
                )
        ));
 
        // Add a captcha
        $this->addElement('captcha', 'captcha', array(
            'label'      => 'Please enter the 5 letters displayed below:',
            'required'   => true,
            'captcha'    => array(
                'captcha' => 'Figlet',
                'wordLen' => 5,
                'timeout' => 300
            )
        ));
 
        // Add the submit button
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Sign Guestbook',
        ));
 
        // And finally add some CSRF protection
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }
}


2.建立對應action
指令:% zf create action sign Guestbook
Creating an action named sign inside controller
at application/controllers/GuestbookController.php
Updating project profile '.zfproject.xml'
Creating a view script for the sign action method
at application/views/scripts/guestbook/sign.phtml
Updating project profile '.zfproject.xml'
// application/controllers/GuestbookController.php
class GuestbookController extends Zend_Controller_Action
{
    // snipping indexAction()...
 
    public function signAction()
    {
        $request = $this->getRequest();
        $form    = new Application_Form_Guestbook();
 
        if ($this->getRequest()->isPost()) {
            if ($form->isValid($request->getPost())) {
                $comment = new Application_Model_Guestbook($form->getValues());
                $mapper  = new Application_Model_GuestbookMapper();
                $mapper->save($comment);
                return $this->_helper->redirector('index');
            }
        }
 
        $this->view->form = $form;
    }
}


3.設定view
<!-- application/views/scripts/guestbook/sign.phtml -->
Please use the form below to sign our guestbook!
<?php
$this->form->setAction($this->url());
echo $this->form;


完成啦,檢查一下http://localhost/guestbook/sign
應該會出現下圖

zend - 建model與database 連結


主要參考官網這篇Create a Model and Database Table

1.db設定檔
指令:zf configure db-adapter
以下各別為開發、測試及成品設定其db
//設定成品db
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_production"&host="localhost"&username="username"&password="ok1234"' production
//設定測試db    
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_testing"' testing
//設定開發db      
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_development"' development
設定完後的結果會存在application/configs/application.ini
所以...其實到application.ini改就可以
那些指令那記得起來...
完整的檔案如下
//application/configs/application.ini
[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.view[]=
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = "ok1234"
resources.db.params.dbname = "db_production"
resources.db.params.driver_options.1002 = "SET NAMES utf8"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.db.adapter = "PDO_MYSQL"
resources.db.params.dbname = "db_testing"

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
resources.db.adapter = "PDO_MYSQL"
resources.db.params.dbname = "db_development"
中文亂碼問題
到application.ini中加入resources.db.params.driver_options.1002 = "SET NAMES utf8"
多個db問題
Zend_Application_Resource_Multidb
留著原本預設的db,才不用再改原本預設的資料

2.建立table物件
針對table(guestbook)建立對應table物件Guestbook.php
指令:% zf create db-table Guestbook guestbook
Creating a DbTable at application/models/DbTable/Guestbook.php
Updating project profile 'zfproject.xml'
Guestbook.php的內容如下
// application/models/DbTable/Guestbook.php
/**
* This is the DbTable class for the guestbook table.
*/
class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
    /** Table name */
    protected $_name    = 'guestbook';
}

3.建立Mapper
剛建立了table物件,在這要建立mapper
mapper的做用在處理insert,delete相關動作地方(要select的欄位,要下的where)
讓table物件與DB處理分開只負責存屬性(欄位)及方法,參考Data Mapper的觀念



% zf create model GuestbookMapper
Creating a model at application/models/GuestbookMapper.php
Updating project profile '.zfproject.xml'
// application/models/GuestbookMapper.php 
public function save($model);
public function find($id, $model);
public function fetchAll();
4.建立model
針對Guestbook建立該model
指令:% zf create model Guestbook
這指令會建立application/models/Guestbook.php
並更新project profile '.zfproject.xml'
// application/models/Guestbook.php
class Application_Model_Guestbook
{
    protected $_comment;
    protected $_created;
    protected $_email;
    protected $_id;

    public function __construct(array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        $this->$method($value);
    }

    public function __get($name)
    {
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        return $this->$method();
    }

    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    public function setComment($text)
    {
        $this->_comment = (string) $text;
        return $this;
    }

    public function getComment()
    {
        return $this->_comment;
    }

    public function setEmail($email)
    {
        $this->_email = (string) $email;
        return $this;
    }

    public function getEmail()
    {
        return $this->_email;
    }

    public function setCreated($ts)
    {
        $this->_created = $ts;
        return $this;
    }

    public function getCreated()
    {
        return $this->_created;
    }

    public function setId($id)
    {
        $this->_id = (int) $id;
        return $this;
    }

    public function getId()
    {
        return $this->_id;
    }
}

5.建立controller
指令:% zf create controller Guestbook

  • Creating a controller at application/controllers/GuestbookController.php
  • Creating an index action method in controller Guestbook
  • Creating a view script for the index action method at application/views/scripts/guestbook/index.phtml
  • Creating a controller test file at tests/application/controllers/GuestbookControllerTest.php
  • Updating project profile '.zfproject.xml'

=>會建立預設的index action
// application/controllers/GuestbookController.php
class GuestbookController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $guestbook = new Application_Model_GuestbookMapper();
        $this->view->entries = $guestbook->fetchAll();
    }
}

6.編輯view
<!-- application/views/scripts/guestbook/index.phtml -->
<p><a href="<?php echo $this->url(
    array(
        'controller' => 'guestbook',
        'action'     => 'sign'
    ),
    'default',
    true) ?>">Sign Our Guestbook</a></p>

Guestbook Entries: <br />
<dl>
    <?php foreach ($this->entries as $entry): ?>
    <dt><?php echo $this->escape($entry->email) ?></dt>
    <dd><?php echo $this->escape($entry->comment) ?></dd>
    <?php endforeach ?>
</dl>

總算結束了
鍵入http://localhost/guestbook 應該會看到下面畫面