发现一篇好文,介绍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 姜大叔 阅读(308) |
评论 (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 姜大叔 阅读(6529) |
评论 (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 姜大叔 阅读(2766) |
评论 (4) |
编辑 收藏
应朋友要求,做一个数据图表的东西,主要是用于将数据以图表的方式表示,以不至于用Excel看一大表格,里面密密麻麻的数字,所以,第一时间想到用Flex Chart玩玩,由于原本已有点Flex基础,So,Flex Chart也不是太难,而且效果满意漂亮,也就当作开拓该方面技术的练手之作吧,程序很简单,就在一边输入数据,另一边则显示该数据所表示的饼图图形,后来并加上了“生成图片”按钮,该功能是参照外国某位牛人所做的,不过就是该功能只支持FireFox。
[url=jiang/catch_chart/chart.html]可以去这里看看效果[/url]
待会我整理好源代码,再放出源代码,并解析一下该程序。
posted @
2008-07-29 14:08 姜大叔 阅读(2294) |
评论 (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 姜大叔 阅读(1215) |
评论 (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 姜大叔 阅读(242) |
评论 (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 姜大叔 阅读(320) |
评论 (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 姜大叔 阅读(221) |
评论 (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 姜大叔 阅读(348) |
评论 (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 姜大叔 阅读(215) |
评论 (0) |
编辑 收藏