»¶ÓÄú·ÃÎÊÎÒ°®IT¼¼ÊõÍø£¬½ñÌìС±àΪÄã·ÖÏíµÄ±à³Ì¼¼ÊõÊÇ£º¡¾¡¶PHPÉè¼ÆÄ£Ê½½éÉÜ¡·µÚÊ®ËÄÕ ¶¯Ì¬¼Ç¼ģʽ¡¿£¬ÏÂÃæÊÇÏêϸµÄ·ÖÏí£¡
¡¶PHPÉè¼ÆÄ£Ê½½éÉÜ¡·µÚÊ®ËÄÕ ¶¯Ì¬¼Ç¼ģʽ
µ½Ä¿Ç°ÎªÖ¹£¬ÄúËù¿´µ½µÄÕâЩÉè¼ÆÄ£Ê½´ó´óÌá¸ßÁË´úÂëµÄ¿É¶ÁÐÔÓë¿Éά»¤ÐÔ¡£È»¶ø£¬ÔÚWEBÓ¦ÓÃÉè¼ÆÓ뿪·¢ÖÐÒ»¸ö»ù±¾µÄÐèÇóÓëÌôÕ½£ºÊý¾Ý¿âÓ¦Óã¬ÕâЩÉè¼ÆÄ£Ê½¶¼Ã»ÓÐÉæ¼°µ½¡£±¾ÕÂÓë½ÓÏÂÀ´µÄÁ½Õ—±íÊý¾ÝÍø¹ØÓë±íÊý¾ÝÓ³É䣬ÌṩÁËÈýÖÖÉè¼ÆÄ£Ê½Ê¹ÄúÄܸüºÃµÄ×éÖ¯ÄãµÄÓ¦ÓóÌÐòÓëÊý¾Ý¿â½øÐн»»¥¡£
ÎÊÌâ
´ó¶àÊýWEBÓ¦Óý«ÐÅÏ¢³ÖÐø±£´æÔÚÊý¾Ý¿âÖС£Óн«Êý¾Ý¿â²Ù×÷³éÏ󻯣¬ÒÔ´ïµ½¼ò»¯±íÊý¾Ý´æÈ¡ºÍ¶ÔÒµÎñÂß¼µÄ¼¯³É´æÈ¡·½·¨Âð£¿
½â¾ö·½°¸
ÀíÂÛÉÏ£¬¶¯Ì¬¼Ç¼ģʽÊÇ×î¼ò»¯µÄÓйØÊý¾Ý¿âµÄÉè¼ÆÄ£Ê½¡£¶¯Ì¬¼Ç¼ģʽ°üº¬ÁËÈçºÎÔÚÀàÖÐÖ±½ÓʵÏÖÓëÊý¾Ý¿â½»»¥µÄÏà¹ØÖªÊ¶¡£
¶¯Ì¬¼Ç¼ģʽÔÚ³ÌÐò´úÂëÓëÊý¾Ý¿â½á¹¹Ö®¼ä²úÉúÁËÒ»ÖֺܸߵĽáºÏ¶È£¬ÔÚһЩÏà¶Ô¼òµ¥µÄÓ¦Óû·¾³ÖУ¬¾ÍÄܱȲÉÓñðµÄ¸´ÔÓ·½°¸¸üÈÝÒ×½â¾öÕâÖÖÒò½áºÏËù²úÉúµÄһЩ¹ÌÓÐÎÊÌâ¡£¶¯Ì¬¼Ç¼ģʽҲÄÜÂú×ãÐí¶à³õ¼¶µÄÊý¾Ý¿âÏîÄ¿¡£Ö»Óе±¸´ÔÓÐÔÔö¼Ó¶øÄÑÒÔÓö¯Ì¬¼Ç¼ģʽ´¦Àíʱ£¬Äã²ÅÓбØÒªÊ¹ÓñíÊý¾ÝÍø¹ØÄ£Ê½£¨²Î¼û15Õ£©£¬»òÊÇÊý¾ÝµØÍ¼Ä£Ê½£¨²Î¼û16Õ£©»òÊDZðµÄÊý¾Ý¿âÉè¼ÆÄ£Ê½
ÆóÒµ¼¶Ó¦Óüܹ¹Ä£Ê½
¸ù¾ÝMartin Fowler’sµÄÖø×÷¡¶ÆóÒµ¼¶Ó¦Óüܹ¹Ä£Ê½¡·£¬ËùνÆóÒµ¼¶Ó¦ÓþÍÊÇÓë±ðµÄÓ¦Óü¯³É»¯£¬°üº¬ÁËÖØÒªµÄÒµÎñÂß¼£¨»òÈçÓ¦ÓÃÐèÇóËù³ÊÏֵķÇÂß¼µÄ¶«Î÷£©£¬²¢ÇÒ¾ßÓÐÐí¶à²¢·¢´æÈ¡ºÍ±£´æ´Ó¸÷ÖÖ½Ó¿ÚÈ¡µÃµÄÊý¾Ý¡£ÓÐȤµÄÊÇ£¬webÓ¦ÓÃÕýºÃ¾ß±¸ÁËÉÏÊö¶à¸öÌØµã£¬ÕâÕýºÃÄܽâÊÍΪʲôMartin Fowler’sµÄÖø×÷ÄÜÒýÆðPHP³ÌÐòÔ±µÄÇ¿ÁÒ·´Ïì¡£
PHPÊý¾Ý¶ÔÏó
PDOÊÇÒ»¸ö¸ßÐÔÄܵÄÊý¾Ý¿âͨµÀ½Ó¿Ú£¨²¢·ÇÊý¾Ý¿â³éÏ󣩡£PDOÊÇÒ»¸öÓÉCÓïÑÔ¹¹³ÉµÄ±¾µØÇý¶¯°ü£¬Òò´ËÆäËÙ¶ÈÊǺܿìµÄ¡£PDOΪËùÓеÄPDOÇý¶¯ÌṩÁËÉêÃ÷£¬ÔöÇ¿Á˽ű¾Ê¹ÓÿâʱµÄ°²È«ÐÔ¡£
Ñù±¾´úÂë
ÈκζÔÊý¾Ý¿âÁ¬½ÓµÄÌÖÂÛ¶¼ÒÀÀµÓÚ¶ÔÊý¾Ý¿âϵͳÓë¶ÔÊý¾Ý¿â·ÃÎʲãµÄÑ¡Ôñ¡£±¾ÕÂÓëËæºóÁ½Õ¶¼Ê¹ÓÃMYSQL(http://www.mysql.com/)Õâ¸öÁ÷ÐеĿªÔ´Êý¾Ý¿â¼°ADOdb (http://adodb.sf.net/)×÷ΪÊý¾Ý¿â·ÃÎʲ㡣ÎÒ½«ADOdb×÷ΪÎÒ×Ô¼º¹¤×÷Êҵıê×¼ÊÇÒòΪËüÓÅÒìµÄÐÔÄÜ£¬ÇÒ³éÏóÁËOracle OCI½Ó¿Ú£¬²¢ÌṩÁËͳһµÄ·ÃÎÊPostgreSQL, Sybase, MySQLºÍÆäËüÊý¾Ý¿âµÄ½Ó¿Ú£¬¶ø³ÉΪÁËÒ×ÓÚʹÓõÄPHP API£¬ÈÃÄãרעÓÚ³ÌÐòÓëÒµÎñÂß¼µÄ´¦Àí¡£
·ÅÐĵÄÌæ»»ÄãµÄ×Ô¼ºµÄÊý¾Ý¿âÓë·ÃÎʲ㣬ÒòΪÕâÀïÌá³öµÄÐí¶à¸ÅÄîÒ²ÊʺÏÓÚ±ðµÄ½â¾ö·½°¸¡£
ÔÚÑо¿t¶¯Ì¬¼Ç¼ģʽ֮ǰ£¬ÈÃÎÒÃÇ´Ó»ù±¾µÄÊý¾Ý¿âÁ¬½Ó¿ªÊ¼¡£ÓÐÒ»¸ö¼¯Öе쬼òµ¥µÄ·½Ê½È¥Ö¸¶¨Á¬½Ó²ÎÊý£¨Ö÷»úÃû£¬Óû§Ãû£¬ÃÜÂ룬Êý¾Ý¿â£©²¢½¨Á¢Ò»¸öÊý¾Ý¿âÁ¬½Ó¶ÔÏóÊǺÜÀíÏëµÄ¡£Ò»¸öµ¥Ò»Ä£Ê½¶ÔÏ󣨲μûµÚËÄÕ£©¾Í·Ç³£ÊʺÏÁË¡£
ÕâÊÇÒ»¸öDBÀ࣬Æäconn()·½·¨·µ»ØÒ»¸öµ¥Ò»Ä£Ê½µÄADOConnectionÀàµÄʵÀý¡£
| // PHP5 require_once ‘adodb/adodb.inc.php’; class DB { //static class, we do not need a constructor private function __construct() {} public static function conn() { static $conn; if (!$conn) { $conn = adoNewConnection(‘mysql’); $conn->connect(‘localhost’, ‘username’, ‘passwd’, ‘database’); $conn->setFetchMode(ADODB_FETCH_ASSOC); } return $conn; } } |
DBÀàÔÊÐíÄãÉ趨Êý¾Ý¿âµÄÀàÐÍÓëÁ¬½Ó²ÎÊý¡£µÚÒ»ÐдúÂ뽫ADOdb¿â°üº¬½øÀ´£¨Äã¿ÉÄÜÐèÒª¸ù¾ÝÄãµÄʵ¼Ê»·¾³À´µ÷Õû·¾¶£©;ÒòΪûÓбØÒªÃ¿´Î¶¼ÊµÀý»¯DB,ËùÒÔDBµÄ¹¹Ô캯ÊýÊÇ˽ÓеÄ; ÐÐ$conn->setFetchMode(ADODB_FETCH_ASSOC)É趨¶ÔÏ󷵻صļǼ¼¯ÊÇÒÔ£¨×Ö¶ÎÃû=>Öµ£©ÐÎʽµÄ¹ØÁªÊý×é¡£ÓëÊý¾Ý¿â´ò½»µÀÖвÉÓùØÁªÊý×éÊǷdz£ÖØÒªµÄ¾Ñéϰ¹ß£¬ÕâÑùÄúµÄ´úÂë¾Í²»»áÊܵ½ÒòSQLÓï¾äÖÐ×Ö¶ÎÅÅÐò¶ø²úÉúµÄÓ°Ïì¡£
×÷ΪʾÀý³ÌÐò£¬ÈÃÎÒÃǽ¨Á¢Ò»¸öActive Record¶ÔÏóÀ´Î¬»¤Ò»¸ö³¬Á´½Ó±í¡£ÒÔÏÂÊÇÒ»¸öÔÚMySQLÊý¾Ý¿âÖн¨Á¢Õâ¸ö³¬Á´½Ó±íµÄSQL¡£
| define(‘BOOKMARK_TABLE_DDL’, <<<EOS CREATE TABLE `bookmark` ( `id` INT NOT NULL AUTO_INCREMENT , `url` VARCHAR( 255 ) NOT NULL , `name` VARCHAR( 255 ) NOT NULL , `description` MEDIUMTEXT, `tag` VARCHAR( 50 ) , `created` DATETIME NOT NULL , `updated` DATETIME NOT NULL , PRIMARY KEY ( `id` ) ) EOS ); |
ʵÑéµÄ¶ÀÁ¢ÐÔ
¸÷¸öʵÑé¼äÓ¦ÊÇÏ໥¶ÀÁ¢µÄ;·ñÔò£¬½ö½öÊÇÔËÐÐÁËijһ¸öʵÑé¾Í»áÓ°Ïìµ½ºóÐøÊµÑéµÄ½á¹û¡£
ΪÁ˱ÜÃâÕâЩ¶¼»ùÓÚͬһÊý¾Ý¿âµÄʵÑé¼äÏ໥¸ÉÈÅ£¬×îºÃÊÇÔÚÿ¸ö²âÊÔ¿ªÊ¼Ç°É¾³ý²¢Öؽ¨Ïà¹Ø±í¡£ÒÔϼòµ¥µÄʵÑéΪºóÐøÊµÑéÌṩÁËÒ»ÖÖ±ê×¼µÄsetup·½·¨¡£
ÒÔÏ´úÂëÑÝʾÈçºÎÔÚÿ¸öʵÑé¿ªÊ¼Ç°ÖØÖÃÄãµÄÊý¾Ý¿â£º
| class ActiveRecordTestCase extends UnitTestCase { protected $conn; function __construct($name=’’) { $this->UnitTestCase($name); $this->conn = DB::conn(); } function setup() { $this->conn->execute(‘drop table bookmark’); $this->conn->execute(BOOKMARK_TABLE_DDL); } } |
Õâ¶Î´úÂëÓÃÒ»¸ö±ê×¼µÄADOConnection¶ÔÏóÀ´¸ø$connµÄÊôÐÔ¸³Öµ£¬²¢ÇÒʹÓÃÁËConnectionµÄexecute()·½·¨À´Ö´ÐÐSQLɾ³ýÓëÖØ½¨±íµÄ²Ù×÷¡£ÒòΪÕâЩ´úÂëÔÚÒ»¸öÃûΪsetup()µÄ·½·¨ÖУ¬Ê¹µÃÿһ¸öʵÑé¶¼ÄÜÔÚÒ»¸öеÄÊý¾Ý¿â»·¾³Öй¤×÷¡£
¸ü½øÒ»²½£¬ÄãÓ¦×öһЩ¶Ôsetup()·½·¨µÄ½ÏÎªÈ«ÃæµÄ²âÊÔ£¨²¢¶àѧϰһЩ¹ØÓÚADOConnection APIµÄʵÀý£©
| class ActiveRecordTestCase extends UnitTestCase { // ... function testSetupLeavesTableEmptyWithCorrectStructure() { $rs = $this->conn->execute(‘select * from bookmark’); $this->assertIsA($rs, ‘ADORecordSet’); $this->assertEqual(0,$rs->recordCount()); foreach(array( ‘id’, ‘url’, ‘name’, ‘description’, ‘tag’, ‘created’, ‘updated’) as $i => $name) { $this->assertEqual($name, $rs->fetchField($i)->name); } } } |
¼´Ê¹Ä㲻̫ÊìϤADOdb£¬ÄãÒ²ÄÜÕýÈ·µÄÈÏʶµ½execute()·½·¨Ôڳɹ¦Ö´Ðк󽫷µ»ØÒ»¸öADORecordSet ¶ÔÏó£¬Õâ¸ö¶ÔÏóÓÐÒ»¸örecordCount()·½·¨£¬Õâ¸ö·½·¨¿ÉÒÔÑéÖ¤±íÊÇ·ñΪ¿Õ¡£¼Ç¼¼¯¶ÔÏó»¹ÓÐһЩ·½·¨È¥ä¯ÀÀ¼Ç¼¼¯ÔªÊý¾ÝºÍfetchField()·½·¨À´Ð§Ñé±í½á¹¹¡£
¼Ç¼½¨Á¢
ÔÚÁ¬½Óµ½Êý¾Ý¿âºó£¬ÄúµÄ“´´½¨£¬¶ÁÈ¡£¬¸üУ¬É¾³ý”£¨CRUD£©³ÌÐò¾ÍÄÜÔÚÊý¾Ý¿âÖнøÐÐÏà¹ØµÄÐвÙ×÷¡£
CRUD
CRUD ÊÇ´´½¨£¬¶ÁÈ¡£¬¸üУ¬É¾³ýµÄËõд. ÕâЩ¶¼ÊÇÊý¾Ý¿â½»»¥Ê½Ó¦ÓÃϵͳµÄ»ù´¡
Ðí¶àPHP WEBʹÓö¼ÊÇCRUD½çÃæÓ¦ÓõÄʾÀý
(http://c2.com/cgi/wiki?CrudScreen).
ÏÂÃæµÄʾÀýÓ¦ÓÃÊǽ«Ò»Ð©ÊéÇ©´æÈëÊý¾Ý¿â£¬Òò´ËÎÒÃǽ«Õâ¸ö¶¯Ì¬¼Ç¼ÀàÃüÃûΪBookmark¡£Òª½¨Á¢Ò»¸öеÄÊéÇ©£¬¿ÉʹÓÃnew·½·¨½¨Á¢Ò»¸ö¸ÃÀàµÄʵÀý£¬²¢É趨ʵÀýµÄÏà¹ØÊôÐÔ¡£µ±ËùÓеÄÊôÐÔ¶¼ÒÑÉ趨£¨Ç¿ÖÆÐÔ£©£¬ÎÒÃÇʹÓÃsave()·½·¨½«Æä´æÈëµ½Êý¾Ý¿âÖС£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testNew() { $link = new Bookmark; $link->url = ‘http://simpletest.org/’; $link->name = ‘SimpleTest’; $link->description = ‘SimpleTest project homepage’; $link->tag = ‘testing’; $link->save(); $this->assertEqual(1, $link->getId()); } } |
´ÓÕâ¸öʵÑéÖÐÎÒÃÇ¿´µ½£¬BookmarkÀàÓÐһЩ¹«¹²µÄÊôÐÔÓëÒ»¸ösave()·½·¨¡£µ±ÊµÀý±»±£´æµ½Êý¾Ý¿âºó£¬getid()·½·¨¿ÉÒÔ·µ»ØÖ¸¶¨¸øËüµÄÊý¾Ý¿â¼Ç¼ºÅ£¨ID£©¡£
ÏÂÃæÊÇBookmarkÀàµÄÊôÐÔ¶¨Òå
| class Bookmark { public $url; public $name; public $description; public $tag; } |
ÈÃÎÒÃÇתÏòÑо¿save()·½·¨¡£ËüÐèÒªÒ»¸öÊý¾Ý¿âÁ¬½Ó£¬Òò´ËÎÒÃÇÔÚ¹¹Ô캯ÊýÖÐÓÃDB::conn()Á¬½Ó¹¤³§ÊµÏÖ¡£
| class Bookmark { protected $id; protected $conn; // ... public function __construct() { $this->conn = DB::conn(); } } |
$conn ÏÖÔھͳÉΪÊʺÏsave()·½·¨µÄÊý¾Ý¿âÁ¬½ÓÁË¡£
| class Bookmark { // ... const INSERT_SQL = “ insert into bookmark (url, name, description, tag, created, updated) values (?, ?, ?, ?, now(), now()) “; protected function save() { $rs = $this->conn->execute( self::INSERT_SQL ,array($this->url, $this->name, $this->description, $this->tag)); if ($rs) { $this->id = (int)$this->conn->Insert_ID(); } else { trigger_error(‘DB Error: ‘.$this->conn->errorMsg()); } } } |
ADOdb µÄ MySQL Çý¶¯Ö§³Ö°´Î»ÖõIJÎÊýÌæ»»¹¦ÄÜ£¬²¢ÇÒÄÜÕýÈ·µÄÒýÓ㨰´ÀàÐͼÓÒýºÅ£©²ÎÊý¡£SQLµÄÐβÎÒÔÎʺÅ(?)µÄÐÎʽָ¶¨£¬Äã¿ÉÒÔÔÚexecute()·½·¨µÄµÚ¶þ¸ö²ÎÊýµÄλÖã¬ÒÔÊý×éµÄÐÎʽ´«µÝʵ²ÎÖµµ½SQLÓï¾äÖÐÀ´Ìæ»»ÒÔÎʺŵãλµÄÐβΡ£
Insert_ID()·½·¨¿ÉÄÜÒÑÒýÆðÄãµÄ×¢Ò⣺Ëü·µ»Ø×îºóÒ»´ÎÖ´ÐвåÈë²Ù×÷ʱ×ÔÔö³¤ÁеÄÖµ¡£
µ½Ä¿Ç°ÎªÖ¹£¬ÕâЩʵÑéÒÑÖ¤Ã÷ÁËÒÔÏÂÊÂʵ£ºÊôÐÔ¿ÉÒÔ±»ÉèÖã¬save()ÄÜÕý³£¹¤×÷£¬$IDÊôÐÔÒѱ»ÖÃΪ1¡£ÈÃÎÒÃǽøÒ»²½µÄÉîÈëµ½Êý¾Ý±íÈ¥ÑéÖ¤ÆäËüµÄÊôÐÔÖµÒ²±»ÕýÈ·µÄ±£´æ¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testNew() { $link = new Bookmark; $link->url = ‘http://simpletest.org/’; $link->name = ‘SimpleTest’; $link->description = ‘SimpleTest project homepage’; $link->tag = ‘testing’; $link->save(); $this->assertEqual(1, $link->getId()); // fetch the table as an array of hashes $rs = $this->conn->getAll(‘select * from bookmark’); $this->assertEqual(1, count($rs), ‘returned 1 row’); foreach(array(‘url’, ‘name’, ‘description’, ‘tag’) as $key) { $this->assertEqual($link->$key, $rs[0][$key]); } } } |
ÒÔÉÏÍ»³öÏÔʾ´úÂëµÄ¹¦ÄÜÊÇ»ñÈ¡Õû¸öÊéÇ©±íÊý¾Ý¡£GetAll()·½·¨Ö´Ðвéѯ²¢·µ»Ø½á¹û¼¯£¬¸Ã½á¹û¼¯ÊÇÒÔÊý×éÐÎʽ´æ·ÅµÄ¼Ç¼µÄ¹þÏ¡±í¡£AssertEqual()·½·¨ÑéÖ¤Ö»ÓÐÒ»Ìõ¼Ç¼´æÔÚÓÚ½á¹û¼¯ÖС£Í¨¹ýforeachÑ»·±È½Ï´ÓÊý¾Ý±íÖÐÈ¡µÃ¼Ç¼µÄ×Ö¶ÎÓë$link¶ÔÏóµÄÊôÐÔÖµÊÇ·ñÒ»Ö¡£
ÉÏÊö´úÂëÒÑÄÜÕý³£¹¤×÷£¬µ«Í¨¹ýÊÖ¹¤µÄ·½·¨É趨ÊôÐÔֵȥÔö¼ÓÊéÇ©±íÊý¾ÝµÄ·½·¨»¹ÊÇÂÔÏÔ·±Ëö¡£Òò´Ë£¬ÎªÉÏÊöµÄ°¸ÀýÔö¼ÓÒ»¸ö·½±ã£¨Í¨Ó㩵ķ½·¨£¬À´ÊµÏÖÔö¼ÓµÄн¨ÊéÇ©¶ÔÏó¡£
The ActiveRecordTestCase::add()·½·¨´øÓУ¨´¦Àí£©Ëĸö²ÎÊý£¬¿É½¨Á¢Óë²åÈëÒ»¸öеÄActiveRecordÊéÇ©¶ÔÏó¡£Èç¹ûÄãÔÚºóÐøÊµÑéÖÐÒªÓõ½Ð´´½¨µÄÊéÇ©¶ÔÏó£¬add()·½·¨»¹¿ÉÒÔÔÚ´´½¨³É¹¦ºó·µ»ØËü¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function add($url, $name, $description, $tag) { $link = new Bookmark; $link->url = $url; $link->name = $name; $link->description = $description; $link->tag = $tag; $link->save(); return $link; } } |
ÄãÍêÈ«¿ÉÒÔÔÚ±¾ÊµÑé°¸ÀýÖÐдһ¸ö²âÊÔ·½·¨À´Ö¤Ã÷Æä¿ÉÓÃÐÔ¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testAdd() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $rs = $this->conn->execute(‘select * from bookmark’); $this->assertEqual(2,$rs->recordCount()); $this->assertEqual(2,$this->conn->Insert_ID()); } } |
¼ÈÈ»ÊéÇ©¿ÉÒÔ´´½¨²¢´æ´¢ÓÚÊý¾Ý¿âÖУ¬ÈÃÎÒÃǸøActive RecordÊéÇ©¶ÔÏóÔö¼ÓÒ»¸ö·½·¨£¬¿ÉÒÔ¼òµ¥µÄ´ÓÊý¾Ý¿âÖлñÈ¡Êý¾Ý²¢ÔÚʵÀýµÄÊôÐÔÖб£´æËù»ñÈ¡µÄÖµ¡£Ò»ÖÖͨÓõĽ¨Á¢¶¯Ì¬¼Ç¼¶ÔÏóµÄ¼¼ÊõÊÇͨ¹ý´«µÝÒ»¸ö±êʾ·û£¬ÈçÊéÇ©ºÅ£¨»òÊDZðµÄʲô±ê×¼£©µ½ËüµÄ¹¹Ô캯ÊýÖУ¬²¢ÇÒ´ÓÊý¾Ý¿âÖÐÈ¡³öÓëÕâ¸öIDÏà¹ØÁªµÄÐÐÊý¾Ý¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testCreateById() { $link = $this->add( ‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $this->assertEqual(1, $link->getId()); $link2 = new Bookmark(1); $this->assertIsA($link2, ‘Bookmark’); $this->assertEqual($link, $link2); } } |
Õâ¸öʵÑé´«µÝÁËÒ»¸öIDµ½¹¹Ô캯Êý£¬ÕâÊÇÇ°ÃæµÄʵÑéËùûÓгöÏÖ¹ýµÄ¡£ÊÇ·ñ´«µÝIDÊÇ¿ÉÑ¡µÄ£¬Èç¹ûûÓд«µÝID£¬ÔòǰÊöÊÔÑéÖн¨Á¢ÐµĿÕÊéǩʵÀýµÄ¹¦Äܽ«ÒÀÈ»Õý³£¹¤×÷¡£
Õâ¶ùÊÇһЩʵÏÖÉÏÊö¹¦ÄÜÒªÇóµÄ´úÂë¡£
| class Bookmark { // ... const SELECT_BY_ID = ‘select * from bookmark where id = ?’; public function __construct($id=false) { $this->conn DB::conn(); if ($id) { $rs = $this->conn->execute( self::SELECT_BY_ID ,array((int)$id)); if ($rs) { $row = $rs->fetchRow(); foreach($row as $field => $value) { $this->$field = $value; } } else { trigger_error(‘DB Error: ‘.$this->conn->errorMsg()); } } } // ... } |
¹¹Ô캯ÊýÔÊÐíÒ»¸öÃûΪ$idµÄ²ÎÊý£¬ËüµÄĬÈÏΪ¼Ù¡£Èç¹û´«À´µÄ²ÎÊý²»Îª¼Ù£¬ÔòBOOKmarkÔòÓôËIDΪ¹Ø¼ü×Ö²éѯÊý¾Ý¿âÖÐBOOKmark±íµÄÏà¹ØÐУ¬Èç¹û¸ÃÐдæÔÚ£¬ÔòÓûñÈ¡µÄÊý¾ÝÀ´É趨¶ÔÏóÊôÐÔµÄÖµ¡£
Êý¾Ý´íÎó²âÊÔ
| Mock::generate(‘ADOConnection’); class ActiveRecordTestCase extends UnitTestCase { //... function testDbFailure() { $conn = new MockADOConnection($this); $conn->expectOnce(‘execute’, array(‘*’,’*’)); $conn->setReturnValue(‘execute’,false); $conn->expectOnce(‘errorMsg’); $conn->setReturnValue(‘errorMsg’, ‘The database has exploded!!!!’); } } |
Õâ¶Î´úÂëµ÷ÓÃÁËMock::generate()¡¡À´Éú³ÉÒ»¸öMockADOConnection¡¡À࣬²¢Éú³ÉÒ»¸öÄ£ÄâÁ¬½ÓµÄʵÀý£¬Í¬Ê±É趨һЩ»ù±¾µÄ·µ»ØÖµÀ´Ö¸Ã÷´íÎ󣬺Ͷ¨ÒåÔÚÕâЩ»·¾³ÖпÉÄÜ»á³öÏÖµÄÒâÍâ¡£
È»¶ø£¬ÒòΪÊéÇ©ÀàµÄ¹¹Ô캯Êýµ÷ÓÃÁ˾²Ì¬·½·¨DB:conn()À´»ñÈ¡Êý¾Ý¿âÁ¬½Ó£¬Òª×¢ÈëÄ£ÄâÁ¬½Óµ½ÆäÖоͺÜÀ§ÄÑÁË¡£Õâ¶ùÓÐһЩ¿ÉÄܵÄʵÏÖ·½·¨£ºÔö¼ÓÒ»¸ö·½·¨À´¸Ä±ä$this->conn£¬Ôö¼ÓÒ»¸ö¿ÉÑ¡²ÎÊýµ½Ã¿Ò»¸ö·½·¨ÖУ¬»òÊÇÔö¼ÓÒ»¸ö²ÎÊýµ½¹¹Ô캯ÊýÖС£ÈÃÎÒÃÇÑ¡ÓÃ×îºóÒ»ÖÖ·½·¨£º¸øBookmarkµÄ¹¹Ô캯ÊýÔö¼ÓÒ»¸ö¿ÉÑ¡µÄ²ÎÊý¡£
| class Bookmark { // ... public function __construct($id=false, $conn=false) { $this->conn = ($conn) ? $conn : DB::conn(); // ... } } |
ÏÖÔÚ£¬ÐµÄBookmarkÒÀÈ»ÄÜÕý³£¹¤×÷£¬µ«ÐµÄBookmark(1, $connection)ÓòÎÊýÖеÄ$connection¶ÔÏó´úÌæÕý³£µÄADOConnection¶ÔÏó¡£
µ±Õâ¶Î´úÂëÍê³Éºó£¬Äã¾ÍÄÜ·½±ãµÄ½«Õý³£µÄÊý¾Ý¿âÁ¬½Ó¶ÔÏóÓÃÄ£ÄâµÄÁ¬½Ó¶ÔÏó½øÐÐÌæ»»£¬²¢ÇÒÄܽøÐÐÊý¾Ý¿â´íÎóµÄ¼ì²â¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testDbFailure() { $conn = new MockADOConnection($this); $conn->expectOnce(‘execute’, array(‘*’,’*’)); $conn->setReturnValue(‘execute’,false); $conn->expectOnce(‘errorMsg’); $conn->setReturnValue(‘errorMsg’, ‘The database has exploded!!!!’); $link = new Bookmark(1,$conn); $this->assertErrorPattern(‘/exploded/i’); $conn->tally(); } |
¶¯Ì¬¼Ç¼ʵÀýID
ÔÚÇ°ÃæµÄÀý×ÓÖУ¬´ó¶àÊýÊôÐÔ¶¼Êǹ«¹²µÄ£¬È»¶ø£¬ÊéÇ©IDÊÇÊܱ£»¤µÄ£¬ÒÔÆäÖµ±»ÃâÒâÍâ¸ü¸Ä£¨Èç¹ûÆäÖµ±»ÒâÍâ¸ü¸Ä£¬µ±ÄãÏë¸üÐÂÊéÇ©Êý¾ÝµÄʱºòÎÊÌâ¾Í³öÏÖÁË£©¡£ÒòΪ$IDÊÇÊܱ£»¤µÄ£¬Òò´ËÔö¼ÓÒ»¸ö¸¨Öú·½·¨À´»ñÈ¡ÆäÖµ¡£
| class Bookmark { protected $id; //... public function getId() { return $this->id; } } |
ÔõÑùÀ´²âÊÔËüÄØ£¿
| class ActiveRecordTestCase extends UnitTestCase { // ... function testGetId() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); // second bookmark, id=2 $link = $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $this->assertEqual(2, $link->getId()); } } |
ÈçÉÏ£¬add()·½·¨Éú²¢³É±£´æÊý¾Ý£¬²¢Í¨¹ýgetid()·½·¨»ñÈ¡Éú³ÉÊý¾ÝµÄIDÖµ²¢ÑéÖ¤ÆäÊÇÏàÆ¥ÅäµÄ¡£
µ«ÊÇ£¬Èç¹ûÄãÏëÓñðµÄÌõ¼þÀ´ÑéÖ¤ËùÉú³ÉµÄÊý¾Ý¶ø²»½ö½öÊÇÓÃÊéÇ©µÄID£¬»òÊÇÄãÈçºÎÈ·±£´ÓÊý¾Ý¿âÖзµ»ØµÄIDÊÇÕýÈ·µÄ£¿ÓÃselectÓï¾ä¸ù¾Ý¸ø¶¨µÄÊôÐÔÌõ¼þÈ¡µÃÊý¾Ý£¬²¢ÑéÖ¤·µ»ØÐеÄIDÖµÊÇÒ»¸öºÃµÄ¼¼Êõ·½·¨¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testGetId() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); // second bookmark, id=2 $link = $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $this->assertEqual(2, $link->getId()); $alt_test = $this->conn->getOne( “select id from bookmark where url = ‘http://phparch.com’”); $this->assertEqual(2, $alt_test); //alternatively $this->assertEqual($link->getId(), $alt_test); } } |
×¢Òâµ½Õâ¸öÊÔÑéÀàËÆÓÚÄãÓÃÊÖ¹¤Ö´ÐÐÒ»¸öSQL²éѯÀ´ÑéÖ¤Êý¾ÝÊÇ·ñÕýÈ·²åÈëµ½ÊéÇ©±íÖС£Í¨¹ý±¾´ÎʵÑéËùʵÏÖ´úÂ룬»¹ÄÜÓÃÓÚÄãºóÐøÊµÑéÖÐÀ´ÑéÖ¤Êý¾ÝµÄÕýÈ·ÐÔ£¬¶ø²»Êǽö½ö¼òµ¥µÄÈ¥Ö´ÐÐËü¡£
¼Ç¼ËÑË÷
ÏÖÔÚ£¬ÎÒÃÇÒÑÄÜʵÏÖ±£´æÊéÇ©¶ÔÏóµ½Êý¾Ý¿â£¬²¢ÇÒÄܸù¾ÝÊéÇ©ID´ÓÊý¾Ý¿âÖлñÈ¡ÏàÓ¦Êý¾ÝÀ´Öؽ¨ÊéÇ©¶ÔÏó¡£µ«Êǵ±IDÖµ²¢²»ÖªµÀ£¨Í¨³£Çé¿öÒ²ÊÇÕâÑù£©Ê±»á·¢Éúʲô£¿»òÊÇÄãÏëͨ¹ýÈ粿·ÖÃû³Æ»òÊÇURLµÈÏà¹ØÖµÀ´ËÑË÷Êý¾Ý¿â£¬Ôò¸ü³£¼ûµÄ½â¾ö·½·¨ÊÇÔö¼ÓÒ»¸ö”finder”·½·¨¡£
ÀýÈ磬ÄãÒ²ÐíÏëʹÓÃfindByUrl()·½·¨²éÕÒÓë¸ø¶¨²ÎÊýÏàÀàËÆµÄÊéÇ©£¬ÏÂÃæµÄʵÑéÔòÄÜʵÏÖÉÏÊöµÄÒªÇó¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testFindByUrl() { $this->add(‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $result = Bookmark::findByUrl(‘php’); $this->assertIsA($result, ‘array’); $this->assertEqual(2, count($result)); $this->assertEqual(2, $result[0]->getId()); $this->assertEqual(‘php|architect’, $result[1]->name); } } |
¸ÃʵÑéÉú³ÉһЩÊý¾Ý£¬²éÕÒURLÖаüº¬ÓГPHP”×ÖÑùµÄÐУ¬²¢Ð£¼ì·µ»ØµÄÊéÇ©¶ÔÏóÊý×éÖеÄ×Ö·û¡£FindByUrl()Ö®ËùÒÔÊÇÒ»¸ö¾²Ì¬·½·¨£¬ÊÇÒòΪÄãÓпÉÄÜÔÚûµÄÊéÇ©¶ÔÏóʵÀý»¯µÄÇé¿öϽøÐиòÙ×÷¡££¨µ±È»ÄãÒ²Äܽ«“²éÕÒ“·½·¨·Åµ½Ã¿Ò»¸ö¶ÔÏóÖУ¬µ«Ä¿Ç° “²éÕÒ”·½·¨ÈÔÈ»ÊÇÊéÇ©ÀàÖеÄÒ»¸ö·½·¨¡££©
ÒÔÏ´úÂëʵÏÖÉÏÊöʵÑéµÄÒªÇó¡£
|
class Bookmark { |
CRUD²Ù×÷ÖеĽ¨Á¢Óë¶ÁÈ¡²¿·Ö½éÉÜÍê±Ï¡£ºÎÈç¸üÐÂÊý¾ÝÄØ£¿µ±È»ÓÃsave()·½·¨À´¸üÐÂactivate record¶ÔÏóÊǺÏÀíµÄ£¬µ«Ä¿Ç°save()·½·¨Ö»ÄÜÍê³É²åÈëÊý¾Ý£¬Æä´úÂëÈçÏÂ
|
class Bookmark{ |
| class Bookmark { // ... const UPDATE_SQL = “ update bookmark set url = ?, name = ?, description = ?, tag = ?, updated = now() where id = ? “; public function save() { $this->conn->execute( self::UPDATE_SQL ,array( $this->url, $this->name, $this->description, $this->tag, $this->id)); } } |
񻂿±ðINSERTÓëUPDATE£¬ÄãÓ¦¸Ã²âÊÔÊéÇ©Êý¾ÝÊÇн¨µÄ»¹ÊÇ´ÓÊý¾Ý¿âÖлñÈ¡µÃµÄ¡£
Ê×ÏÈ£¬ÖØÐÂÖÆ×÷Á½¸ö°æ±¾µÄsave()·½·¨£¬·Ö±ðÃüÁîΪinsert()Óëupdate()¡£
|
class Bookmark { |
| class Bookmark { const NEW_BOOKMARK = -1; protected $id = Bookmark::NEW_BOOKMARK; // ... public function save() { if ($this->id == Bookmark::NEW_BOOKMARK) { $this->insert(); } else { $this->update(); } } } |
×îºóÒ»¸öÎÊÌ⣺µ±Äã²åÈë»òÊǸüмǼʱ£¬Ê±¼ä´Á×ÜÊÇÒª¸Ä±äµÄ¡£Èç¹û²»²ÉÈ¡´ÓÊý¾Ý¿âÖлñȡʱ¼ä´ÁµÄÊֶΣ¬ÔòûÓиüºÃµÄ·½·¨ÔÚÊéÇ©¶ÔÏóÖмǼ׼ȷµÄʱ¼ä´ÁÁË¡£ÒòΪÔÚ²åÈëÓëÐÞ¸ÄÖж¼ÒªÓ¦Óõ½£¬ËùÒÔÒª¸ü¸ÄActivate RecordÀ࣬µ±save()·½·¨Íê³Éºó£¬¾Í¸üÐÂʱ¼ä´Á£¨ÊµÀýµÄÏà¹ØÊôÐÔÖµ£©£¬ÒÔ±ÜÃâºóÀ´²úÉúµÄ²»Í¬²½¡£
|
class Bookmark { |
| class ActiveRecordTestCase extends UnitTestCase { // ... function testSave() { $link = Bookmark::add( ‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $link->description = ‘Where I write about PHP, Linux and other stuff’; $link->save(); $link2 = Bookmark($link->getId()); $this->assertEqual($link->getId(), $link2->getId()); $this->assertEqual($link->created, $link2->updated); } } |
ÏÖÔÚ£¬ÈÃÎÒÃÇתÏòÈçºÎ´¦Àíɾ³ý²Ù×÷¡£ÔÚ£±£¶Õ¨D¨DÊý¾ÝµØÍ¼Ä£Ê½ÖÐÓÐÒ»¸öÀý×Ó£¬µ«ÊÇÄã¿ÉÒÔ·½±ãµÄ´Óinsert()ºÍupdate()·½·¨ÖÐÍÆµ¼³öÀ´¡£
×ܽá
ÕýÈç´ó¶àÊý³õ´Î³¢ÊÔÓÉÃæÏò¹ý³Ìµ½ÃæÏò¶ÔÏó±à³ÌËù±íÏÖµÄÄÇÑù£¬¶¯Ì¬¼Ç¼ģʽÔÚ¸ÅÄîÓëÖ´ÐÐÉ϶¼½ÏΪ¼òµ¥¡£½«ÄãËùÓеÄSQL´úÂë¶¼×éÖ¯ÔÚÒ»ÆðÊǷdz£ºÃµÄ£¬²¢ÇÒ¶¯Ì¬¼Ç¼ģʽ¸øÁËÄãÒ»¸ö·Ç³£ºÃµÄ½«ÒµÎñÂß¼ÓëÊý¾Ý¿â²Ù×÷Ïà½áºÏÀ´³ÖÐø±£´æ¶ÔÏóµÄ·½·¨¡£
±¾ÕµÄÀý×ÓÓÃÁËÒ»¸öÕæÊµµÄÊý¾Ý¿âÀ´¿ª·¢²âÊÔ´úÂë¡£ÁíÒ»¸ö²âÊÔ¼òµ¥Êý¾Ý¿â´úÂëµÄ·½·¨ÊÇʹÓÃÄ£Äâ¶ÔÏ󣨲μûµÚ£¶Õ£©À´Ä£ÄâÊý¾Ý¿âÁ¬½Ó¡£²»ÐÒµÄÊÇ£¬Õâ¸ö·½·¨²¢Êǹ㷺ÓÐЧ¡£SQLÊÇÒ»¸ö¸´ÔÓµÄÓïÑÔ£¬Ä£ÄâµÄÿ¸öÓï¾ä¶¼ÓëÊý¾Ý¿âµÄϸ½ÚʵÑéÃÜÇÐÏà¹Ø¡£¶øÓÃн¨µÄ£¬Êµ¼ÊµÄ±í½øÐÐʵÑéÔòÁîÈ˾õµÃÊæ·þµÃ¶à£¬Ã»ÓÐÄ£ÄâSQLʱµÄ¸±×÷ÓÃÁË¡£
Èç¹û¶¯Ì¬¼Ç¼ģʽ»¹Óв»ÀûµÄ·½Ã棬ÔòÊÇÆä¸´ÔÓÐÔÁË¡£Ò»¸ö¶¯Ì¬¼Ç¼Àà¿ÉÄÜѸËٵıä´ó£¬¾ÍÏñÒ»¸ö¿é´ÅÌú¡£ÀýÈ磬ÊéÇ©ÀàÏÖÔÚÖ»ÓÐÒ»¸öfindById()·½·¨£¬µ«ÄãºÜÓпÉÄÜÏëÒªfindByDescription()·½·¨£¬»òÊÇfindByGroup()£¬findRecentlyCreated()µÈ·½·¨¡£
ÁíÒ»¸öÎÊÌâÊǶÔÏó»á±äµÃ“ÖØ¸´”£¬ÕâÔÚsave()·½·¨ÖпÉÄܻῴµ½¡£ÀýÈ磬$linkÓë$link£²ÔÚʵÑéÓÃÀý±íʾµÄÊDz»Í¬µÄ¶ÔÏ󣬵«ÊÂʵÉÏËüÃǶ¼ÊÇָͬһ¸öÊéÇ©ID¡£Äã¿ÉÒÔÓÃÏÂÃæµÄʵÑéÀ´Ö¤Ã÷¡£
| class ActiveRecordTestCase extends UnitTestCase { // ... function testSave() { // ... $this->assertNotIdentical($link, $link2); } } |
Èç¹ûÈÏΪ½â¾öÕâ¸öÎÊÌâÊÇÖØÒªµÄ£¬ÄãÓпÉÄÜÒªÔö¼ÓÒ»¸öÄÚ²¿µÄ×¢²á»úÖÆ£¨²Î¼ûµÚÎåÕ£©È·±£Bookmark(1)·µ»ØµÄËùÓжÔÏóµÄʵÀýÓ¦ÊÇͬһ¸ö¶ÔÏó¡£ÒòΪÄãʵ¼ÊÉÏÓõÄÊÇnew²Ù×÷À´½¨Á¢Ò»¸ö¶ÔÏó¶ø²»ÊÇÓù¤³§·½·¨£¬×÷ΪһÖÖʵ¼ÊµÄActive RecordÀ࣬ÄãÓ¦¸Ã½«BookmarkÐÞ¸ÄΪ´úÀí£¨²Î¼û£±£±Õ£©À´ÕæÕý½â¾öÕâ¸öÎÊÌâ¡£
ÁíÒ»¸ö·½Ã棬Active Recordģʽ±»Éè¼Æ³ÉÒ»´Î´¦ÀíÒ»ÐмǼµÄ·½Ê½¡£ÕâÖÖģʽÊǵäÐ͵Ĕ¹ÜÀí”ʽӦÓõĽçÃæ£¬Èç±à¼Ò»ÆªÎÄÕ£¬Ò»¸öÁ´½Ó£¬Ò»¸ö×¢Ê͵ȡ£µ«ÊÇ´óÊýµÄÍøÒ³Òª´¦ÀíµÄÊǶàÊý¾Ý¼¯»òÊǶàÐÐÊý¾Ý£¬ÕâÕýÊÇÎÒÃÇÏÂÒ»ÕÂÒªÌÖÂÛµÄÖ÷ÒªÄÚÈݨD¨D±íÊý¾ÝÍø¹ØÄ£Ê½¡£
ÒÔÉÏËù·ÖÏíµÄÊǹØÓÚ¡¶PHPÉè¼ÆÄ£Ê½½éÉÜ¡·µÚÊ®ËÄÕ ¶¯Ì¬¼Ç¼ģʽ£¬ÏÂÃæÊDZà¼ÎªÄãÍÆ¼öµÄÓмÛÖµµÄÓû§»¥¶¯£º
¡¡¡¡Ïà¹ØÎÊÌ⣺½éÉܼ¸¸öÄã±È½ÏÊìϤµÄÉè¼ÆÄ£Ê½,²¢¼òµ¥½éÉÜËüÃÇÊÇÈç...
¡¡¡¡´ð£ºÈçºÎ×öºÃ¼ô¼ÄØ£¿Ôڴ˱ÊÕß̸̸×Ô¼ºµÄ¹Ûµã£º¼ô¼¾ÍÊǽ«²»·ûºÏÖ÷ÌâµÄ²¿·Öɾ³ý²¢ÕâÀﻹ½éÉܼ¸¸ö¹ý¶ÉЧ¹ûµÄ²é¿´¼¼ÇÉ£ºÔÚTransitionsÃæ°åµÄ´°¿Ú¿ØÖƲ˵¥ÖУ¬Ñ¡Ôñ >>Ïêϸ
¡¡¡¡Ïà¹ØÎÊÌ⣺PHPÓÐÄļ¸ÖÖÉè¼ÆÄ£Ê½£¿
¡¡¡¡´ð£ºPHP Ò»°ãÓÐÎåÖÖ³£¼ûµÄÉè¼ÆÄ£Ê½ ¹¤³§Ä£Ê½ ¹¤³§Ä£Ê½ ÊÇÒ»ÖÖÀ࣬Ëü¾ßÓÐΪÄú´´½¨¶ÔÏóµÄijЩ·½·¨¡£Äú¿ÉÒÔʹÓù¤³§Àà´´½¨¶ÔÏ󣬶ø²»Ö±½ÓʹÓà new¡£ÕâÑù£¬Èç¹ûÄúÏëÒª¸ü¸ÄËù´´½¨µÄ¶ÔÏóÀàÐÍ£¬Ö»Ðè¸ü¸Ä¸Ã¹¤³§¼´¿É¡£Ê¹Óøù¤³§µÄËùÓдúÂë»á×Ô¶¯¸ü¸Ä¡£ ÀýÈç... >>Ïêϸ
¡¡¡¡Ïà¹ØÎÊÌ⣺Çó³ÌÐòÔ±ÄDZ¾Ê¥¾¡¶Éè¼ÆÄ£Ê½¡·£¬ÖÐÓ¢Îľù¿É£¬·¢ÖÁk...
¡¡¡¡´ð£ºÕâ±¾Êé±È½ÏÀÏÁË£¬ºÜ¶à¾ÉÓÐģʽ²¿·ÖÔÚ±à³ÌÓïÑÔа汾ÖÐÒѾÓÐÄÚÖÃʵÏÖ£¬¶øÇÒ±íÊöÓïÑÔÒ²±È½ÏÉúÓ² ½¨Òé¿ÉÒÔ¿´¿´ Head firstÉè¼ÆÄ£Ê½ »ò ¹úÄÚµÄ Éè¼ÆÄ£Ê½Ö®ìø Å¶ ÁíÍâ ¼ÈÈ»ÄãÌá³ö¿´Õâ±¾Ê飬Ïë±ØÄãÒ²ÓÐÒ»¶¨µÄ±à³Ì×ÔѧÄÜÁ¦ÁË ÔÙÍÆ¼öÁíÍâÁ½±¾ÊéÄã ÖØ¹¹... >>Ïêϸ
- ÆÀÂÛÁÐ±í£¨ÍøÓÑÆÀÂÛ½ö¹©ÍøÓѱí´ï¸öÈË¿´·¨£¬²¢²»±íÃ÷±¾Õ¾Í¬ÒâÆä¹Ûµã»ò֤ʵÆäÃèÊö£©
-
