發現一篇好文,介紹AS3中常見的位運算技巧的。小弟勉強翻譯一下,有錯誤還請指正。原文在這里
在AS3中位操作是非常快的,這里列出一些可以加快某些計算速度的代碼片段集合。我不會解釋什么是位運算符,也不會解釋怎么使用他們,只能告訴大家如果想清楚其中的原理這里有一篇極好的文章在gamedev.net上叫做 ‘Bitwise Operation in C' .
如果你知道任何下邊沒有列出來的不錯的技巧,請留下個評論或者給我發個郵件。所有這些都是基于AS3的
[b]左位移幾就相當于乘以2的幾次方[/b]( Left bit shifting to multiply by any power of two )
大約快了300%
[code]
x = x * 2;
x = x * 64;
//相當于:
x = x << 1;
x = x << 6;
[/code]
[b]右位移幾就相當于除以2的幾次方[/b](Right bit shifting to divide by any power of two)
大約快了350%
[code]
x = x / 2;
x = x / 64;
//相當于:
x = x >> 1;
x = x >> 6;
[/code]
[b]Number 到 integer(整數)轉換[/b]
在AS3中使用int(x)快了10% 。盡管如此位操作版本在AS2中工作的更好
[code]
x = int(1.232)
//相當于:
x = 1.232 >> 0;
[/code]
[b]提取顏色組成成分[/b]
不完全是個技巧,是正常的方法 (Not really a trick, but the regular way of extracting values using bit masking and shifting.)
[code]
//24bit
var color:uint = 0x336699;
var r:uint = color >> 16;
var g:uint = color >> 8 & 0xFF;
var b:uint = color & 0xFF;
//32bit
var color:uint = 0xff336699;
var a:uint = color >>> 24;
var r:uint = color >>> 16 & 0xFF;
var g:uint = color >>> 8 & 0xFF;
var b:uint = color & 0xFF;
[/code]
[b]合并顏色組成成分[/b]
替換值到正確位置并組合他們 (‘Shift up’ the values into the correct position and combine them.)
[code]
//24bit
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = r << 16 | g << 8 | b;
//32bit
var a:uint = 0xff;
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = a << 24 | r << 16 | g << 8 | b;
[/code]
[b]使用異或運算交換整數而不需要用臨時變量[/b]
很可愛的技巧, 在本頁頂端的鏈接里有詳細的解釋 ,這里快了 20%
[code]
var t:int = a;
a = b;
b = t;
//相當于:
a ^= b;
b ^= a;
a ^= b;
[/code]
[b]自增/自減(Increment/decrement)[b]
這個比以前的慢不少,但卻是個模糊你代碼的好方法;-)
[code]
i = -~i; // i++
i = ~-i; // i--
[/code]
[b]取反[/b](Sign flipping using NOT or XOR)
另人奇怪的是這個居然快了300%!
[code]
i = -i;
//相當于:
i = ~i + 1;
//或者
i = (i ^ -1) + 1;
[/code]
[b]使用bitwise AND快速取模[/b] (Fast modulo operation using bitwise AND)
如果除數是2的次方,取模操作可以這樣做:
模數= 分子 & (除數 - 1);
這里大約快了600%
[code]
x = 131 % 4;
//相當于:
x = 131 & (4 - 1);
[/code]
[b]檢查是否為偶數[/b](Check if an integer is even/uneven using bitwise AND)
這里快了 600%
[code]
isEven = (i % 2) == 0;
//相當于:
isEven = (i & 1) == 0;
[/code]
[b]絕對值[/b]
忘記 Math.abs()吧 (Forget Math.abs() for time critical code.)
version 1 比 Math.abs() 快了2500% ,version 2 居然比 version 1 又快了20% !
[code]
//version 1
i = x < 0 ? -x : x;
//version 2
i = (x ^ (x >> 31)) - (x >> 31);
[/code]
posted @
2008-07-29 14:14 姜大叔 閱讀(312) |
評論 (0) |
編輯 收藏
好久沒寫文章了,上一個多月,很多很多煩人的事情,我也不想多說了,導致了沒時間寫文章了,不過今后的時間將會多點,所以在這段時間里打算多寫點技術文章來填充一下Blog,主要是Flash與Java方面吧。
今天做了一個小東西,一個會轉動的3D盒子的效果,用于切換不同的內容面板,是一個不錯的Flex效果,該東西是用了DistortionEffects做的,首先感謝Dreamer介紹了DistortionEffects這個東東,我也是在他Blog里看到,之后用來做點東西試試的。以下是Dreamer里的一編文章:[url=http://www.zhuoqun.net/html/y2007/492.html]DistortionEffects[/url]
其實這個很簡單,只是使用了DistortionEffects里面的CubeRotate效果,很炫的效果,致至該效果的實現,還有待看看它的源碼進行研究研究!
以下放出我的該小Flex的源碼:
[mDown=attachments/month_0712/j20071225181513.rar]點擊下載此文件[/mDown]
posted @
2008-07-29 14:13 姜大叔 閱讀(6541) |
評論 (48) |
編輯 收藏
本篇接著上一篇文章,上篇文章中,大家都看到最終效果了,這個例子很簡單,我就粗略的講解一下代碼吧
整個Flex程序,就兩個Panel面板,將控件都排放好到Panel里面,之后定好相應的屬性,我主要解析一下下面的代碼:
1 < mx:Script >
2 <! [CDATA[
3 // 導入需要用到的類
4 import mx.utils.Base64Encoder;
5 import mx.collections.ArrayCollection;
6 import mx.controls.Alert;
7 import com.adobe.images.PNGEncoder;
8
9 // 這里定義一個ArrayCollection 這就是PieChart控件所需要的dataProvider,并賦好初值
10 [Bindable]
11 private var mydata:ArrayCollection = new ArrayCollection([
12 {name: " 非常滿意 " ,num: 1 },
13 {name: " 滿意 " ,num: 1 },
14 {name: " 普通 " ,num: 1 },
15 {name: " 不滿意 " ,num: 1 },
16 {name: " 非常不滿意 " ,num: 1 }
17 ]);
18
19 // 方法為PieChart控件自動調用的,是用于當圖表要顯示Label時,將會調用該方法,并傳上相應的參數,這樣,你就可以在該方法里自已處理好要顯示的數據,再返回給Chart顯示
20 private function showLabel(data:Object, field:String, index:Number, percentValue:Number):String{
21 return data.name + " : " + data.num + " \n " + Math.round(percentValue) + " % " ;
22 }
23
24 // 該方法是當點擊“確定”按鈕時調用的,用于改變圖表數據的ArrayCollection里的數據,再更新圖表顯示
25 private function changeData(ent:Event): void {
26 // 定一個臨時的集合用于放置數據
27 var temp:ArrayCollection = new ArrayCollection();
28 // 判斷用戶所填的數據是否為空,如果為空的就不要加進集合里了,免得圖表出現一些無謂的Label,下同
29 if (resu0.text != "" ){
30 temp.addItem({name: " 非常滿意 " ,num: resu0.text});
31 }
32 if (resu1.text != "" ){
33 temp.addItem({name: " 滿意 " ,num: resu1.text});
34 }
35 if (resu2.text != "" ){
36 temp.addItem({name: " 普通 " ,num: resu2.text});
37 }
38 if (resu3.text != "" ){
39 temp.addItem({name: " 不滿意 " ,num: resu3.text});
40 }
41 if (resu4.text != "" ){
42 temp.addItem({name: " 非常不滿意 " ,num: resu4.text});
43 }
44 panel1.title = subjectTitle.text;
45 /*
46 mydata[0].num = resu0.text;
47 mydata[1].num = resu1.text;
48 mydata[2].num = resu2.text;
49 mydata[3].num = resu3.text;
50 mydata[4].num = resu4.text;
51 */
52 pc.dataProvider = temp;
53 }
54
55 // 這里是截圖的方法函數,參照于國外某高手地Flex截圖方面的代碼
56 private function catchPic(ent:Event): void {
57 // 根據要截圖的Panel的大小建立一個放置位圖數據的BitmapData對象
58 var bitmapData:BitmapData = new BitmapData(panel1.width,panel1.height, true , 0xffffff );
59 // 用現時panel1對象的位圖信息填充到bitmapData對象中
60 // 由于每一個DisplayObject對象都有自已的用于顯示的位圖色彩信息,
61 // 所以很多繼承了DisplayObject的類都可以填充到bitmapData對象中處理,如模糊處理等
62 bitmapData.draw(panel1);
63 // 用PNGEncoder類對位圖信息進行壓縮轉換處理才得以輸出PNG圖片格式數據
64 var bytes:ByteArray = PNGEncoder.encode(bitmapData);
65 // 再將數據進行編碼,用于在JavaScript中向瀏覽器傳播
66 // 最后調用JavaScript來打開新窗口來顯示圖借數據
67 var b64encoder:Base64Encoder = new Base64Encoder();
68 b64encoder.encodeBytes(bytes);
69 ExternalInterface.call( " showPic " ,b64encoder.flush(),panel1.width + 25 ,panel1.height + 25 );
70 }
71 ]] >
72 </ mx:Script >
JavaScript方面要寫上以下函數:
1 function showPic(img,width,height){
2 window.open( " data:image/png;base64, " + img, "" , " width= " + width + " ,height= " + height + " ,resizable=1 " );
3 }
以上有幾點應該要注意:
注意PieChart的dataProvider的寫法,也就是ArrayCollection的寫法,這與很多控件的dataProvider的都一樣,比如DataGrid控件。
注意,PNGEncoder類不是Flex原本自帶的,是要另外自已下載的擴展包,在com.adobe.images里面,是Adobe發布的核心擴展類庫,更多的類庫,大家可以在網上找找。
以下放出完整的源代碼:[down=attachments/month_0710/92007102323188.rar]點擊下載此文件[/down]
posted @
2008-07-29 14:10 姜大叔 閱讀(2774) |
評論 (4) |
編輯 收藏
應朋友要求,做一個數據圖表的東西,主要是用于將數據以圖表的方式表示,以不至于用Excel看一大表格,里面密密麻麻的數字,所以,第一時間想到用Flex Chart玩玩,由于原本已有點Flex基礎,So,Flex Chart也不是太難,而且效果滿意漂亮,也就當作開拓該方面技術的練手之作吧,程序很簡單,就在一邊輸入數據,另一邊則顯示該數據所表示的餅圖圖形,后來并加上了“生成圖片”按鈕,該功能是參照外國某位牛人所做的,不過就是該功能只支持FireFox。
[url=jiang/catch_chart/chart.html]可以去這里看看效果[/url]
待會我整理好源代碼,再放出源代碼,并解析一下該程序。
posted @
2008-07-29 14:08 姜大叔 閱讀(2302) |
評論 (0) |
編輯 收藏
這幾天無聊著,打開163郵箱,看到右上角的天氣信息,突然心血來潮,自已也做個天氣信息的小模塊放在Blog上,就是左邊側欄的那個,其實之前都做過,只不過是用Java來解析,Flex來顯示,而已之前的那個是解析www.weathercn.com的信息的,但現在該站的天氣頁面改版了,所以不得不重新做,既然如此,就拿163的來做吧。原理都是一樣,用PHP讀取163的天氣信息網頁,再用正則表達式解析網頁的內容,提取有用的天氣信息,組織好成XML格式,之后Flex用WebService來讀取該PHP,得到XML數據,再相應的顯示。
其實這并不難,打開的我163郵箱,查看它的網頁源碼,經過一番的查找分析,找到它獲取天氣信息的網頁:http://mimg.163.com/tianqi/city/59287.html 呵呵,還是Html的哦,網易的將動態的天氣生成靜態的頁面,我們訪問起來,也不太占服務器資源吧,因為天氣也是經常訪問的。看看源代碼,就幾行Html代碼,正合我的需求,免得我的PHP分析大量的代碼占點資源。不過有點要注意,網易把每個城市的代號生成一個頁面,即是一個城市,一個天氣頁面,上面那個URL是廣州的,就是說 59287 就是廣州的城市代碼,在PHP里訪問時,要跟據用戶選的是哪個城市,相對應的修改那個號碼就行了,如:
$url = "http://mimg.163.com/tianqi/city/".$_GET['city'].".html";
這樣,你訪問PHP時,要傳一個城市代碼參數,至于網易定義的城市代碼,我這里就不列出來了,太多太長了,也找了我不少時間。我放在Flex的源碼里,可以下載我的源碼看看。
以下是PHP頁面的代碼:
1 <? php
2 include ( " class.Chinese.php " ); # 導入字符集轉換的類
3 $codeTableDir = " ./config/ " ; # 指定字符碼表的路徑
4
5 $url = " http://mimg.163.com/tianqi/city/ " . $_GET [ ' city ' ] . " .html " ; # 獲取城市代碼,組成完整的URL
6
7 $fh = fopen ( $url , ' r ' ); # 讀取該URL獲取內容
8 while ( ! feof ( $fh )){
9 $content .= fread ( $fh , 128 ); # 讀取全部內容
10 }
11 $content = new Chinese( " GB2312 " , " UTF8 " , $content , $codeTableDir ); # 轉換字符碼,GB轉UTF8
12 $content = $content -> ConvertIT(); # 轉換
13 eregi ( ' (<span class="wetCityName">)([^/]*)(</span>) ' , $content , $arr ); # 找出表示城市的內容
14 $city = $arr [ 2 ];
15
16 eregi ( ' (<span class="wetDate">)(.*)(</span></div>) ' , $content , $arr ); # 找出表示日期的內容
17 $date = $arr [ 2 ];
18
19 $wea = split ( ' txtAlgCen fRig handle ' , $content ); # 分開今天與明天
20
21 eregi ( ' (<div class="wetSts">)([^<]*)(</div>) ' , $wea [ 0 ] , $arr ); # 找出表示今日天氣的內容
22 $info1 = $arr [ 2 ];
23 eregi ( ' (<div class="wetSts">)([^<]*)(</div>) ' , $wea [ 1 ] , $arr ); # 找出表示明日天氣的內容 下同
24 $info2 = $arr [ 2 ];
25
26 eregi ( ' (</b>)([^<]*)(</div>) ' , $wea [ 0 ] , $arr );
27 $temp1 = $arr [ 2 ];
28 eregi ( ' (</b>)([^<]*)(</div>) ' , $wea [ 1 ] , $arr );
29 $temp2 = $arr [ 2 ];
30
31 eregi ( ' (class="wetDico )(.*)("></div>) ' , $wea [ 0 ] , $arr );
32 $pic1 = $arr [ 2 ];
33 eregi ( ' (class="wetDico )(.*)("></div>) ' , $wea [ 1 ] , $arr );
34 $pic2 = $arr [ 2 ];
35
36 echo " <?xml version=\ " 1.0 \ " encoding=\ " utf - 8 \ " ?> " ;
37 echo " \n " ;
38 ?>
39 < weather >
40 < city ><?= $city ?></ city >
41 < date ><?= $date ?></ date >
42 < today >
43 < wea ><?= $info1 ?></ wea >
44 < temp ><?= $temp1 ?></ temp >
45 < pic ><?= $pic1 ?></ pic >
46 </ today >
47 < tomorrow >
48 < wea ><?= $info2 ?></ wea >
49 < temp ><?= $temp2 ?></ temp >
50 < pic ><?= $pic2 ?></ pic >
51 </ tomorrow >
52 </ weather >
以上有幾點要注意:
1。由于網易里的網頁是用GB2312編碼的,而Flex里接收的XML要UTF-8編碼才會正確讀出,所以要將獲取的網易里的數據進行轉碼,這問題剛開始時,老是亂碼,搞到心煩,后來發現網易的Html的頭信息里 發現是GB2312的編碼,郁悶了半天,之后上網找了個中文轉碼的類,下載來直接套用。
2。獲取回來的天氣信息的Html是分今天與明天的天氣信息,而里面的格式也是一樣的,所以,用正則查找時,只找到最先的那個,所以要先找個今天與明天的分界點,將其分離開來再各自解析里面的內容,得出今天的天氣與明天的天氣。
3。寫輸出XML時,格式要正確,不然Flex里讀取會有麻煩,還有,encoding一定要是UTF-8,還要將該PHP文件保存成UTF-8格式,我用DW寫該PHP時,因為我的DW新建文件時,默認是ISO8859-1的,所以要將其文檔編碼格式改為UTF-8來保存。
PHP完工之后,來到Flex這邊,畫好界面,添加代碼如下:
先加一個HttpService標簽 :
<mx:HTTPService id="hs" showBusyCursor="true" method="GET" result="{hsResult(event);}" fault="{hsFault(event);}" />
(事件響應方法我就不在這里貼出來了,可下載源碼看)
當下拉選框選中城市之后,判斷用戶選中的是哪個城市,再對照該城市的代號,組合成URL
hs.url = "http://www.jiangzone.com.cn/jiang/weather/weather.php?city=" + cityvalues[i];
hs.send();
結果返回時,再相應的賦值:
lblCity.text = event.result.weather.city;
lblDate.text = event.result.weather.date;
lblWea.text = event.result.weather.today.wea;
weather對應XML里的<weather>根標簽,city對應XML里的<city>標簽。
OK,修改一下,大功告成!
以下是源碼:
[down=attachments/month_0709/t2007916122822.rar]點擊下載此文件[/down]
posted @
2008-07-29 14:07 姜大叔 閱讀(1222) |
評論 (1) |
編輯 收藏
adobe的一些as3類庫提供給google code(http://actionscript3libraries.riaforge.org/)可以隨意下載...
其中的as3corelib里面包含image的png和jpg類和json(序列化數據)類包.
同時amfphp1.9beta的發布可以讓你用remoting來傳遞amf3格式的數據.
那么有了這兩個條件我們就可以用他們來直接生成png和jpg格式的圖片...
使用方法也是比較簡單,使用前面我提供的方法可以很方便的實現...
as3corelib里面的png和jpg類
[down=attachments/month_0709/r2007917165754.rar]點擊下載此文件[/down]
as代碼:
//------------------------------------------------------------------------------------
//在舞臺上放一個mc名字為a,mc包含一些隨意的圖形
import flash.net.*;
import flash.display.*;
var hostName:String = "http://localhost/amfphp/";
var gatewayUrl:String = hostName+"gateway.php";
////////////////////////////
var bpd:BitmapData = new BitmapData(a.width, a.height);
bpd.draw(a);
//var jpegEnc:JPEGEncoder = new JPEGEncoder(80);
//var dat:ByteArray = jpegEnc.encode(bpd);
var dat:ByteArray = PNGEncoder.encode(bpd);
//
var nc:NetConnection = new NetConnection();
//nc.objectEncoding = 0;
nc.connect(gatewayUrl);
//
nc.call("SavePic.save",new Responder(onResult,onFault),dat);
//nc.call("SavePic.test",new Responder(onResult,onFault),"h..roading");
/////////////////////////////
function onResult(re:Object)
{
trace(re);
}
function onFault(re:Object)
{
trace(re);
for(var i in re)
trace(i+"=>"+re[i]);
}
//----------------------------------------------------------------------------------------------
php代碼:
1 // -----------------------------------------------------------------------------------------------
2 <? php
3
4 class SavePic
5 {
6
7 function Tuya()
8 {
9 $this -> methodTable = array (
10 " save " => array (
11 " access " => " remote "
12 ) ,
13 " test " => array (
14 " access " => " remote "
15 )
16 );
17 }
18 function test( $str )
19 {
20 return $str ;
21
22
23 }
24
25
26 function save( $data )
27 {
28 $name = time () . ' .jpg ' ; // png
29
30 $im = fopen ( $name , ' a ' );
31
32 fwrite ( $im , $data );
33
34 fclose ( $im );
35
36 return $name ;
37 }
38 }
39 ?>
40
41
posted @
2008-07-29 14:05 姜大叔 閱讀(248) |
評論 (0) |
編輯 收藏
在關系數據庫應用中,都離不開表與表的關聯,表與表之間建立了關聯關系后就可以提供很多方便的操作了,比如我要查詢一個學生的信息,如果不建立學生與班級的關系的話,那么,只可以顯示出學生的基本信息,而學生是屬于某一個班級的,我現在想知道這個學生的信息與該學生所在的班級的信息,甚至是該學生的任課老師等信息,建立了學生表,與班級表,老師表之間的關系就方便好多了,用一個學生ID就可以查找出所有相關聯的數據。
在FleaPHP中,支持以下四種關聯關系:
* HAS_ONE
* HAS_MANY
* MANY_TO_MANY
* BELONGS_TO
分別對應FLEA_Db_TableDataGateway表中的 $hasOne,$hasMany,$manyToMany,$belongsTo 屬性
我們下面就用 老師,學生,學生檔案,班級的例子說說這幾個關系。
以下是SQL代碼:
1 // 學生表
2 Create TABLE `testDB`.`student` (
3 `stu_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
4 `stu_name` VARCHAR ( 20 ) NOT NULL ,
5 `stu_class_id` INTEGER UNSIGNED NOT NULL ,
6 PRIMARY KEY (`stu_id`)
7 )
8
9 // 學生檔案表
10 Create TABLE `testDB`.`stu_record` (
11 `record_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
12 `stu_id` INTEGER UNSIGNED NOT NULL ,
13 `family_add` VARCHAR ( 150 ) NULL ,
14 `family_tel` VARCHAR ( 20 ) NULL ,
15 PRIMARY KEY (`record_id`)
16 )
17
18 // 教師表
19 Create TABLE `testDB`.`teacher` (
20 `teacher_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
21 `teacher_name` VARCHAR ( 20 ) NOT NULL ,
22 PRIMARY KEY (`teacher_id`)
23 )
24
25 // 班級表
26 Create TABLE `testDB`.`classes` (
27 `class_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
28 `class_name` VARCHAR ( 20 ) NOT NULL ,
29 PRIMARY KEY (`class_id`)
30 )
31
32 // 由于教師與班級是多對多關系,所有建立一個中間連接表以表示該關聯
33 Create TABLE `testDB`.`link_teacher_classes` (
34 `link_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
35 `teacher_id` INTEGER UNSIGNED NOT NULL ,
36 `class_id` INTEGER UNSIGNED NOT NULL ,
37 PRIMARY KEY (`link_id`)
38 )
現在,建好表之后,我們還要寫幾個繼承自FLEA_Db_TableDataGateway父類的類,以對應數據庫中的Student,Teacher,Classes表(連接表不用了)如下:
1 // 學生表對應的類
2 class Model_Student extends FLEA_Db_TableDataGateway{
3 var $tableName = ' student ' ;
4 var $primaryKey = ' stu_id ' ;
5
6 /*
7 這是一對一關系,一個學生對應唯一的一個Record檔案
8 tableClass 對應要與之關聯一對一的表的對象類,即檔案表的類
9 foreignKey是在檔案表中,對應學生表的一個外鍵接連字段,
10 用該字段標識該檔案屬于哪個學生
11 mappingName 就是用于在你查詢學生信息時,學生檔案字段的別名
12 */
13 var $hasOne = array (
14 ' tableClass ' => ' Model_Record ' ,
15 ' foreignKey ' => ' stu_id ' ,
16 ' mappingName ' => ' record '
17 );
18 /*
19 這是從屬關系,一個學生屬于某一個班級,換過來說就是班級與學生一對多,
20 一個班級有多個學生,而學生就只屬于一個班級
21 tableClass 指定該類要與之有從屬關系的類,這里是班級類
22 foreignKey 這里指定的是該表里的連接外表的字段,這里是學生表的班級ID字段
23 注意:這里的foreignKey指的是本表的字段,而上面hasOne關系中的foreignKey
24 指的是外表中的字段,要注意區分清楚
25 mappingName這里就不多說了,跟上面的一樣,也是用于顯示區分的別名
26 */
27 var $belongsTo = array (
28 array (
29 ' tableClass ' => ' Model_Classes ' ,
30 ' foreignKey ' => ' stu_class_id ' ,
31 ' mappingName ' => ' class '
32 )
33 );
34 }
35
36 // 檔案表對應的類
37 class Model_Record extends FLEA_Db_TableDataGateway{
38 var $tableName = ' stu_record ' ;
39 var $primaryKey = ' record_id ' ;
40 }
41
42 // 教師表對應的類
43 class Model_Teacher extends FLEA_Db_TableDataGateway{
44 var $tableName = ' teacher ' ;
45 var $primaryKey = ' teacher_id ' ;
46
47 /*
48 這里確立了教師與班級的多對多關系,一個教師可以教多個班級
49 而一個班級也有多個教師
50 tableClass 指定要建立多對多關系的表的類
51 joinTable 這個屬性要注意一個,這個是指定教師表與班級表關系的連接表
52 由于二維表的數據結構的原因,所以多對多關系要用一個中間表(即連接表)來表示
53 連接表中就指明兩個表各自的主鍵ID就可以了,以兩個字段作復合主鍵,如不用復合
54 主鍵,就新增加一個字段作主鍵也可,這沒關系
55 */
56 var $manyToMany = array (
57 array (
58 ' tableClass ' => ' Model_Classes ' ,
59 ' mappingName ' => ' class ' ,
60 ' joinTable ' => ' link_teacher_classes ' ,
61 )
62 );
63 }
64
65 class Model_Classes extends FLEA_Db_TableDataGateway{
66 var $tableName = ' classes ' ;
67 var $primaryKey = ' class_id ' ;
68
69 /*
70 這里確立了班級與學生的一對多關系
71 tableClass 指定該表的類要與哪個表的類建立一對多關系
72 foreignKey 外鍵ID,這里即指定學生表中定義的班級ID,這個是外表的字段
73 */
74 var $hasMany = array (
75 array (
76 ' tableClass ' => ' Model_Student ' ,
77 ' foreignKey ' => ' stu_class_id ' ,
78 ' mappingName ' => ' students '
79 )
80 );
81
82 var $manyToMany = array (
83 // 由于多對多關系是雙向的,所以班級表也可以定義上與教師表的多對多關系
84 // 也可以不寫,看需求而定,比如你想查看某個班級信息時,一并顯示該班
85 // 有多少個任課老師的話,那就在這個班級類里加上關系,我這里就不寫了。。。
86 );
87 }
以上的代碼就建立好了關系了,現在只管使用就是了。
不過還提醒大家一點,在每個關系里,都有一個 ‘enabled’ 的屬性,如果設置為 false的話,則是將該關系禁掉,所以查詢出來的結果就沒有該關系的相應數據,這樣可以節省效率,按需要時才打開相應的關聯,該屬性默認為true 可以如下設置:
1 array (
2 ' tableClass ' => ' Model_Student ' ,
3 ' foreignKey ' => ' stu_class_id ' ,
4 ' mappingName ' => ' students ' ,
5 ‘enabled’ => false
6 )
現在我們來測試一下數據。(事先自行插入幾行數據用以測試)
1 $classManager = FLEA :: getSingleton( ' Model_Classes ' );
2 $class =& $classManager -> find( array ( ' class_id ' => 1 ));
3 dump( $class );
出現結果如下:
這個例子已含蓋了這四個關聯關系的基本用法了,其它的就由你們來探索了,不久后,我將會發表一下這此關聯方面的高級應用,有時間的話會寫寫這方面的東西。敬請期待!
posted @
2008-07-29 14:02 姜大叔 閱讀(330) |
評論 (0) |
編輯 收藏
這篇文章是接著上一篇,在上一篇的基礎上加了用戶注冊功能,注冊成功后顯示用戶信息,由于時間關系,沒有詳細研究實現什么功能例子用于教學,本來我也只是FleaPHP初學者,所以,雖然例子十分的傻瓜式簡單,但就當是我在學FleaPHP時的快速練習吧。
這里只實現了個注冊功能,有經驗的應該閉上眼睛都能做出來了,所以我這里的只是演示一下FleaPHP的大概操作流程的,也就是它的結構都是差不多,我在之前第一篇的那個Model_User類里,加了幾個方法:
1 // 添加一個新用戶
2 function addNewUser( $user ){
3 return $this -> _tbUser -> create( $user );
4 }
5 // 用主鍵加載一個用戶
6 function loadUser( $userid ){
7 return $this -> _tbUser -> find( $userid );
8 }
并在Default.php里,也就是在Default的Controller里加了一個action與一個方法函數:
1 function actionRegister(){
2 $mod_user = new Model_User;
3 $username = $_POST [ " username " ];
4 $password = $_POST [ " password " ];
5 $password2 = $_POST [ " password2 " ];
6
7 if ( strlen ( $username ) < 6 ){
8 $message = ' 用戶名要求6-10位! ' ;
9 include ( ' app/View/register.php ' );
10 return ;
11 }
12
13 if ( $password != $password2 ){
14 $message = ' 你輸入的密碼不一致,請重新輸入! ' ;
15 include ( ' app/View/register.php ' );
16 return ;
17 }
18
19 if ( strlen ( $password ) < 6 ){
20 $message = ' 密碼要求6-10位! ' ;
21 include ( ' app/View/register.php ' );
22 return ;
23 }
24
25 $user = array (
26 ' name ' => $username ,
27 ' password ' => $password
28 );
29 $newUserId = $mod_user -> addNewUser( $user );
30
31 if ( $newUserId ){
32 $message = ' 注冊成功! ' ;
33 $this -> showinfo( $newUserId );
34 } else {
35 $message = ' 出現錯誤,注冊失敗! ' ;
36 include ( ' app/View/error.php ' );
37 }
38 }
39
40 function showinfo( $userid ){
41 $mod_user = new Model_User;
42 $user = $mod_user -> loadUser( $userid );
43 include ( ' app/View/userinfo.php ' );
44 }
這都很直觀了,大家注意的是流程的控制與轉移,如果是開發小項目的話,這可能還會覺得麻煩,但當項目稍大時,程序結構將會很直觀,控制流程很清淅。
之后在View文件夾里加了register.php error.php等View文件,也主要是Html的,應盡量把邏輯代碼與UI代碼分開,這里只是初入門篇,遲點將會介紹與Smarty模板技術結合使用的文章。
最終源碼下載:[down=attachments/month_0710/k20071016235619.rar]點擊下載此文件[/down]
posted @
2008-07-29 13:58 姜大叔 閱讀(230) |
評論 (0) |
編輯 收藏
由于忙,很少時間學學 FleaPHP 框架,不過之前也看了看學了點東西,感覺FleaPHP框架還是很不錯的,有良好的MVC模式結構,比較方便的數據庫操作,好東西不敢獨享,所以獻上我在學習FleaPHP中的一點小心得,適合初接觸 FleaPHP 框架的同學,PHP基礎不太好的話,建議先補習一下PHP再看看這系列的文章。
本例子是我剛學FleaPHP框架時的小練習,一步一步循序漸進,剛開始的例子顯得比較簡單,都只是熟習他的環境而已,不過我將采用增量開發的模式,慢慢完善深入,同學們記得專心上堂哦,做好功課哦。(文章的末尾將提供完整源代碼打包,由于篇幅有限,所以文章中貼出來的代碼有的只是片段)
這篇是我寫 FleaPHP 學習筆記的開篇,做的是一個簡單的登錄功能,牛刀小試吧,認大家認識一下 FleaPHP 的MVC結構與基本數據庫操作,如果是對 FleaPHP 還不知道是什么東西的話,可以到以下網站了解了解。
fleaphp.org
數據庫準備:數據庫里就只有一個表 tb_user 里面有三個字段,id ,name ,password 夠簡單吧[smile]
我的這個FleaPHP應用的目錄結構如下:
圖中可以看到就一個index.php主頁文件,一個app與一個FLEA文件夾,因為FleaPHP是采用單一入口框架,所以就只有一個index.php文件,所以的請求都經由這個文件再進行分類分發,這樣可以提高代碼的安全性,可以將程序其它文件放置到URL訪問不到的地方,在index.php里引用該路徑就可以了。不過有點要注意的是文件的路徑的正確性。
app文件夾就是我的程序代碼放置的地方,里面有Controller,Model,View,Table文件夾,Controller文件夾都是FleaPHP的命名約定的,最好使用這樣的命名,因為會跟據請求到該文件夾中找相對應的類文件的,好,我們先來看看index.php的代碼:
1 <? php
2 require ( " ./FLEA/FLEA.php " );
3 FLEA :: import( dirname ( __FILE__ ) . " /app " );
4
5 // 準備數據庫連接信息
6 $dsn = array (
7 ' driver ' => ' mysql ' ,
8 ' host ' => ' localhost ' ,
9 ' login ' => ' root ' ,
10 ' password ' => ' root ' ,
11 ' database ' => ' test ' ,
12 );
13
14 set_app_inf( ' dbDSN ' , $dsn );
15
16 FLEA :: runMVC();
17 ?>
就這么個三四行代碼,程序就啟動了,呵呵,不過后面還有呢。。。
先來解析一下,第一句是 require("./FLEA/FLEA.php"); 就是要先導入FleaPHP的核心引擎,所以之前大家看到了有個FLEA文件夾,就是FLEA的核心引擎啦,這個大家先不用管它,等到要研究他的源代碼時再看吧,平時的使用就看看提供的API文檔就夠了。
同學們注意了,FLEA::import(dirname(__FILE__)."/app"); 這句的作用是什么?這個import函數是FLEA的靜態函數,用于將你的程序文件夾導入進來,如果有玩過Java的同學應該知道多少吧,當FleaPHP接收到一個請求時,會分析URL再調用相對的Controller和Action,
如:http://localhost/fleatest/index.php?controller=Shop&action=checkout 這里即調用Shop控制器里面的checkout動作,而FleaPHP怎么知道我的控制器代碼放在哪里呢?就是靠import這個語句了,將程序文件夾導入進來之后,FleaPHP會自去到這個文件夾里找Controller文件夾再找Shop.php這個類文件,所以,如果你為了安全起見,將程序文件夾放在了其它訪問不到的地方,就得靠這個import來導入,以FleaPHP能正確找到所需要的Controller。(可能說得啰嗦了[redface],打字累了,燒根煙先,同學們小息片刻!)
接下來$dsn這個數組就是存放你連接數據庫的信息啦,聰明的同學一眼看出來了。之后當然要設置入FleaPHP配置里面啦,用這個set_app_inf('dbDSN',$dsn);,之后,FLEA::runMVC(); 這個就是啟動了。我們輸入的URL是 http://localhost/fleatest/index.php,由于FleaPHP默認的Controller是Default,默認的Action是Index,所以,這時,FleaPHP就會跳到app/Controller/Default.php這個頁面來,代碼如下:
1 <? php
2 FLEA :: loadClass( " Model_User " );
3 class Controller_Default
4 {
5 function actionIndex(){
6 include ( ' app/View/login.php ' );
7 }
8
9 function actionLogin(){
10 // 新建一個對應user數據表操作的Model對象
11 $mod_user = new Model_User;
12 // 根據用戶輸入的用戶名查找數據庫有沒有存在
13 $result = $mod_user -> findByName( $_POST [ ' username ' ]);
14 if ( empty ( $result )){
15 $message = ' 該用戶不存在! ' ;
16 include ( ' app/View/login.php ' );
17 } else {
18 // 判斷密碼是否相同
19 if ( $result [ ' password ' ] == $_POST [ ' password ' ]){
20 $username = $result [ ' name ' ];
21 include ( ' app/View/welcome.php ' );
22 } else {
23 $message = ' 密碼不正確,請重新輸入! ' ;
24 include ( ' app/View/login.php ' );
25 }
26 }
27 }
28 }
29 ?>
為什么類名是 Controller_Default ?這都是FleaPHP的命名規則,大家可以去官網看看它的命名規則,這里就不多啰嗦了。現在,它將會調用actionIndex的默認action函數,里面只引入了一個php文件,那就是登錄界面的頁面。
在登錄界面的Form里,設置好action提交路徑,使它提交到Default控制器的Login動作(action),里面實例化了一個Model對象,該對象是封裝了對表tb_user的操作,之后程序邏輯就是跟據登錄成功與否來進行相應的信息表示啦,簡單的實現了從Controller -> Model -> View 的MVC訪問操作流程。
大概的結構就這么簡單了。
最后符上源代碼:[down=attachments/month_0710/520071010232245.rar]點擊下載此文件[/down]
大家如果有什么疑問,可以留言或發到我郵箱里!
posted @
2008-07-29 13:57 姜大叔 閱讀(354) |
評論 (1) |
編輯 收藏
緩存
功能強大的應用程序一般都有很大的開銷,通常是數據獲取和處理操作帶來的。對于Web應用程序,這個問題是由于HTTP協議的無狀態性造成的。由于HTTP協議是無狀態的,對于每個頁面請求,都要重復地執行相同的操作,而不論數據是否修改。要讓應用程序在世界范圍最大的網絡中可用,會使這個問題進一步惡化。所以,毫不奇怪,人們總在想方設法地讓Web應用程序運行得更高效。對此有一種特別有效的解決方案,這也是最合理的方案之一:將動態頁面轉換成靜態頁面,只有在頁面內容有修改之后才重新構建,或者定期地重新構建。Smarty提供了這樣一個特性,一般稱為頁面緩存。
如果要使用緩存,需要首先通過設置Smarty 的緩存屬性來啟用緩存,如下:
1 <? php
2 require ( " Smarty.class.php " );
3 $smarty = new Smarty;
4 $smarty -> caching = 1 ;
5 $smarty -> display( " news.tpl " );
6 ?>
啟用緩存后,調用 display() 和 fetch() 方法在指定模板 (由$cache_dir 屬性指定) 中保存目標模板的內容。
處理緩存生命期
緩存的頁面在由 $cache_lifetime 屬性指定的生命期(以秒為單位)內有效,默認為3600秒,即1小時。因此,如果希望修改此設置,就可以設置這個屬性,如下:
1 <? php
2 require ( " Smarty.class.php " );
3 $smarty = new Smarty;
4 $smarty -> caching = 1 ;
5 // 設置生命周期
6 $smarty -> cache_lifetime = 1800 ;
7 $smarty -> display( " news.tpl " );
8 ?>
在此對象的生命期內,后續調用和緩存的模板都使用此生命期。
有可能需要覆蓋以前設置的緩存生命期,從而能分別控制每個模板的緩存生命期。通過將$caching 屬性設置為2就可以做到這一點,如下:
1 <? php
2 require ( " Smarty.class.php " );
3 $smarty = new Smarty;
4 $smarty -> caching = 2 ;
5 $smarty -> cache_lifetime = 1200 ;
6 $smarty -> display( " news.tpl " );
7 ?>
在這里,news.tpl 模板的生命期設置為20分鐘,它覆蓋了前面設置的全局生命期值。
通過 is_cached( ) 消除處理開銷
如前面所述,緩存模板還能消除處理開銷,如果禁用緩存(只啟用編譯),這些處理開銷總是會發生。但是,默認情況下并沒有啟用緩存。要啟用緩存,需要把處理指令放在 if 條件中,并執行 is_cached( )方法,如下:
1 <? php
2 require ( " Smarty.class.php " );
3 $smarty = new Smarty;
4 $smarty -> caching = 1 ;
5
6 if ( ! $smarty -> is_cached( " news.tpl " )){
7 $conn = mysql_connect ( " localhost " , " name " , " pwd " );
8 $db = mysql_select_db ( " news " );
9 $query = " select * from news " ;
10
11 }
12 $smarty -> display( " news.tpl " );
13 ?>
在這個例子中,將首先驗證模板news.tpl是否有效。如果有效,則跳過數據庫訪問,否則才訪問數據庫。
為每個模板創建多個緩存
任何指定的Smarty模板都可以用于為整個新聞項,博客項等提供一個通用界面。由于同一個模板用來生成不同數量的不同項,那么如何緩存一個模板的多個實例呢?答案比你想像的要簡單。Smarty的開發人員實際不已經解決了這個問題,可以通過display()方法為緩存模板的每個實例指派一個唯一標識符。例如,假設有一個用生成用戶信息的模板,并希望緩存這個模板的各個實例:
1 <? php
2 require ( " Smarty.class.php " );
3 require ( " User.class.php " );
4
5 $smarty = new Smarty;
6 $smarty -> caching = 1 ;
7
8 // 根據不同的用戶ID來區分不同的用戶實例來判斷有沒有被緩存
9 if ( ! is_cached( " userinfo.tpl " , $_GET [ ' userid ' ])){
10 $user = new User();
11
12 $smarty -> assign( " name " , $user -> getName());
13 $smarty -> assign( " address " , $user -> getAddress());
14 }
15
16 /*
17 當顯示時也根據該用戶的ID來區分將哪個實例進行緩存,而不影響其它用戶的緩存
18 即是用userid 值來區分同一個緩存模板的不同實例,所有用戶都共用一個模板,
19 但信息都不盡相同,所以不能統一緩存,要獨立分開緩存
20 */
21 $smarty -> display( " userinfo.tpl " , $_GEG [ ' userid ' ]);
22 ?>
特別注意下面一行:
$smarty->display("userinfo.tpl",$_GEG['userid']);
這一行對于此腳本有兩個功能,一方面獲取名為$_GET['userinfo'] 的 userinfo.tpl 緩存版本,另一方面,如果還不存在這個緩存,則用這個名字來緩存該模板實例。采用這種方式,可以輕松地為指定模板緩存任意數量的實例。
關于緩存的結語
模板緩存大大提升了應用程序的性能,如果決定將Smarty集成到工程中來,就應當認真地考慮緩存。但是,因為大多數強大的Web應用程序功能都體現在其動態性上,所以一方面要考慮到性能提升,另一方面也要考慮到緩存頁面隨時間是否仍有效,要在這二者之間進行權衡。
posted @
2008-07-29 13:55 姜大叔 閱讀(222) |
評論 (0) |
編輯 收藏