随笔-31  评论-257  文章-0  trackbacks-0
 
发现一篇好文,介绍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 姜大叔 阅读(299) | 评论 (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 姜大叔 阅读(6508) | 评论 (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 姜大叔 阅读(2749) | 评论 (4)编辑 收藏
      应朋友要求,做一个数据图表的东西,主要是用于将数据以图表的方式表示,以不至于用Excel看一大表格,里面密密麻麻的数字,所以,第一时间想到用Flex Chart玩玩,由于原本已有点Flex基础,So,Flex Chart也不是太难,而且效果满意漂亮,也就当作开拓该方面技术的练手之作吧,程序很简单,就在一边输入数据,另一边则显示该数据所表示的饼图图形,后来并加上了“生成图片”按钮,该功能是参照外国某位牛人所做的,不过就是该功能只支持FireFox。



[url=jiang/catch_chart/chart.html]可以去这里看看效果[/url]

待会我整理好源代码,再放出源代码,并解析一下该程序。


posted @ 2008-07-29 14:08 姜大叔 阅读(2281) | 评论 (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 姜大叔 阅读(1200) | 评论 (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 姜大叔 阅读(233) | 评论 (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(20NOT 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(150NULL,
14   `family_tel` VARCHAR(20NULL,
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(20NOT 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(20NOT 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 姜大叔 阅读(310) | 评论 (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 姜大叔 阅读(210) | 评论 (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 姜大叔 阅读(338) | 评论 (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 姜大叔 阅读(206) | 评论 (0)编辑 收藏
仅列出标题
共4页: 上一页 1 2 3 4 下一页