<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-88  評論-77  文章-48  trackbacks-0
     
    1.Image格式文件轉成byte[]?

    答:第一步:
    如何獲得image對象的int數組呢?這個就簡單了可以通過獲得RGB數組就可以。Image對象中有直接的getRGB方法,不過這里的參數的位置和J2SE中不太一樣
    第二步,把得到的Int數組再生成byte數組。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6559&page=1

    2.eclipse中RMS保存的文件在哪里?

    答:圖像文件保存的時候先轉化為byte[]?不是String?

    存儲的時候一般存儲為***.db文件??目錄在wtk_home/appdb/模擬器/***.db
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6470&page=1


    3.關于播放midi

    答:須明確的一點是?我們的MIDlet是運行在Java?ME平臺環境下的??不一定設備提供的功能在Java?ME平臺都得到了實現
    你可以將虛擬機可以播放的音樂類型!
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=6455&page=1


    4.團隊開發利器CVS培訓基礎講義

    答:詳細見:http://www.j2medev.com/bbs/dispbbs.asp?boardID=4&ID=6324&page=1


    5.netBean能用兩個代碼窗口顯示同一個類嗎?

    答:不能

    6.g.drawString()占用內存問題

    答:drawString()方法本身不占內存,關鍵是drawString中的參數string是不是每次都new了一個,如果把分數變成圖片這樣就不會new新的對象,從而節省了內存和gc的頻率。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=5319&page=2

    7.手機上使用過三重的圖形緩沖技術

    答:三重圖形緩沖又稱翻頁技術。這種方法不一定會提高繪制速度,在J2SE中系統會根據速度在二重緩沖和該方法中自動進行切換,當然僅僅是1.4版本以后添加的。一般的MIDP設備應該會吃不消。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=5376&page=2

    8.索愛k700模擬器支持中文顯示修改方法

    答:SonyEricsson_Z520.properties和SonyEricsson_K700.properties的不同點,發現只是
    font.default?=?.......這塊字體屬性不一樣而已,因此就將k700所需的字體換成z520用的字體,就能顯示中文了。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=4&ID=3061&page=2

    9.模擬核彈的爆炸效果

    答:具體實現依賴于程序結構,原理就是顯示一張圖片后,循環一定次數才顯示下一張圖片。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=6182&page=2

    10.UI界面和CANVAS類之間如何切換屏幕?

    答:在Canvas的paint()方法中把屏幕清一下???比如用白色覆蓋一下
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=1413&page=1

    11.關于?properties文件

    答:用UE或者notepad應該都可以打開,這個文件是用來配置模擬器的特性的?比如是否支持觸摸屏。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6524&page=1

    12.在E680I中如何實現全屏

    答:在midp2.0下,摩托羅拉的機子也是可以用Canvas.setFullScreenMode()來全屏的,最上面的電池格以及信號強弱格那一窄條是固定的。而Nokia和索愛就不這樣,全屏真的是全屏。(不過經過斑竹mydeman實際實驗后指出,E680I的確可以實現真全屏,可能是各個版本不同的關系請廣大站友自己實驗后得出正確結論,然后反饋給我)
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=6216&page=1

    13.J2ME中顯示時間的問題

    答:Calendar?ca?=?Calendar.getInstance();
    ????????int?year?=ca.get(Calendar.YEAR);
    ????????int?month=ca.get(Calendar.MONTH)+1;
    ????????int?day=ca.get(Calendar.DATE);

    14.這是個什么錯誤MontyThread?-6

    答:程序用了platformRequest來調用真機上不支持的功能
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6334&page=1

    15.JDK1.5可否用來開發MIDP,

    答:可以

    16.如何由jar生成相應的jad文件

    答:用ezJad等生成工具。
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=17&ID=6019&page=3
    工具下載地址:http://www.j2medev.com/Soft/ShowSoft.asp?SoftID=299

    17.怎樣判斷g.darwImage()方法是否執行完畢一次

    答:加個flag?或者等paint()執行完??
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=4683&page=4

    18.eclipse開發的J2ME程序中顯示圖片出現異常

    答:eclipse?中?file--->new--->java---->source?folder?記得一定得是source?folder
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=568&page=4

    19.Httpconnect?連接超時問題
    答:It?is?not?possible?to?set?the?connection?timeout?in?a?midlet.?The?timeout?behavior?is?fixed?and?is:1.?For?open(),?if?the?connection?cannot?be?made?after?60?seconds,?the?open()?will?throw?IOException.2.?For?read(),?if?no?data?arrives?after?40?seconds,?the?read()?will?throw?IOException.3.?For?write(),?if?the?data?cannot?be?sent?out?after?40?seconds,?the?write()?will?throw?IOException.
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=5345&page=5

    20.motov600的左右軟鍵怎么用
    答:v600的左右鍵為21,22和E398的正好相反.
    原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=5284&page=5
    posted @ 2006-04-29 09:11 崛起的程序員 閱讀(230) | 評論 (0)編輯 收藏
    PHP V5 新的面向對象編程特性顯著提升了這個流行語言中的功能層次。學習如何用 PHP V5 動態特性創建可以滿足需求的對象。

    PHP V5 中新的面向對象編程(OOP)特性的引入顯著提升了這個編程語言的功能層次。現在不僅有了私有的、受保護的和公共的成員變量和函數 —— 就像在 Java?、 C++ 或 C# 編程語言中一樣 —— 但是還可以創建在運行時變化的對象,即動態地創建新方法和成員變量。而使用 Java、C++ 或 C# 語言是做不到這件事的。這種功能使得超級快速的應用程序開發系統(例如 Ruby on Rails)成為可能。

    但是,在進入這些之前,有一點要注意:本文介紹 PHP V5 中非常高級的 OOP 特性的使用,但是這類特性不是在每個應用程序中都需要的。而且,如果不具備 OOP 的堅實基礎以及 PHP 對象語法的初步知識,這類特性將會很難理解。

    動態的重要性

    對象是把雙刃劍。一方面,對象是封裝數據和邏輯并創建更容易維護的系統的重大方式。但另一方面,它們會變得很繁瑣,需要許多冗余的代碼,這時可能最希望做到的就是不要犯錯。這類問題的一個示例來自數據庫訪問對象。一般來說,想用一個類代表每個數據庫表,并執行以下功能:對象從數據庫讀出數據行;允許更新字段,然后用新數據更新數據庫或刪除行。還有一種方法可以創建新的空對象,設置對象的字段,并把數據插入數據庫。

    如果在數據庫中有一個表,名為 Customers,那么就應當有一個對象,名為 Customer,它應當擁有來自表的字段,并代表一個客戶。而且 Customer 對象應當允許插入、更新或刪除數據庫中對應的記錄。現在,一切都很好,而且有也很多意義。但是,有許多代碼要編寫。如果在數據庫中有 20 個表,就需要 20 個類。

    有三個解決方案可以采用。第一個解決方案就是,坐在鍵盤前,老老實實地錄入一段時間。對于小項目來說,這還可以,但是我很懶。第二個解決方案是用代碼生成器,讀取數據庫模式,并自動編寫代碼。這是個好主意,而且是另一篇文章的主題。第三個解決方案,也是我在本文中介紹的,是編寫一個類,在運行時動態地把自己塑造成指定表的字段。這個類執行起來比起特定于表的類可能有點慢 —— 但是把我從編寫大量代碼中解脫出來。這個解決方案在項目開始的時候特別有用,因為這時表和字段不斷地變化,所以跟上迅速的變化是至關重要的。

    所以,如何才能編寫一個能夠彎曲 的類呢?





    回頁首


    寫一個柔性的類

    對象有兩個方面:成員變量方法。在編譯語言(例如 Java)中,如果想調用不存在的方法或引用不存在的成員變量,會得到編譯時錯誤。但是,在非編譯語言,例如 PHP 中,會發生什么?

    在 PHP 中的方法調用是這樣工作的。首先,PHP 解釋器在類上查找方法。如果方法存在,PHP 就調用它。如果沒有,那么就調用類上的魔法方法 __call(如果這個方法存在的話)。如果 __call 失敗,就調用父類方法,依此類推。

    魔法方法
    魔法方法是有特定名稱的方法,PHP 解釋器在腳本執行的特定點上會查找魔法方法。最常見的魔法方法就是對象創始時調用的構造函數。

    __call 方法有兩個參數:被請求的方法的名稱和方法參數。如果創建的 __call 方法接受這兩個參數,執行某項功能,然后返回 TRUE,那么調用這個對象的代碼就永遠不會知道在有代碼的方法和 __call 機制處理的方法之間的區別。通過這種方式,可以創建這樣的對象,即動態地模擬擁有無數方法的情況。

    除了 __call 方法,其他魔法方法 —— 包括 __get__set —— 調用它們的時候,都是因為引用了不存在的實例變量。腦子里有了這個概念之后,就可以開始編寫能夠適應任何表的動態數據庫訪問類了。





    回頁首


    經典的數據庫訪問

    先從一個簡單的數據庫模式開始。清單 1 所示的模式針對的是單一的數據表數據庫,容納圖書列表。


    清單 1. MySQL 數據庫模式
    														
    																DROP TABLE IF EXISTS book;
    CREATE TABLE book (
            book_id INT NOT NULL AUTO_INCREMENT,
            title TEXT,
            publisher TEXT,
            author TEXT,
            PRIMARY KEY( book_id )
    );
    
    														
    												

    請把這個模式裝入到名為 bookdb 的數據庫。

    接下來,編寫一個常規的數據庫類,然后再把它修改成動態的。清單 2 顯示了圖書表的簡單的數據庫訪問類。


    清單 2. 基本的數據庫訪問客戶機
    														
    																<?php
    require_once("DB.php");
    
    $dsn = 'mysql://root:password@localhost/bookdb';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    class Book
    {
      private $book_id;
      private $title;
      private $author;
      private $publisher;
    
      function __construct()
      {
      }
    
      function set_title( $title ) { $this->title = $title; }
      function get_title( ) { return $this->title; }
    
      function set_author( $author ) { $this->author = $author; }
      function get_author( ) { return $this->author; }
    
      function set_publisher( $publisher ) {
      $this->publisher = $publisher; }
      function get_publisher( ) { return $this->publisher; }
    
      function load( $id )
      {
        global $db;
    $res = $db->query( "SELECT * FROM book WHERE book_id=?",
        array( $id ) );
        $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
        $this->book_id = $id;
        $this->title = $row['title'];
        $this->author = $row['author'];
        $this->publisher = $row['publisher'];
      }
    
      function insert()
      {
        global $db;
        $sth = $db->prepare(
    'INSERT INTO book ( book_id, title, author, publisher )
        VALUES ( 0, ?, ?, ? )'
        );
        $db->execute( $sth,
          array( $this->title,
            $this->author,
            $this->publisher ) );
        $res = $db->query( "SELECT last_insert_id()" );
        $res->fetchInto( $row );
        return $row[0];
      }
    
      function update()
      {
        global $db;
        $sth = $db->prepare(
    'UPDATE book SET title=?, author=?, publisher=?
       WHERE book_id=?'
        );
        $db->execute( $sth,
          array( $this->title,
            $this->author,
            $this->publisher,
            $this->book_id ) );
      }
    
      function delete()
      {
        global $db;
        $sth = $db->prepare(
          'DELETE FROM book WHERE book_id=?'
        );
        $db->execute( $sth,
          array( $this->book_id ) );
      }
    
      function delete_all()
      {
        global $db;
        $sth = $db->prepare( 'DELETE FROM book' );
        $db->execute( $sth );
      }
    }
    
    $book = new Book();
    $book->delete_all();
    $book->set_title( "PHP Hacks" );
    $book->set_author( "Jack Herrington" );
    $book->set_publisher( "O'Reilly" );
    $id = $book->insert();
    echo ( "New book id = $id\n" );
    
    $book2 = new Book();
    $book2->load( $id );
    echo( "Title = ".$book2->get_title()."\n" );
    $book2->delete( );
    ?>
    
    														
    												

    為了保持代碼簡單,我把類和測試代碼放在一個文件中。文件首先得到數據庫句柄,句柄保存在一個全局變量中。然后定義 Book 類,用私有成員變量代表每個字段。還包含了一套用來從數據庫裝入、插入、更新和刪除行的方法。

    底部的測試代碼先刪除數據庫中的所有條目。然后,代碼插入一本書,輸出新記錄的 ID。然后,代碼把這本書裝入另一個對象并輸出書名。

    清單 3 顯示了在命令行上用 PHP 解釋器運行代碼的效果。


    清單 3. 在命令行運行代碼
    														
    																% php db1.php
    New book id = 25
    Title = PHP Hacks
    %
    
    														
    												

    不需要看太多,就已經得到重點了。Book 對象代表圖書數據表中的行。通過使用上面的字段和方法,可以創建新行、更新行和刪除行。





    回頁首


    初識動態

    下一步是讓類變得稍微動態一些:動態地為每個字段創建 get_set_ 方法。清單 4 顯示了更新后的代碼。


    清單 4. 動態 get_ 和 set_ 方法
    														
    																<?php
    require_once("DB.php");
    
    $dsn = 'mysql://root:password@localhost/bookdb';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    class Book
    {
      private $book_id;
      private $fields = array();
    
      function __construct()
      {
        $this->fields[ 'title' ] = null;
        $this->fields[ 'author' ] = null;
        $this->fields[ 'publisher' ] = null;
      }
    
      function __call( $method, $args )
      {
        if ( preg_match( "/set_(.*)/", $method, $found ) )
        {
          if ( array_key_exists( $found[1], $this->fields ) )
          {
            $this->fields[ $found[1] ] = $args[0];
            return true;
          }
        }
        else if ( preg_match( "/get_(.*)/", $method, $found ) )
        {
          if ( array_key_exists( $found[1], $this->fields ) )
          {
            return $this->fields[ $found[1] ];
          }
        }
        return false;
      }
    
      function load( $id )
      {
        global $db;
    $res = $db->query( "SELECT * FROM book WHERE book_id=?",
       array( $id ) );
        $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
        $this->book_id = $id;
        $this->set_title( $row['title'] );
        $this->set_author( $row['author'] );
        $this->set_publisher( $row['publisher'] );
      }
    
      function insert()
      {
        global $db;
        $sth = $db->prepare(
    'INSERT INTO book ( book_id, title, author, publisher )
       VALUES ( 0, ?, ?, ? )'
        );
        $db->execute( $sth,
          array( $this->get_title(),
            $this->get_author(),
            $this->get_publisher() ) );
        $res = $db->query( "SELECT last_insert_id()" );
        $res->fetchInto( $row );
        return $row[0];
      }
    
      function update()
      {
        global $db;
        $sth = $db->prepare(
    'UPDATE book SET title=?, author=?, publisher=?
      WHERE book_id=?'
        );
        $db->execute( $sth,
          array( $this->get_title(),
            $this->get_author(),
            $this->get_publisher(),
            $this->book_id ) );
      }
    
      function delete()
      {
        global $db;
        $sth = $db->prepare(
          'DELETE FROM book WHERE book_id=?'
        );
        $db->execute( $sth,
          array( $this->book_id ) );
      }
    
      function delete_all()
      {
        global $db;
        $sth = $db->prepare( 'DELETE FROM book' );
        $db->execute( $sth );
      }
    }
    
    ..
    
    														
    												

    要做這個變化,需要做兩件事。首先,必須把字段從單個實例變量修改成字段和值組合構成的散列表。然后必須添加一個 __call 方法,它只查看方法名稱,看方法是 set_ 還是 get_ 方法,然后在散列表中設置適當的字段。

    注意,load 方法通過調用 set_titleset_authorset_publisher方法 —— 實際上都不存在 —— 來實際使用 __call 方法。





    回頁首


    走向完全動態

    刪除 get_set_ 方法只是一個起點。要創建完全動態的數據庫對象,必須向類提供表和字段的名稱,還不能有硬編碼的引用。清單 5 顯示了這個變化。


    清單 5. 完全動態的數據庫對象類
    														
    																<?php
    require_once("DB.php");
    
    $dsn = 'mysql://root:password@localhost/bookdb';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    class DBObject
    {
      private $id = 0;
      private $table;
      private $fields = array();
    
      function __construct( $table, $fields )
      {
        $this->table = $table;
        foreach( $fields as $key )
          $this->fields[ $key ] = null;
      }
    
      function __call( $method, $args )
      {
        if ( preg_match( "/set_(.*)/", $method, $found ) )
        {
          if ( array_key_exists( $found[1], $this->fields ) )
          {
            $this->fields[ $found[1] ] = $args[0];
            return true;
          }
        }
        else if ( preg_match( "/get_(.*)/", $method, $found ) )
        {
          if ( array_key_exists( $found[1], $this->fields ) )
          {
            return $this->fields[ $found[1] ];
          }
        }
        return false;
      }
    
      function load( $id )
      {
        global $db;
        $res = $db->query(
      "SELECT * FROM ".$this->table." WHERE ".
      $this->table."_id=?",
          array( $id )
        );
        $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
        $this->id = $id;
        foreach( array_keys( $row ) as $key )
          $this->fields[ $key ] = $row[ $key ];
      }
    
      function insert()
      {
        global $db;
    
        $fields = $this->table."_id, ";
        $fields .= join( ", ", array_keys( $this->fields ) );
    
        $inspoints = array( "0" );
        foreach( array_keys( $this->fields ) as $field )
          $inspoints []= "?";
        $inspt = join( ", ", $inspoints );
    
    $sql = "INSERT INTO ".$this->table." ( $fields )
       VALUES ( $inspt )";
    
        $values = array();
        foreach( array_keys( $this->fields ) as $field )
          $values []= $this->fields[ $field ];
    
        $sth = $db->prepare( $sql );
        $db->execute( $sth, $values );
    
        $res = $db->query( "SELECT last_insert_id()" );
        $res->fetchInto( $row );
        $this->id = $row[0];
        return $row[0];
      }
    
      function update()
      {
        global $db;
    
        $sets = array();
        $values = array();
        foreach( array_keys( $this->fields ) as $field )
        {
          $sets []= $field.'=?';
          $values []= $this->fields[ $field ];
        }
        $set = join( ", ", $sets );
        $values []= $this->id;
    
    $sql = 'UPDATE '.$this->table.' SET '.$set.
      ' WHERE '.$this->table.'_id=?';
    
        $sth = $db->prepare( $sql );
        $db->execute( $sth, $values );
      }
    
      function delete()
      {
        global $db;
        $sth = $db->prepare(
       'DELETE FROM '.$this->table.' WHERE '.
       $this->table.'_id=?'
        );
        $db->execute( $sth,
          array( $this->id ) );
      }
    
      function delete_all()
      {
        global $db;
        $sth = $db->prepare( 'DELETE FROM '.$this->table );
        $db->execute( $sth );
      }
    }
    
    $book = new DBObject( 'book', array( 'author',
       'title', 'publisher' ) );
    $book->delete_all();
    $book->set_title( "PHP Hacks" );
    $book->set_author( "Jack Herrington" );
    $book->set_publisher( "O'Reilly" );
    $id = $book->insert();
    
    echo ( "New book id = $id\n" );
    
    $book->set_title( "Podcasting Hacks" );
    $book->update();
    
    $book2 = new DBObject( 'book', array( 'author',
      'title', 'publisher' ) );
    $book2->load( $id );
    echo( "Title = ".$book2->get_title()."\n" );
    $book2->delete( );
    ? >
    
    														
    												

    在這里,把類的名稱從 Book 改成 DBObject。然后,把構造函數修改成接受表的名稱和表中字段的名稱。之后,大多數變化發生在類的方法中,過去使用一些硬編碼結構化查詢語言(SQL),現在則必須用表和字段的名稱動態地創建 SQL 字符串。

    代碼的惟一假設就是只有一個主鍵字段,而且這個字段的名稱是表名加上 _id。所以,在 book 表這個示例中,有一個主鍵字段叫做 book_id。主鍵的命名標準可能不同;如果這樣,需要修改代碼以符合標準。

    這個類比最初的 Book 類復雜得多。但是,從類的客戶的角度來看,這個類用起來仍很簡單。也就是說,我認為這個類能更簡單。具體來說,我不愿意每次創建圖書的時候都要指定表和字段的名稱。如果我四處拷貝和粘貼這個代碼,然后修改了 book 表的字段結構,那么我可能就麻煩了。在清單 6 中,通過創建一個繼承自 DBObject 的簡單 Book 類,我解決了這個問題。


    清單 6. 新的 Book 類
    														
    																..
    class Book extends DBObject 
    {
      function __construct()
      {
        parent::__construct( 'book', 
          array( 'author', 'title', 'publisher' ) );
      }
    }
    
    $book = new Book( );
    $book->delete_all();
    $book->{'title'} = "PHP Hacks";
    $book->{'author'} = "Jack Herrington";
    $book->{'publisher'} = "O'Reilly";
    $id = $book->insert();
    
    echo ( "New book id = $id\n" );
    
    $book->{'title'} = "Podcasting Hacks";
    $book->update();
    
    $book2 = new Book( );
    $book2->load( $id );
    echo( "Title = ".$book2->{'title'}."\n" );
    $book2->delete( );
    ?>
    
    														
    												

    現在,Book 類真的是簡單了。而且 Book 類的客戶也不再需要知道表或字段的名稱了。





    回頁首


    改進的空間

    對這個動態類我想做的最后一個改進,是用成員變量訪問字段,而不是用笨重的 get_set_ 操作符。清單 7 顯示了如何用 __get__set 魔法方法代替 __call


    清單 7. 使用 __get 和 __set 方法
    														
    																<?php
    require_once("DB.php");
    
    $dsn = 'mysql://root:password@localhost/bookdb';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    class DBObject
    {
      private $id = 0;
      private $table;
      private $fields = array();
    
      function __construct( $table, $fields )
      {
        $this->table = $table;
        foreach( $fields as $key )
          $this->fields[ $key ] = null;
      }
    
      function __get( $key )
      {
        return $this->fields[ $key ];
      }
    
      function __set( $key, $value )
      {
        if ( array_key_exists( $key, $this->fields ) )
        {
          $this->fields[ $key ] = $value;
          return true;
        }
        return false;
      }
    
      function load( $id )
      {
        global $db;
        $res = $db->query(
      "SELECT * FROM ".$this->table." WHERE ".
       $this->table."_id=?",
          array( $id )
        );
        $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
        $this->id = $id;
        foreach( array_keys( $row ) as $key )
          $this->fields[ $key ] = $row[ $key ];
      }
    
      function insert()
      {
        global $db;
    
        $fields = $this->table."_id, ";
        $fields .= join( ", ", array_keys( $this->fields ) );
    
        $inspoints = array( "0" );
        foreach( array_keys( $this->fields ) as $field )
          $inspoints []= "?";
        $inspt = join( ", ", $inspoints );
    
    $sql = "INSERT INTO ".$this->table. 
       " ( $fields ) VALUES ( $inspt )";
    
        $values = array();
        foreach( array_keys( $this->fields ) as $field )
          $values []= $this->fields[ $field ];
    
        $sth = $db->prepare( $sql );
        $db->execute( $sth, $values );
    
        $res = $db->query( "SELECT last_insert_id()" );
        $res->fetchInto( $row );
        $this->id = $row[0];
        return $row[0];
      }
    
      function update()
      {
        global $db;
    
        $sets = array();
        $values = array();
        foreach( array_keys( $this->fields ) as $field )
        {
          $sets []= $field.'=?';
          $values []= $this->fields[ $field ];
        }
        $set = join( ", ", $sets );
        $values []= $this->id;
    
    $sql = 'UPDATE '.$this->table.' SET '.$set.
      ' WHERE '.$this->table.'_id=?';
    
        $sth = $db->prepare( $sql );
        $db->execute( $sth, $values );
      }
    
      function delete()
      {
        global $db;
        $sth = $db->prepare(
    'DELETE FROM '.$this->table.' WHERE '.
    $this->table.'_id=?'
        );
        $db->execute( $sth,
          array( $this->id ) );
      }
    
      function delete_all()
      {
        global $db;
        $sth = $db->prepare( 'DELETE FROM '.$this->table );
        $db->execute( $sth );
      }
    }
    
    class Book extends DBObject 
    {
      function __construct()
      {
      parent::__construct( 'book',
        array( 'author', 'title', 'publisher' ) );
      }
    }
    
    $book = new Book( );
    $book->delete_all();
    $book->{'title'} = "PHP Hacks";
    $book->{'author'} = "Jack Herrington";
    $book->{'publisher'} = "O'Reilly";
    $id = $book->insert();
    
    echo ( "New book id = $id\n" );
    
    $book->{'title'} = "Podcasting Hacks";
    $book->update();
    
    $book2 = new Book( );
    $book2->load( $id );
    echo( "Title = ".$book2->{'title'}."\n" );
    $book2->delete( );
    ?>
    
    														
    												

    底部的測試代碼只演示了這個語法干凈了多少。要得到圖書的書名,只需得到 title 成員變量。這個變量會調用對象的 __get 方法,在散列表中查找 title 條目并返回。

    現在就得到了單個動態的數據庫訪問類,它能夠讓自己適應到數據庫中的任何表。





    回頁首


    動態類的更多用途

    編寫動態類不僅限于數據庫訪問。請看清單 8 中的 Customer 對象這個例子。


    清單 8. 簡單的 Customer 對象
    														
    																<?php
    class Customer
    {
      private $name;
    
      function set_name( $value )
      {
        $this->name = $value;
      }
    
      function get_name()
      {
        return $this->name;
      }
    }
    
    $c1 = new Customer();
    $c1->set_name( "Jack" );
    $name = $c1->get_name();
    echo( "name = $name\n" );
    ?>
    
    														
    												

    這個對象足夠簡單。但是如果我想在每次檢索或設置客戶名稱時都記錄日志,會發生什么呢?我可以把這個對象包裝在一個動態日志對象內,這個對象看起來像 Customer 對象,但是會把 getset 操作的通知發送給日志。清單 9 顯示了這類包裝器對象。


    清單 9. 動態包裝器對象
    														
    																<?php
    class Customer
    {
      private $name;
    
      function set_name( $value )
      {
        $this->name = $value;
      }
    
      function get_name()
      {
        return $this->name;
      }
    }
    
    class Logged
    {
      private $obj;
    
      function __call( $method, $args )
      {
        echo( "$method( ".join( ",", $args )." )\n" );
    return call_user_func_array(array(&$this->obj,
       $method), $args );
      }
    
      function __construct( $obj )
      {
        $this->obj = $obj;
      }
    }
    
    $c1 = new Logged( new Customer() );
    $c1->set_name( "Jack" );
    $name = $c1->get_name();
    echo( "name = $name\n" );
    ?>
    
    														
    												

    調用日志版本的 Customer 的代碼看起來與前面相同,但是這時,對 Customer 對象的任何訪問都被記入日志。清單 10 顯示了運行這個日志版代碼時輸出的日志。


    清單 10. 運行日志版對象
    														
    																% php log2.php
    set_name( Jack )
    get_name(  )
    name = Jack
    %
    
    														
    												

    在這里,日志輸出表明用參數 Jack 調用了set_name 方法。然后,調用 get_name 方法。最后,測試代碼輸出 get_name 調用的結果。





    回頁首


    結束語

    如果這個動態對象素材對您來說理解起來有點難,我不會責備您。因為我自己也花了不少時間研究它并使用代碼才理解它并看出它的好處。

    動態對象有許多功能,但是也有相當的風險。首先,在剛開始編寫魔法方法時,類的復雜性顯著增加。這些類更難理解、調試和維護。另外,因為集成開發環境(IDE)變得越來越智能,所以在處理動態類時它們也會遇到這類問題,因為當它們在類上查找方法時會找不到方法。

    現在,并不是說應當避免編寫這類代碼。相反。我非常喜歡 PHP 的設計者這么有想法,把這些魔法方法包含在語言中,這樣我們才能編寫這類代碼。但是重要的是,既要理解優點,也要理解不足。

    當然,對于應用程序(例如數據庫訪問)來說,在這里介紹的技術 —— 與廣泛流行的 Ruby on Rails 系統上使用的技術類似 —— 能夠極大地減少用 PHP 實現數據庫應用程序所需要的時間。節約時間總不是壞事。





    回頁首


    參考資料

    學習
    posted @ 2006-04-28 16:02 崛起的程序員 閱讀(209) | 評論 (0)編輯 收藏

    年輕人買套套的經歷

      顧客“老板套子怎么賣?”

      老板“10元一個”

      顧客“我先試試行么?”

      老板“還試什么呀?便宜點9元好了。”

      顧客“暈,這也叫便宜啊?”

      老板“好啦8元可以了吧。”

      顧客“......”

      老板“不會還嫌貴吧?”

      顧客“不是貴,是讓我精盡人亡啊”

      老板“沒那么夸張吧,看你是小朋友,7元好了”

      顧客“恩,差不多啦,可是我沒那么多錢啊。”

      老板“啊?你有多少啊?”

      顧客“5元。”

      老板“天啊,暈死了,怎么也得再添1元啊!”

      顧客“我很想添,可是我的資金有限啊”

      老板“好啦,我認倒霉,5元成交”

      顧客“我不是要給你5元,我得留下2元做車”

      老板“不會吧,你不會做車來這里買這東西吧?”

      顧客“是啊我做11路來的而且還是回頭客啊”

      老板“雖然以前沒看過你,不過希望你以后再來,3元成交行了吧。”

      顧客(臉上帶紅)“可是我還沒有對象”

      老板“啊?那你買這干什么啊?”

      顧客“沒關系,如果你再便宜1元的話我就能找到了!”

      老板“¥%……¥%……%¥算你狠,2元行了吧!”

      顧客“等等,這個怎么有個洞啊?”

      老板“沒有洞怎么用啊!?”

      顧客“怎么看起來像用過的啊?”

      老板“侮辱我可以但是不要侮辱我的套子,這絕對是新的。”

      顧客“哇,上面還沒干呢啊,你騙我啊!”

      老板“啊!!不好意思嘿嘿……做生意嗎,你要知道我每天的門面房租金上千呢,不然我吃什么,1元可以了吧”

      顧客“你這種行為嚴重的危害了我的健康并且深深的影響了我的心靈.......”

      老板“啊呀!這么嚴重啊,你別生氣,我5毛賣給你行了吧。”

      顧客“好,開張發票來!”

      老板暈死!

    十二個避孕套

      爸爸和13歲的兒子走進屈臣氏,路經放避孕套的貨架。兒子問爸爸「這些一盒盒的是什

    么?爸爸告訴兒子:「這些是避孕套,是用來進行安全的性行為用的。兒子U「啊~原來這些

    便是避孕套,上性教育課老師曾提及過!........[但為什么這些要一盒入里面有三個的?

      爸爸:「嗯......這些是給大學生用的,星期五一個,星期六一個,星期日一........」

      兒子:「.......那么這些一盒六個的是誰用的?」

      爸爸:「嗯........這是研究生用的,星期五兩個,星期六兩個,星期日兩個........」

      兒子:「.......那這些呢?」

      兒子拿起了一盒十二個裝的。

      爸爸透了一下涼氣,凄凄道:「那是給已婚人仕用的,一月份一個,二月份一個,三月份一個............」


    彩色的保險套

      有一個人想嘗試新奇的事,便跑到情趣商品店買彩色的保險套他看到兩個彩色的套子,

    一個是黑色的,一個外型像是米老鼠他決定買那個黑色的回家,并跟太太大戰了幾回合不過

    那個套子并沒發生什作用,后來他太太懷孕了經過九月之后生下小baby,再經過6年之后孩子

    長大了這個小孩有一天問他老爸:“為什么哥哥姊姊的膚色都是白的而我卻是黑的?”爸爸

    回答道:“孩子,你沒長得像米老鼠就該謝天謝地了”


    IT避孕套

    有一天軟件工業一蹶不振,軟件業三大巨頭SUN,UNIX和微軟都決定改做避孕套生意,

    他們生產的避孕套分別命名為JAVA避孕套,X避孕套和MS避孕套。 一個使用JAVA避孕

    套的顧客來到SUN公司投訴,說戴著不合適,SUN公司回答說要等國際標準組織(ISO)制定相

    應的標準才行,并吹牛說那時他們生產的避孕套將適合每個男人,顧客只好轉而使用X避孕

    套。可他發現等他讀完隨套附上的說明書后,他的妻子已經睡著了,他自己也忘了為什么

    要用X避孕套。最后,他只好換用MS避孕套。出乎他意料的是,MS避孕套非常好用,他很愉

    快的連續使用了好幾個月,突然發現他妻子懷孕了。他非常生氣氣勢洶洶的找到微軟公

    司,微軟的回答是:補丁馬上就到!

    posted @ 2006-04-28 13:46 崛起的程序員 閱讀(560) | 評論 (1)編輯 收藏
    Stripes 1.3 版本發布了.Stripes是一個視圖框架用于利用最新的Java技術來構建Web應用程序.
    文章來源:http://www.matrix.org.cn/resource/news/670_Stripes.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(218) | 評論 (0)編輯 收藏
    JIRA 3.6 版本發布了.JIRA是一個優秀的問題(or bugs,task,improvement,new feature )跟蹤及管理軟件。
    文章來源:http://www.matrix.org.cn/resource/news/671_JIRA.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(214) | 評論 (0)編輯 收藏
    Apache MyFaces 1.1.2 版本發布了.MyFaces是JavaServer Faces(JSF) Web框架 (JSR 127)的一個實現。JavaServer Faces Web框架是一個新的實現MVC模式的規范.它可以與Struts框架相媲美甚至的一些特性與觀念已經超過了Struts.
    文章來源:http://www.matrix.org.cn/resource/news/672_Apache+MyFaces.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(226) | 評論 (0)編輯 收藏
    Apple 發布了 Mac OS X Tiger 的更新包.for for Mac OS X 10.4.5 Tiger 用戶.更新包增加了對Java 2 Platform Standard Edition 5.0的可靠性和兼容性.
    文章來源:http://www.matrix.org.cn/resource/news/673_Apple+Tiger+Java.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(251) | 評論 (0)編輯 收藏
    Apache FOP 0.92 beta 版本發布了.FOP是Apache計劃所發展的一個開源的XSL-FO處理器項目,可以把Formatting Object格式的文件轉換成 可列印文件,如PDF、PostScript等格式。
    文章來源:http://www.matrix.org.cn/resource/news/674_Apache+FOP.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(292) | 評論 (0)編輯 收藏
    ObjectWeb ASM 3.0 beta2 版本發布了.ASM是一套JAVA字節碼生成架構。它可以動態生成二進制格式的stub類或其他代理類,或者在類被JAVA虛擬機裝入內存之前,動態修改類。
    文章來源:http://www.matrix.org.cn/resource/news/675_ObjectWeb+ASM.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(265) | 評論 (0)編輯 收藏
    Apache WS Policy 宣布改名為 Apache Neethi.
    文章來源:http://www.matrix.org.cn/resource/news/676_Apache+Neethi.html
    posted @ 2006-04-28 11:29 崛起的程序員 閱讀(293) | 評論 (0)編輯 收藏
    僅列出標題
    共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 
    主站蜘蛛池模板: a在线视频免费观看在线视频三区| 99久久99热精品免费观看国产| 国产日产亚洲系列| 99久久免费中文字幕精品| 亚洲性无码一区二区三区| 国产精品亚洲高清一区二区| 4444www免费看| 一级成人生活片免费看| 亚洲精品美女在线观看播放| 国产成人精品免费直播| 色猫咪免费人成网站在线观看| 亚洲高清乱码午夜电影网| 亚洲国产精华液网站w| 免费看少妇作爱视频| A级毛片高清免费视频在线播放| 国产成人精品日本亚洲网址| 久久亚洲国产成人影院网站| 99久久国产热无码精品免费| 国产免费内射又粗又爽密桃视频| 亚洲国产成人久久| 久久亚洲高清观看| 免费人妻无码不卡中文字幕18禁| 久久免费看黄a级毛片| 和老外3p爽粗大免费视频| 亚洲人成欧美中文字幕| 亚洲精品综合一二三区在线| 亚洲国产成人a精品不卡在线| 成人免费视频网站www| 中文字幕免费在线看线人动作大片 | 91免费在线视频| 久久精品国产亚洲AV天海翼 | 亚洲卡一卡2卡三卡4麻豆| 亚洲无线观看国产精品| 国产一区二区视频免费| 国产日本一线在线观看免费| 黄色片免费在线观看| 成年网在线观看免费观看网址| 亚洲综合精品成人| 亚洲18在线天美| 污污的视频在线免费观看| 国产精品亚洲午夜一区二区三区|