發(fā)現(xiàn)一篇好文,介紹AS3中常見的位運算技巧的。小弟勉強翻譯一下,有錯誤還請指正。原文在這里
在AS3中位操作是非常快的,這里列出一些可以加快某些計算速度的代碼片段集合。我不會解釋什么是位運算符,也不會解釋怎么使用他們,只能告訴大家如果想清楚其中的原理這里有一篇極好的文章在gamedev.net上叫做 ‘Bitwise Operation in C' .
如果你知道任何下邊沒有列出來的不錯的技巧,請留下個評論或者給我發(fā)個郵件。所有這些都是基于AS3的
[b]左位移幾就相當(dāng)于乘以2的幾次方[/b]( Left bit shifting to multiply by any power of two )
大約快了300%
[code]
x = x * 2;
x = x * 64;
//相當(dāng)于:
x = x << 1;
x = x << 6;
[/code]
[b]右位移幾就相當(dāng)于除以2的幾次方[/b](Right bit shifting to divide by any power of two)
大約快了350%
[code]
x = x / 2;
x = x / 64;
//相當(dāng)于:
x = x >> 1;
x = x >> 6;
[/code]
[b]Number 到 integer(整數(shù))轉(zhuǎn)換[/b]
在AS3中使用int(x)快了10% 。盡管如此位操作版本在AS2中工作的更好
[code]
x = int(1.232)
//相當(dāng)于:
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]使用異或運算交換整數(shù)而不需要用臨時變量[/b]
很可愛的技巧, 在本頁頂端的鏈接里有詳細(xì)的解釋 ,這里快了 20%
[code]
var t:int = a;
a = b;
b = t;
//相當(dāng)于:
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;
//相當(dāng)于:
i = ~i + 1;
//或者
i = (i ^ -1) + 1;
[/code]
[b]使用bitwise AND快速取模[/b] (Fast modulo operation using bitwise AND)
如果除數(shù)是2的次方,取模操作可以這樣做:
模數(shù)= 分子 & (除數(shù) - 1);
這里大約快了600%
[code]
x = 131 % 4;
//相當(dāng)于:
x = 131 & (4 - 1);
[/code]
[b]檢查是否為偶數(shù)[/b](Check if an integer is even/uneven using bitwise AND)
這里快了 600%
[code]
isEven = (i % 2) == 0;
//相當(dāng)于:
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 姜大叔 閱讀(311) |
評論 (0) |
編輯 收藏
好久沒寫文章了,上一個多月,很多很多煩人的事情,我也不想多說了,導(dǎo)致了沒時間寫文章了,不過今后的時間將會多點,所以在這段時間里打算多寫點技術(shù)文章來填充一下Blog,主要是Flash與Java方面吧。
今天做了一個小東西,一個會轉(zhuǎn)動的3D盒子的效果,用于切換不同的內(nèi)容面板,是一個不錯的Flex效果,該東西是用了DistortionEffects做的,首先感謝Dreamer介紹了DistortionEffects這個東東,我也是在他Blog里看到,之后用來做點東西試試的。以下是Dreamer里的一編文章:[url=http://www.zhuoqun.net/html/y2007/492.html]DistortionEffects[/url]
其實這個很簡單,只是使用了DistortionEffects里面的CubeRotate效果,很炫的效果,致至該效果的實現(xiàn),還有待看看它的源碼進(jìn)行研究研究!
以下放出我的該小Flex的源碼:
[mDown=attachments/month_0712/j20071225181513.rar]點擊下載此文件[/mDown]
posted @
2008-07-29 14:13 姜大叔 閱讀(6538) |
評論 (48) |
編輯 收藏
本篇接著上一篇文章,上篇文章中,大家都看到最終效果了,這個例子很簡單,我就粗略的講解一下代碼吧
整個Flex程序,就兩個Panel面板,將控件都排放好到Panel里面,之后定好相應(yīng)的屬性,我主要解析一下下面的代碼:
1 <mx:Script>
2 <![CDATA[
3 //導(dǎo)入需要用到的類
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控件自動調(diào)用的,是用于當(dāng)圖表要顯示Label時,將會調(diào)用該方法,并傳上相應(yīng)的參數(shù),這樣,你就可以在該方法里自已處理好要顯示的數(shù)據(jù),再返回給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 //該方法是當(dāng)點擊“確定”按鈕時調(diào)用的,用于改變圖表數(shù)據(jù)的ArrayCollection里的數(shù)據(jù),再更新圖表顯示
25 private function changeData(ent:Event):void{
26 //定一個臨時的集合用于放置數(shù)據(jù)
27 var temp:ArrayCollection = new ArrayCollection();
28 //判斷用戶所填的數(shù)據(jù)是否為空,如果為空的就不要加進(jìn)集合里了,免得圖表出現(xiàn)一些無謂的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 //這里是截圖的方法函數(shù),參照于國外某高手地Flex截圖方面的代碼
56 private function catchPic(ent:Event):void{
57 //根據(jù)要截圖的Panel的大小建立一個放置位圖數(shù)據(jù)的BitmapData對象
58 var bitmapData:BitmapData = new BitmapData(panel1.width,panel1.height,true,0xffffff);
59 //用現(xiàn)時panel1對象的位圖信息填充到bitmapData對象中
60 //由于每一個DisplayObject對象都有自已的用于顯示的位圖色彩信息,
61 //所以很多繼承了DisplayObject的類都可以填充到bitmapData對象中處理,如模糊處理等
62 bitmapData.draw(panel1);
63 //用PNGEncoder類對位圖信息進(jìn)行壓縮轉(zhuǎn)換處理才得以輸出PNG圖片格式數(shù)據(jù)
64 var bytes:ByteArray = PNGEncoder.encode(bitmapData);
65 //再將數(shù)據(jù)進(jìn)行編碼,用于在JavaScript中向瀏覽器傳播
66 //最后調(diào)用JavaScript來打開新窗口來顯示圖借數(shù)據(jù)
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方面要寫上以下函數(shù):
1 function showPic(img,width,height){
2 window.open("data:image/png;base64," + img,"","width="+width+",height="+height+",resizable=1");
3 }
以上有幾點應(yīng)該要注意:
注意PieChart的dataProvider的寫法,也就是ArrayCollection的寫法,這與很多控件的dataProvider的都一樣,比如DataGrid控件。
注意,PNGEncoder類不是Flex原本自帶的,是要另外自已下載的擴(kuò)展包,在com.adobe.images里面,是Adobe發(fā)布的核心擴(kuò)展類庫,更多的類庫,大家可以在網(wǎng)上找找。
以下放出完整的源代碼:[down=attachments/month_0710/92007102323188.rar]點擊下載此文件[/down]
posted @
2008-07-29 14:10 姜大叔 閱讀(2773) |
評論 (4) |
編輯 收藏
應(yīng)朋友要求,做一個數(shù)據(jù)圖表的東西,主要是用于將數(shù)據(jù)以圖表的方式表示,以不至于用Excel看一大表格,里面密密麻麻的數(shù)字,所以,第一時間想到用Flex Chart玩玩,由于原本已有點Flex基礎(chǔ),So,F(xiàn)lex Chart也不是太難,而且效果滿意漂亮,也就當(dāng)作開拓該方面技術(shù)的練手之作吧,程序很簡單,就在一邊輸入數(shù)據(jù),另一邊則顯示該數(shù)據(jù)所表示的餅圖圖形,后來并加上了“生成圖片”按鈕,該功能是參照外國某位牛人所做的,不過就是該功能只支持FireFox。
[url=jiang/catch_chart/chart.html]可以去這里看看效果[/url]
待會我整理好源代碼,再放出源代碼,并解析一下該程序。
posted @
2008-07-29 14:08 姜大叔 閱讀(2301) |
評論 (0) |
編輯 收藏
這幾天無聊著,打開163郵箱,看到右上角的天氣信息,突然心血來潮,自已也做個天氣信息的小模塊放在Blog上,就是左邊側(cè)欄的那個,其實之前都做過,只不過是用Java來解析,F(xiàn)lex來顯示,而已之前的那個是解析www.weathercn.com的信息的,但現(xiàn)在該站的天氣頁面改版了,所以不得不重新做,既然如此,就拿163的來做吧。原理都是一樣,用PHP讀取163的天氣信息網(wǎng)頁,再用正則表達(dá)式解析網(wǎng)頁的內(nèi)容,提取有用的天氣信息,組織好成XML格式,之后Flex用WebService來讀取該PHP,得到XML數(shù)據(jù),再相應(yīng)的顯示。
其實這并不難,打開的我163郵箱,查看它的網(wǎng)頁源碼,經(jīng)過一番的查找分析,找到它獲取天氣信息的網(wǎng)頁:http://mimg.163.com/tianqi/city/59287.html 呵呵,還是Html的哦,網(wǎng)易的將動態(tài)的天氣生成靜態(tài)的頁面,我們訪問起來,也不太占服務(wù)器資源吧,因為天氣也是經(jīng)常訪問的。看看源代碼,就幾行Html代碼,正合我的需求,免得我的PHP分析大量的代碼占點資源。不過有點要注意,網(wǎng)易把每個城市的代號生成一個頁面,即是一個城市,一個天氣頁面,上面那個URL是廣州的,就是說 59287 就是廣州的城市代碼,在PHP里訪問時,要跟據(jù)用戶選的是哪個城市,相對應(yīng)的修改那個號碼就行了,如:
$url = "http://mimg.163.com/tianqi/city/".$_GET['city'].".html";
這樣,你訪問PHP時,要傳一個城市代碼參數(shù),至于網(wǎng)易定義的城市代碼,我這里就不列出來了,太多太長了,也找了我不少時間。我放在Flex的源碼里,可以下載我的源碼看看。
以下是PHP頁面的代碼:
1 <?php
2 include("class.Chinese.php"); #導(dǎo)入字符集轉(zhuǎn)換的類
3 $codeTableDir = "./config/"; #指定字符碼表的路徑
4
5 $url = "http://mimg.163.com/tianqi/city/".$_GET['city'].".html"; #獲取城市代碼,組成完整的URL
6
7 $fh = fopen($url,'r'); #讀取該URL獲取內(nèi)容
8 while(!feof($fh)){
9 $content .= fread($fh,128); #讀取全部內(nèi)容
10 }
11 $content = new Chinese("GB2312","UTF8",$content,$codeTableDir); #轉(zhuǎn)換字符碼,GB轉(zhuǎn)UTF8
12 $content = $content->ConvertIT(); #轉(zhuǎn)換
13 eregi('(<span class="wetCityName">)([^/]*)(</span>)',$content,$arr); #找出表示城市的內(nèi)容
14 $city = $arr[2];
15
16 eregi('(<span class="wetDate">)(.*)(</span></div>)',$content,$arr); #找出表示日期的內(nèi)容
17 $date = $arr[2];
18
19 $wea = split('txtAlgCen fRig handle',$content); #分開今天與明天
20
21 eregi('(<div class="wetSts">)([^<]*)(</div>)',$wea[0],$arr); #找出表示今日天氣的內(nèi)容
22 $info1 = $arr[2];
23 eregi('(<div class="wetSts">)([^<]*)(</div>)',$wea[1],$arr); #找出表示明日天氣的內(nèi)容 下同
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。由于網(wǎng)易里的網(wǎng)頁是用GB2312編碼的,而Flex里接收的XML要UTF-8編碼才會正確讀出,所以要將獲取的網(wǎng)易里的數(shù)據(jù)進(jìn)行轉(zhuǎn)碼,這問題剛開始時,老是亂碼,搞到心煩,后來發(fā)現(xiàn)網(wǎng)易的Html的頭信息里 發(fā)現(xiàn)是GB2312的編碼,郁悶了半天,之后上網(wǎng)找了個中文轉(zhuǎn)碼的類,下載來直接套用。
2。獲取回來的天氣信息的Html是分今天與明天的天氣信息,而里面的格式也是一樣的,所以,用正則查找時,只找到最先的那個,所以要先找個今天與明天的分界點,將其分離開來再各自解析里面的內(nèi)容,得出今天的天氣與明天的天氣。
3。寫輸出XML時,格式要正確,不然Flex里讀取會有麻煩,還有,encoding一定要是UTF-8,還要將該PHP文件保存成UTF-8格式,我用DW寫該PHP時,因為我的DW新建文件時,默認(rèn)是ISO8859-1的,所以要將其文檔編碼格式改為UTF-8來保存。
PHP完工之后,來到Flex這邊,畫好界面,添加代碼如下:
先加一個HttpService標(biāo)簽 :
<mx:HTTPService id="hs" showBusyCursor="true" method="GET" result="{hsResult(event);}" fault="{hsFault(event);}" />
(事件響應(yīng)方法我就不在這里貼出來了,可下載源碼看)
當(dāng)下拉選框選中城市之后,判斷用戶選中的是哪個城市,再對照該城市的代號,組合成URL
hs.url = "http://www.jiangzone.com.cn/jiang/weather/weather.php?city=" + cityvalues[i];
hs.send();
結(jié)果返回時,再相應(yīng)的賦值:
lblCity.text = event.result.weather.city;
lblDate.text = event.result.weather.date;
lblWea.text = event.result.weather.today.wea;
weather對應(yīng)XML里的<weather>根標(biāo)簽,city對應(yīng)XML里的<city>標(biāo)簽。
OK,修改一下,大功告成!
以下是源碼:
[down=attachments/month_0709/t2007916122822.rar]點擊下載此文件[/down]
posted @
2008-07-29 14:07 姜大叔 閱讀(1221) |
評論 (1) |
編輯 收藏
adobe的一些as3類庫提供給google code(http://actionscript3libraries.riaforge.org/)可以隨意下載...
其中的as3corelib里面包含image的png和jpg類和json(序列化數(shù)據(jù))類包.
同時amfphp1.9beta的發(fā)布可以讓你用remoting來傳遞amf3格式的數(shù)據(jù).
那么有了這兩個條件我們就可以用他們來直接生成png和jpg格式的圖片...
使用方法也是比較簡單,使用前面我提供的方法可以很方便的實現(xiàn)...
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 姜大叔 閱讀(246) |
評論 (0) |
編輯 收藏
在關(guān)系數(shù)據(jù)庫應(yīng)用中,都離不開表與表的關(guān)聯(lián),表與表之間建立了關(guān)聯(lián)關(guān)系后就可以提供很多方便的操作了,比如我要查詢一個學(xué)生的信息,如果不建立學(xué)生與班級的關(guān)系的話,那么,只可以顯示出學(xué)生的基本信息,而學(xué)生是屬于某一個班級的,我現(xiàn)在想知道這個學(xué)生的信息與該學(xué)生所在的班級的信息,甚至是該學(xué)生的任課老師等信息,建立了學(xué)生表,與班級表,老師表之間的關(guān)系就方便好多了,用一個學(xué)生ID就可以查找出所有相關(guān)聯(lián)的數(shù)據(jù)。
在FleaPHP中,支持以下四種關(guān)聯(lián)關(guān)系:
* HAS_ONE
* HAS_MANY
* MANY_TO_MANY
* BELONGS_TO
分別對應(yīng)FLEA_Db_TableDataGateway表中的 $hasOne,$hasMany,$manyToMany,$belongsTo 屬性
我們下面就用 老師,學(xué)生,學(xué)生檔案,班級的例子說說這幾個關(guān)系。
以下是SQL代碼:
1 //學(xué)生表
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 //學(xué)生檔案表
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 //由于教師與班級是多對多關(guān)系,所有建立一個中間連接表以表示該關(guān)聯(lián)
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 )
現(xiàn)在,建好表之后,我們還要寫幾個繼承自FLEA_Db_TableDataGateway父類的類,以對應(yīng)數(shù)據(jù)庫中的Student,Teacher,Classes表(連接表不用了)如下:
1 //學(xué)生表對應(yīng)的類
2 class Model_Student extends FLEA_Db_TableDataGateway{
3 var $tableName = 'student';
4 var $primaryKey = 'stu_id';
5
6 /*
7 這是一對一關(guān)系,一個學(xué)生對應(yīng)唯一的一個Record檔案
8 tableClass 對應(yīng)要與之關(guān)聯(lián)一對一的表的對象類,即檔案表的類
9 foreignKey是在檔案表中,對應(yīng)學(xué)生表的一個外鍵接連字段,
10 用該字段標(biāo)識該檔案屬于哪個學(xué)生
11 mappingName 就是用于在你查詢學(xué)生信息時,學(xué)生檔案字段的別名
12 */
13 var $hasOne = array(
14 'tableClass' => 'Model_Record',
15 'foreignKey' => 'stu_id',
16 'mappingName' => 'record'
17 );
18 /*
19 這是從屬關(guān)系,一個學(xué)生屬于某一個班級,換過來說就是班級與學(xué)生一對多,
20 一個班級有多個學(xué)生,而學(xué)生就只屬于一個班級
21 tableClass 指定該類要與之有從屬關(guān)系的類,這里是班級類
22 foreignKey 這里指定的是該表里的連接外表的字段,這里是學(xué)生表的班級ID字段
23 注意:這里的foreignKey指的是本表的字段,而上面hasOne關(guān)系中的foreignKey
24 指的是外表中的字段,要注意區(qū)分清楚
25 mappingName這里就不多說了,跟上面的一樣,也是用于顯示區(qū)分的別名
26 */
27 var $belongsTo = array(
28 array(
29 'tableClass' => 'Model_Classes',
30 'foreignKey' => 'stu_class_id',
31 'mappingName' => 'class'
32 )
33 );
34 }
35
36 //檔案表對應(yīng)的類
37 class Model_Record extends FLEA_Db_TableDataGateway{
38 var $tableName = 'stu_record';
39 var $primaryKey = 'record_id';
40 }
41
42 //教師表對應(yīng)的類
43 class Model_Teacher extends FLEA_Db_TableDataGateway{
44 var $tableName = 'teacher';
45 var $primaryKey = 'teacher_id';
46
47 /*
48 這里確立了教師與班級的多對多關(guān)系,一個教師可以教多個班級
49 而一個班級也有多個教師
50 tableClass 指定要建立多對多關(guān)系的表的類
51 joinTable 這個屬性要注意一個,這個是指定教師表與班級表關(guān)系的連接表
52 由于二維表的數(shù)據(jù)結(jié)構(gòu)的原因,所以多對多關(guān)系要用一個中間表(即連接表)來表示
53 連接表中就指明兩個表各自的主鍵ID就可以了,以兩個字段作復(fù)合主鍵,如不用復(fù)合
54 主鍵,就新增加一個字段作主鍵也可,這沒關(guān)系
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 這里確立了班級與學(xué)生的一對多關(guān)系
71 tableClass 指定該表的類要與哪個表的類建立一對多關(guān)系
72 foreignKey 外鍵ID,這里即指定學(xué)生表中定義的班級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 // 由于多對多關(guān)系是雙向的,所以班級表也可以定義上與教師表的多對多關(guān)系
84 // 也可以不寫,看需求而定,比如你想查看某個班級信息時,一并顯示該班
85 // 有多少個任課老師的話,那就在這個班級類里加上關(guān)系,我這里就不寫了。。。
86 );
87 }
以上的代碼就建立好了關(guān)系了,現(xiàn)在只管使用就是了。
不過還提醒大家一點,在每個關(guān)系里,都有一個 ‘enabled’ 的屬性,如果設(shè)置為 false的話,則是將該關(guān)系禁掉,所以查詢出來的結(jié)果就沒有該關(guān)系的相應(yīng)數(shù)據(jù),這樣可以節(jié)省效率,按需要時才打開相應(yīng)的關(guān)聯(lián),該屬性默認(rèn)為true 可以如下設(shè)置:
1 array(
2 'tableClass' => 'Model_Student',
3 'foreignKey' => 'stu_class_id',
4 'mappingName' => 'students',
5 ‘enabled’ => false
6 )
現(xiàn)在我們來測試一下數(shù)據(jù)。(事先自行插入幾行數(shù)據(jù)用以測試)
1 $classManager = FLEA::getSingleton('Model_Classes');
2 $class =& $classManager->find(array('class_id' => 1));
3 dump($class);
出現(xiàn)結(jié)果如下:
這個例子已含蓋了這四個關(guān)聯(lián)關(guān)系的基本用法了,其它的就由你們來探索了,不久后,我將會發(fā)表一下這此關(guān)聯(lián)方面的高級應(yīng)用,有時間的話會寫寫這方面的東西。敬請期待!
posted @
2008-07-29 14:02 姜大叔 閱讀(328) |
評論 (0) |
編輯 收藏
這篇文章是接著上一篇,在上一篇的基礎(chǔ)上加了用戶注冊功能,注冊成功后顯示用戶信息,由于時間關(guān)系,沒有詳細(xì)研究實現(xiàn)什么功能例子用于教學(xué),本來我也只是FleaPHP初學(xué)者,所以,雖然例子十分的傻瓜式簡單,但就當(dāng)是我在學(xué)FleaPHP時的快速練習(xí)吧。
這里只實現(xiàn)了個注冊功能,有經(jīng)驗的應(yīng)該閉上眼睛都能做出來了,所以我這里的只是演示一下FleaPHP的大概操作流程的,也就是它的結(jié)構(gòu)都是差不多,我在之前第一篇的那個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與一個方法函數(shù):
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 = '出現(xiàn)錯誤,注冊失敗!';
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 }
這都很直觀了,大家注意的是流程的控制與轉(zhuǎn)移,如果是開發(fā)小項目的話,這可能還會覺得麻煩,但當(dāng)項目稍大時,程序結(jié)構(gòu)將會很直觀,控制流程很清淅。
之后在View文件夾里加了register.php error.php等View文件,也主要是Html的,應(yīng)盡量把邏輯代碼與UI代碼分開,這里只是初入門篇,遲點將會介紹與Smarty模板技術(shù)結(jié)合使用的文章。
最終源碼下載:[down=attachments/month_0710/k20071016235619.rar]點擊下載此文件[/down]
posted @
2008-07-29 13:58 姜大叔 閱讀(228) |
評論 (0) |
編輯 收藏
由于忙,很少時間學(xué)學(xué) FleaPHP 框架,不過之前也看了看學(xué)了點東西,感覺FleaPHP框架還是很不錯的,有良好的MVC模式結(jié)構(gòu),比較方便的數(shù)據(jù)庫操作,好東西不敢獨享,所以獻(xiàn)上我在學(xué)習(xí)FleaPHP中的一點小心得,適合初接觸 FleaPHP 框架的同學(xué),PHP基礎(chǔ)不太好的話,建議先補習(xí)一下PHP再看看這系列的文章。
本例子是我剛學(xué)FleaPHP框架時的小練習(xí),一步一步循序漸進(jìn),剛開始的例子顯得比較簡單,都只是熟習(xí)他的環(huán)境而已,不過我將采用增量開發(fā)的模式,慢慢完善深入,同學(xué)們記得專心上堂哦,做好功課哦。(文章的末尾將提供完整源代碼打包,由于篇幅有限,所以文章中貼出來的代碼有的只是片段)
這篇是我寫 FleaPHP 學(xué)習(xí)筆記的開篇,做的是一個簡單的登錄功能,牛刀小試吧,認(rèn)大家認(rèn)識一下 FleaPHP 的MVC結(jié)構(gòu)與基本數(shù)據(jù)庫操作,如果是對 FleaPHP 還不知道是什么東西的話,可以到以下網(wǎng)站了解了解。
fleaphp.org
數(shù)據(jù)庫準(zhǔn)備:數(shù)據(jù)庫里就只有一個表 tb_user 里面有三個字段,id ,name ,password 夠簡單吧[smile]
我的這個FleaPHP應(yīng)用的目錄結(jié)構(gòu)如下:
圖中可以看到就一個index.php主頁文件,一個app與一個FLEA文件夾,因為FleaPHP是采用單一入口框架,所以就只有一個index.php文件,所以的請求都經(jīng)由這個文件再進(jìn)行分類分發(fā),這樣可以提高代碼的安全性,可以將程序其它文件放置到URL訪問不到的地方,在index.php里引用該路徑就可以了。不過有點要注意的是文件的路徑的正確性。
app文件夾就是我的程序代碼放置的地方,里面有Controller,Model,View,Table文件夾,Controller文件夾都是FleaPHP的命名約定的,最好使用這樣的命名,因為會跟據(jù)請求到該文件夾中找相對應(yīng)的類文件的,好,我們先來看看index.php的代碼:
1 <?php
2 require("./FLEA/FLEA.php");
3 FLEA::import(dirname(__FILE__)."/app");
4
5 // 準(zhǔn)備數(shù)據(jù)庫連接信息
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"); 就是要先導(dǎo)入FleaPHP的核心引擎,所以之前大家看到了有個FLEA文件夾,就是FLEA的核心引擎啦,這個大家先不用管它,等到要研究他的源代碼時再看吧,平時的使用就看看提供的API文檔就夠了。
同學(xué)們注意了,F(xiàn)LEA::import(dirname(__FILE__)."/app"); 這句的作用是什么?這個import函數(shù)是FLEA的靜態(tài)函數(shù),用于將你的程序文件夾導(dǎo)入進(jìn)來,如果有玩過Java的同學(xué)應(yīng)該知道多少吧,當(dāng)FleaPHP接收到一個請求時,會分析URL再調(diào)用相對的Controller和Action,
如:http://localhost/fleatest/index.php?controller=Shop&action=checkout 這里即調(diào)用Shop控制器里面的checkout動作,而FleaPHP怎么知道我的控制器代碼放在哪里呢?就是靠import這個語句了,將程序文件夾導(dǎo)入進(jìn)來之后,F(xiàn)leaPHP會自去到這個文件夾里找Controller文件夾再找Shop.php這個類文件,所以,如果你為了安全起見,將程序文件夾放在了其它訪問不到的地方,就得靠這個import來導(dǎo)入,以FleaPHP能正確找到所需要的Controller。(可能說得啰嗦了[redface],打字累了,燒根煙先,同學(xué)們小息片刻!)
接下來$dsn這個數(shù)組就是存放你連接數(shù)據(jù)庫的信息啦,聰明的同學(xué)一眼看出來了。之后當(dāng)然要設(shè)置入FleaPHP配置里面啦,用這個set_app_inf('dbDSN',$dsn);,之后,F(xiàn)LEA::runMVC(); 這個就是啟動了。我們輸入的URL是 http://localhost/fleatest/index.php,由于FleaPHP默認(rèn)的Controller是Default,默認(rèn)的Action是Index,所以,這時,F(xiàn)leaPHP就會跳到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 //新建一個對應(yīng)user數(shù)據(jù)表操作的Model對象
11 $mod_user = new Model_User;
12 //根據(jù)用戶輸入的用戶名查找數(shù)據(jù)庫有沒有存在
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的命名規(guī)則,大家可以去官網(wǎng)看看它的命名規(guī)則,這里就不多啰嗦了。現(xiàn)在,它將會調(diào)用actionIndex的默認(rèn)action函數(shù),里面只引入了一個php文件,那就是登錄界面的頁面。
在登錄界面的Form里,設(shè)置好action提交路徑,使它提交到Default控制器的Login動作(action),里面實例化了一個Model對象,該對象是封裝了對表tb_user的操作,之后程序邏輯就是跟據(jù)登錄成功與否來進(jìn)行相應(yīng)的信息表示啦,簡單的實現(xiàn)了從Controller -> Model -> View 的MVC訪問操作流程。
大概的結(jié)構(gòu)就這么簡單了。
最后符上源代碼:[down=attachments/month_0710/520071010232245.rar]點擊下載此文件[/down]
大家如果有什么疑問,可以留言或發(fā)到我郵箱里!
posted @
2008-07-29 13:57 姜大叔 閱讀(353) |
評論 (1) |
編輯 收藏
緩存
功能強大的應(yīng)用程序一般都有很大的開銷,通常是數(shù)據(jù)獲取和處理操作帶來的。對于Web應(yīng)用程序,這個問題是由于HTTP協(xié)議的無狀態(tài)性造成的。由于HTTP協(xié)議是無狀態(tài)的,對于每個頁面請求,都要重復(fù)地執(zhí)行相同的操作,而不論數(shù)據(jù)是否修改。要讓應(yīng)用程序在世界范圍最大的網(wǎng)絡(luò)中可用,會使這個問題進(jìn)一步惡化。所以,毫不奇怪,人們總在想方設(shè)法地讓W(xué)eb應(yīng)用程序運行得更高效。對此有一種特別有效的解決方案,這也是最合理的方案之一:將動態(tài)頁面轉(zhuǎn)換成靜態(tài)頁面,只有在頁面內(nèi)容有修改之后才重新構(gòu)建,或者定期地重新構(gòu)建。Smarty提供了這樣一個特性,一般稱為頁面緩存。
如果要使用緩存,需要首先通過設(shè)置Smarty 的緩存屬性來啟用緩存,如下:
1 <?php
2 require("Smarty.class.php");
3 $smarty = new Smarty;
4 $smarty->caching = 1;
5 $smarty->display("news.tpl");
6 ?>
啟用緩存后,調(diào)用 display() 和 fetch() 方法在指定模板 (由$cache_dir 屬性指定) 中保存目標(biāo)模板的內(nèi)容。
處理緩存生命期
緩存的頁面在由 $cache_lifetime 屬性指定的生命期(以秒為單位)內(nèi)有效,默認(rèn)為3600秒,即1小時。因此,如果希望修改此設(shè)置,就可以設(shè)置這個屬性,如下:
1 <?php
2 require("Smarty.class.php");
3 $smarty = new Smarty;
4 $smarty->caching = 1;
5 //設(shè)置生命周期
6 $smarty->cache_lifetime = 1800;
7 $smarty->display("news.tpl");
8 ?>
在此對象的生命期內(nèi),后續(xù)調(diào)用和緩存的模板都使用此生命期。
有可能需要覆蓋以前設(shè)置的緩存生命期,從而能分別控制每個模板的緩存生命期。通過將$caching 屬性設(shè)置為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 模板的生命期設(shè)置為20分鐘,它覆蓋了前面設(shè)置的全局生命期值。
通過 is_cached( ) 消除處理開銷
如前面所述,緩存模板還能消除處理開銷,如果禁用緩存(只啟用編譯),這些處理開銷總是會發(fā)生。但是,默認(rèn)情況下并沒有啟用緩存。要啟用緩存,需要把處理指令放在 if 條件中,并執(zhí)行 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是否有效。如果有效,則跳過數(shù)據(jù)庫訪問,否則才訪問數(shù)據(jù)庫。
為每個模板創(chuàng)建多個緩存
任何指定的Smarty模板都可以用于為整個新聞項,博客項等提供一個通用界面。由于同一個模板用來生成不同數(shù)量的不同項,那么如何緩存一個模板的多個實例呢?答案比你想像的要簡單。Smarty的開發(fā)人員實際不已經(jīng)解決了這個問題,可以通過display()方法為緩存模板的每個實例指派一個唯一標(biāo)識符。例如,假設(shè)有一個用生成用戶信息的模板,并希望緩存這個模板的各個實例:
1 <?php
2 require("Smarty.class.php");
3 require("User.class.php");
4
5 $smarty = new Smarty;
6 $smarty->caching = 1;
7
8 //根據(jù)不同的用戶ID來區(qū)分不同的用戶實例來判斷有沒有被緩存
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 當(dāng)顯示時也根據(jù)該用戶的ID來區(qū)分將哪個實例進(jìn)行緩存,而不影響其它用戶的緩存
18 即是用userid 值來區(qū)分同一個緩存模板的不同實例,所有用戶都共用一個模板,
19 但信息都不盡相同,所以不能統(tǒng)一緩存,要獨立分開緩存
20 */
21 $smarty->display("userinfo.tpl",$_GEG['userid']);
22 ?>
特別注意下面一行:
$smarty->display("userinfo.tpl",$_GEG['userid']);
這一行對于此腳本有兩個功能,一方面獲取名為$_GET['userinfo'] 的 userinfo.tpl 緩存版本,另一方面,如果還不存在這個緩存,則用這個名字來緩存該模板實例。采用這種方式,可以輕松地為指定模板緩存任意數(shù)量的實例。
關(guān)于緩存的結(jié)語
模板緩存大大提升了應(yīng)用程序的性能,如果決定將Smarty集成到工程中來,就應(yīng)當(dāng)認(rèn)真地考慮緩存。但是,因為大多數(shù)強大的Web應(yīng)用程序功能都體現(xiàn)在其動態(tài)性上,所以一方面要考慮到性能提升,另一方面也要考慮到緩存頁面隨時間是否仍有效,要在這二者之間進(jìn)行權(quán)衡。
posted @
2008-07-29 13:55 姜大叔 閱讀(220) |
評論 (0) |
編輯 收藏