打印

[翻译]PHP与FLASH之间的交互!

================================================
英文原地址:http://www.macromedia.com/desdev/mx/flash/articles/flashmx_php.html

本文版权属于Macromedia.com的FlashMX Application Development Center所有。

本文著作权属于Helen Triolo( actionscript-toolbox.com)所有,非经作者同意,不得随意传播用于商业目的。


本文中文翻译权属于蓝色未来(http://www.21blue.com),非经本人同意,不得随意传播用于商业目的。
================================================
本人第一次翻译此类的英文文档,再加上时间仓促,不妥之处也总是在所难免,希望大家指正。这里也有中英文的对照文档(http://asp3.6to23.com/chaoyuebetter/article/php_flash/flash_php.htm)不通之处,大家可以对照阅读。
================================================

随着flashMX中LoadVars对象的引入,php(包括任何其他的服务器端的编程语言)和flash之间的交互变得更加的容易了。用一个示例就可以让你真切地感受到,在做这些事情的时候,由于简单而带给你的乐趣。我用MySQL作为数据库(主要包括我朋友的email、电话及照片等信息,当然如果有的话,我们会加上他们的说明),用php去访问这个数据库,而用flash去展示结果。看,各司其职,多么奇妙的组合!然后我将详细地描述我曾经作出的每一个步骤。
一个动态的地址簿
在我们开始建立地址簿之前,请先尝试点击下面你所看到的A、B、C标签,以便明白对所请求的信息是如何被显示在主窗口中的。
*****************************************************************
这里应该是可以演示的最后效果窗口,由于本人没有可以执行PHP脚本的空间,所以大家可以到上面提到的原英文文档(Click to Left)上去察看最后的效果。
*****************************************************************
===================================================

示例文件
在你开始之前,请先下载这个教程中的原文件。

Windows source files fmx_loadvars.zip (27 KB)

===================================================
首先建立MySQL数据库,以便php脚本可以访问到.
在建立任何的数据库程序之前,第一件必须要做的事情就是去定义你的数据结构。在这个例子中,我建立了新的MySQL表,包括以下的字段:

[LIST]contact ID, smallint, primary key, auto_increment
lastName, tinytext
firstName, tinytext
phone, tinytext
email, tinytext
picFile, tinytext
caption, tinytext [/LIST]
然后,可以用下面的表达式手工将字段记录加入:
复制内容到剪贴板
代码:
insert into contacts
values (NULL, 'Anderson', 'Lois', '301-424-5555',
'lois@yahoo.com', 'lois.jpg', 'Lois, 2001');
由于这个表是一个比较小的表,可以用上面的方法;对一个交大型的表,将应该费一些心思,通过读入纪录着你需要的信息的文本文件,可以大大减少你将数据移入表中的时间。

为了确认,你创建的表是可以通过php访问得到的,我用下面的代码先去测试一下:
复制内容到剪贴板
代码:
<?php
mysql_connect("servername","username","password");
mysql_select_db("databasename");
$qr = mysql_query("SELECT * FROM contacts");
$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
$row = mysql_fetch_array($qr);
echo $row['lastName'].", ".$row['firstName']."<br>";
echo " ".$row['phone']." ".$row['email']."<Br>";
echo " ".$row['picFile'].": ".$row['caption']."<Br><Br>";
}
?>
本帖最近评分记录
创建flash电影
为了可以在你的flash中显示文本,可能需要建立一个或者多个文本域(Text Field).你可以通过使用creatTextField动态地创建一个,或者在电影里创建文本域,然后给它一个实例名,就可以调用这个实例了.我选择的是后面的那种办法.我把主文字窗口的实例名定为"content"(你可以在我提供的fla的"text field & scrollbar中发现它),将它的属性设定为"multiline",同时也要把"Render text as HTML"勾选上,以便你可以在文本中设定链接.

增加一个滚动条
因为你将要把所有的地址纪录按照那个小册子里给定的顺序放进你的文本域里,所以你必须要设定一个滚动条以便于那些较多的项目可以适合你给你的文本域所规定的尺寸.要做到这个,在flashMX中真的太简单的事情了.首先打开组件面板,拖一个scrollbar的备份到你的文本域.它将自动吸附到文本域的位置,并且自动地和"content"实例想连接.呵呵,美妙的体验.

建立一个MoviClip去放置JPEG图片
在这个电影中,你需要做的另外的一件事情就是放置那些你将要的载入的图片了.要作到这些,首先创建一个mc容器(位于我提供的原文件"pic,caption"层中),然后给这个mc一个实例名"picHolder".同样在该层里,新创建一个文本域(属性值仍旧为"multiline",但是HTML不再需要了),并将该文本域赋予实例名为"caption".

创建按钮标签
由于所有的标签除外观上稍有不同.之外,而功能基本上完全一样,所以你可以用那个在flashMX中所特有的button movie clip特征去创建它们.也就是说,你将用movie clip创建一个模板标签,然后你就可以复制尽可能多的你需要的标签了.然后,加入右边的字母标签所要执行的代码,同时给该标签加上对鼠标事件的监听,以便可以去相应用户的鼠标点击动作.

每一个按钮剪辑(tab movie clip)都包括着一个文本域"letter".每一个电影剪辑在被点击后,也都有一个被指定的相关onRelease功能.以便于完成你所要求的动作,当然,你也需要知道,你正在被访问的到底是哪一个标签剪辑.要想做到这个,首先应该按照一定的方式命名你的电影剪辑,以便于可以方便地知道当前正在被点击的是哪一个标签剪辑.比如,A标签被命名为"theA",B标签被命名为"theB"等等.记牢你刚才所赋予的实例名,下面的代码(在主电影区的第1桢)可以正确地设定你的三个标签(包括当被点击的时候,可以正确地显示字母及执行正确的动作):
复制内容到剪贴板
代码:
for (var i=65; i<=67; i++) {
// display the correct letter on the tab
this["tab"+chr(i)].letter.text = chr(i);
// when this tab is clicked
this["tab"+chr(i)].onRelease = function() {
// can't use chr(i) here -- must use mc name
// because i will not be set when the event actually happens
c.thisLetter = this._name.substr(3,1);
bigLetter.text = c.thisLetter;
content.htmlText = "Loading data for " + c.thisLetter;
// scope of this function is main timeline so can refer to c directly
c.sendAndLoad("flashmx_dbPassAndReturnString.php",c,"POST");
}
}
对于A-C中的每一个字母,将被赋值被标签上的"letter"文本域;同时,也会执行下面的这些常规程序:

将与被选择的标签相关的字母 赋值给"对象c"的"thisLetter"属性,c是一个LoadVars对象,将在下面着重讨论.
显示那个被选择的字母作为一个地址簿的背景图.
告知用户当前正在从数据库中搜取信息.
启动转换器,使用LoadVars对象c去传输数据
注意,现在在主电影中,要做的事情还没有完成;当一个标签被点击的时候,他们将正在建立那些即将被执行的指令.现在你需要亲自去建立一个LoadVars对象,并且包括那些通过php得到数据后而将完成的动作.下面,我们将详细讲解怎么样可以做到这些.



LoadVars对象可以在一个服务器端的脚本(包括PHP、ASP、CF、Perl或者JSP)和flash电影之间传输数据。LoadVars对象的属性通过post或者get方式被传送到服务器端脚本.从服务器端传送的任何变量都将交给作为LoadVars对象中由load方法指定的属性。
复制内容到剪贴板
代码:
Using LoadVars.send
format = loadVarsObject.send( url, target, method ), where all are expressions
在这个例子中,你想送出你选择的字母标签 以便你可以使用php脚本去查询数据库.因此,一个LoadVars对象必须要被首先建立,并且他的一个属性必须设定给那个字母.在查阅那个例子中的代码之前,下面的例子可以教你正确地把一个值赋予已经新建立的LoadVars对象的属性,然后被传递给php脚本.
复制内容到剪贴板
代码:
var c = new LoadVars();
c.thisLetter = "A";
c.send("dbquery.php","_self","POST");
服务器端的脚本可以把传递过来的LoadVars对象的属性作为一个变量,然后可以使用这些变量去查询数据库,最后显示查询的结果.
复制内容到剪贴板
代码:
<?php
mysql_connect("servername","username","password");
mysql_select_db("dbname");
$qr = mysql_query("SELECT * FROM contacts WHERE LEFT(lastName,1) =
'".$HTTP_POST_VARS['thisLetter']."'");
// display visitors row (1)
$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
$row = mysql_fetch_array($qr);
echo $row['lastName'].", ".$row['firstName']."<br>";
echo " ".$row['phone']." ".$row['email']."<Br>";
echo " ".$row['picFile'].": ".$row['caption']."<Br><Br>";
}
?>
下面就是在输出窗口中显示的输出结果(也就是你的那个flash电影正在运行的那个窗口,因为你在LoadVars.send里指定了""_self作为目标窗口):
复制内容到剪贴板
代码:
Anderson, Lois
301-424-5555 lois@yahoo.com
lois.jpg: Lois, 2001
Armand, Cheryl and Joe
912-948-4444 armandcj@hh.com
babysue.jpg: C and J's baby Sue, 9 days old
(etc)
由于你使用Post来传递变量,因此需要使用$HTTP_POST_VARS去读取变量.如果你需要亲自建立查询字符串(有时候可能你必须这样),你可以传递变量而无须去指定方式,并且,它将以"GET"的缺省方式去传递,因为你的那些附加的字符串.
复制内容到剪贴板
代码:
var c = new LoadVars();
c.send("dbquery.php?thisLetter=A","newWindow");
下面的代码dbquery.php将在输入窗口中产生同样的结果,但是是在一个新的窗口.
复制内容到剪贴板
代码:
<?php
mysql_connect("servername","username","password");
mysql_select_db("dbname");
$qr = mysql_query("SELECT * FROM contacts
WHERE LEFT(lastName,1) = '".$HTTP_GET_VARS['thisLetter']."'");
// display visitors row (1)
$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
$row = mysql_fetch_array($qr);
echo $row['lastName'].", ".$row['firstName']."<Br>";
echo " ".$row['phone']." ".$row['email']."<Br>";
echo " ".$row['picFile'].": ".$row['caption']."<Br><Br>";
}
?>
当写一个Flash-to-server-side程序时,象上面的代码那样做一个简单的测试,将一个很好的习惯,使用.send命令可以在试图测试整个程序之前确信你所期望的变量已经被成功传递.
复制内容到剪贴板
代码:
Receiving using LoadVars.load
format = loadVarsObject.load( url ), where url is an expression
既然你已经得到从PHP脚本中传递过来的变量,而且可以成功地加以使用,然而你怎么样得到那些返回给flash的信息呢?在将传送和接收合起来讨论之前,让我们先只看使用LoadVars对象的load方法而接收到了什么。

在一个服务器端脚本送到flash的变量被传递时,总是用var=value这样的值对传递,并在值对之间用&分开。例如下面的就是一个标准的传递的变量形式:
复制内容到剪贴板
代码:
lastName=Anderson&phone=301-424-5555
如果这样的字符串通过LoadVars对象的load方法传递,那么传递过来的变量就可以被flash做为LoadVars对象正确地读取。

但是,除了上面讨论的之外,应该有更多的东西需要我们加以注意。从一个数据库得到信息及将信息传递给flash 并不是能够即可就可以完成。当对数据库的操作完成之后,才能去通知flash接收信息。因为flash不能够使用那些实际上并不存在的变量(呵呵,这是一个常识性的问题),因此我们需要去定义一个函数,利用LoadVars对象的onload属性,可以使我们的数据被返回时,该函数才被正确地执行。也就是说,应该首先确认我们需要的变量已经被传递过来时,才执行你定义的函数。现在可以用两种途径做到这些,第一个可以使用的是匿名函数(我认为也可以叫做字面意义上的函数):
复制内容到剪贴板
代码:
var c = new LoadVars();
c.onLoad = function() {
returnvals.text = "returned from php: \n\n";
for (i in this) {
returnvals.text += i + " = " + this[i] + "\n";
}
};
第二种方法是使用一个命名函数,然后将其应用到onLoad属性(同时也就不举例说了,在函数名的后面不要加“()”):
复制内容到剪贴板
代码:
function showValues() {
returnvals.text = "returned from php: \n\n";
for (i in this) {
returnvals.text += i + " = " + this[i] + "\n";
}
}
var c = new LoadVars();
c.onLoad = showValues;
无论哪种方法,注意到在函数中的"this",是对LoadVars对象的实例化的调用。
因此在上面的任意的代码的基础上, 使用下面的一行代码就可以获得所需要的数据:
复制内容到剪贴板
代码:
c.load("passvars.php");
在passvar.php的脚本中,代码如下:
复制内容到剪贴板
代码:
<?php
$lastName = "Anderson";
$phone = "301-424-5555";
echo "lastName=".$lastName."&phone=".$phone;
?>
在输出窗口的结果如下:
复制内容到剪贴板
代码:
returned from php:
phone = 301-424-5555
lastName = Anderson
onLoad = [type Function]
你想接受到的两个变量是phone和lastName。你这个实例中,onLoad也出现了,即使它不是一个变量,因为它也是LoadVars的属性之一。通常你总是在你知道了你所需要的变量后,仅仅关心的就只有这些变量,而忽略了LoadVars的任何的其他的属性。当然,在有效载入之前,你可以删除任意LoadVars对象赘余的属性(虽然onLoad 不是赘余的,而且为了使对象正常工作,onLoad是LoadVars的必须的属性)

用LoadVars.sendAndLoad使传送和接手数据一次完成
复制内容到剪贴板
代码:
format = loadVarsObject.sendAndLoad( url, loadVarsObject, method ),
where url and method are expressions and loadVarsObject is not
在这个例子中,你想通过那些被选择的字母(也就是被点击的标签),然后传递回所有通过查询得到的纪录。因此php程序必须返回类似于var=value这样的值对的字符串组合,并且flash movie也必须使用LoadVars对象的正确的属性在你的flash movie对象Scrolling text field中显示她们。

PHP脚本返回的字符串的特征就如下面所示:
复制内容到剪贴板
代码:
"n=4&lastName0=Anderson&firstName0=Lois&phone=301-424-5555&...&caption3=lastyear"
其中包括以A开头的Last Name的总共四条记录。注意到你已经在字符串的开头增加了一个变量,为告知flash已经探测到的总共的记录数,以便于你可以设置一个合适的循环去读取他们。所使用的部分PHP脚本如下所示:
复制内容到剪贴板
代码:
$nrows = mysql_num_rows($qr);
$rString = "n=".$nrows;
for ($i=0; $i < $nrows; $i++) {
$row = mysql_fetch_array($qr);
$rString .= "&lastName".$i."=".$row['lastName'].
"&firstName".$i."=".$row['firstName'];
$rString .= "&phone".$i."=".$row['phone']."&email".$i."=".$row['email'];
$rString .= "&picFile".$i."=".$row['picFile'].
"&caption".$i."=".$row['caption'];
}
echo $rString;
现在所有的为读取获取变量的代码已经完成了。现在你可能要做是定义一个函数,当变量获取到变量后,可以执行该函数(该函数的主要功用就是去读取和处理变量)。最后,加上正确的snedAndLoad命令。下面就是在Flash Movie中的代码(其中"?"表示换行Line Break)。
复制内容到剪贴板
代码:
function showContent() {
var i;
content.htmlText = "";
for (i=0; i < this.n; i++) {
if (this["picFile"+i] != "") {
content.htmlText += ?
"<b>" + this["firstName"+i] + " " + this["lastName"+i] + ?
"</b>" + "<a href='asfunction:showjpg," + this["picFile"+i] + ?
"," + escape(this["caption"+i]) + ?
"'> (<font color='#0000cc'>pic</font>)?
</a><Br>";
} else {
content.htmlText += ?
"<b>" + this["firstName"+i] + " " + this["lastName"+i] + ?
"</b><Br>";
}
content.htmlText += " " + this["phone"+i] + "<Br>";
content.htmlText += ?
" <a href='mailto:" + this["email"+i] + "'>" + ?
this["email"+i] + "</a><Br><Br>";
}
}
// Create new load vars object c for data transfer
var c = new LoadVars();
c.onLoad = showContent;
要记住应该在被选择的标签被触发了onRelease事件后,才亲自执行sendAndLoad命令。
复制内容到剪贴板
代码:
this["tab"+chr(i)].onRelease = function() {
...
c.sendAndLoad("flashmx_dbPassAndReturnString.php",c,"POST");
}
现在你已经建立起包括传递A、B、C标签对象给PHP服务器端脚本,同时处理了从PHP脚本返回的各种变量。为了搞清楚在函数showContent中的代码的意思,你必须记得下面这些形式对访问c对象的phone3属性时是等价的。
复制内容到剪贴板
代码:
c.phone3
and
c["phone"+3]
and
i=3
c["phone"+i]
and
i=3
this["phone"+i] if the code is inside a function assigned to c
(要想知道关于这方面的更多信息,可以从我的actionscript-toolbox.com站查阅 Addressing Movieclips page相关的知识,他们可以应用于所有的actionscript对象,而不仅仅是Movie Clips)

因此,你就可以简单地获得返回的每一个属性,然后按你希望的样式在你创立的文本域里显示。
复制内容到剪贴板
代码:
asfunction
format = asfunction:functionname,param where param is an expression
这个例子中还有另外的两个有趣的东西。其中一个是使用asfunction去引用在Flash中的函数;另外的一个就是将JPEG直接载入Flash中。正如你在上面的showContent函数中看到的那样,asfunction允许你在Flash的文本域中执行类似HTML中样的连接,使调用另一个FLASH函数。在本实例中,它回调showjpg函数,而且还传递了一个参数(而且仅能够传递一个),该参数包括JPEG文件的名字和说明,之间用#分割。下面就是showjpg函数的代码:
复制内容到剪贴板
代码:
function showjpg(paramString) {
// get the individual parameters:
// params[0] = picture file name
// params[1] = caption
var params = paramString.split("#");
picHolder.loadMovie(params[0]);
caption.text = unescape(params[1]);
}
对于传递回参数,首先要处理的就是将你所需要的参数用split函数分离,为产生一个两元素的数组。第一个元素保存的是JPEG的名字;另一个保存的是说明。
复制内容到剪贴板
代码:
Loading a JPEG
format = mcInstanceName.loadMovie(jpgfile) where jpgfile is an expression
picHolder.loadMovie(params[0]);
上面的代码是为了把储存在params[0]中的文件名载入picHolder电影剪辑。由于picHolder被创建在左上的点(0,0),而且你已经定义所有的图片去适合这个尺寸,因此图片可以精确地被载入右边的位置而且你没有必要再要考虑到有关更多的东西了。在载如JPEG进入你定义的容器之后,再填入传递过来的caption文本。unescape函数是用来把传递过来的文本使用非URL编码(un-URL-encode)[注意使用escape函数可以用来对传递过来的值进行URL编码,否则在说明中的比如":"","将会不正常的显示]。

总结一下所有的步骤也就是:首先使用LoadVars对象发送数据,PHP脚本获得之后,返回你所需要的数据,showContents函数用来处理从Flash电影中接收到的数据。

TOP

终于搞定,帖UBB真的好累。:)

本文暂时只在蓝色经典发,如果需要转载,请与PoPo:stuDreamer@163.com联系。

TOP

非常不错
ps:mmc文章的版权控制得非常严格
虽然有写出处,但如果没和mmc联系,最好还是不要翻译

TOP

嗯,看到她写的是比较经典的方案,所以翻译了过来。但版权是个问题,我会跟作者联系一下。

TOP

不错,打分鼓励一下。
虽然不是用于商业用途,不过还是和作者联系一下好:)
4 Elements Blogs
黑色的风略过我的翅膀,我却无法落下来梳理你的羽毛

Blueidea Web Team
Team Member

TOP

很有用呢,终于找到这方面的资料了.继续哦.

TOP

VERY VERY GOOD!!!!!!!
下次讲讲通过XML进行数据交互吧!
My Hello Snoopy
China Blogs
.NET and Flash develop

TOP

great post! thx for share.
男人最痛苦两件事莫过于:兴趣变成职业,女友变成老婆!

TOP

哇.一下子看完有点头痛了.不过真是好东东.有时间的话真要做个FLASHbbs看看.^_^
冰雪白绵咩~~!

TOP

非常感谢!请问这里谁的flash水平最高?

TOP

有没有   flash 和 jsp之间的交互!?
one more step

TOP

cool.看来flash真要开始学习一下了。
------------
在线等待
------------

TOP

OKOK,我从姓麦的官方网站上看到这篇文章的时候
还愁着怎么翻译呢,哈哈,现在好了

TOP

能否讲讲asp数据的flash表现,调用资料和图片等
最后一球定乾坤!

TOP

作者的老巢 actionscript-toolbox.com 还有好多好东西,

TOP

?提问: 它的A B C 不是从数据库中调出的吗?

          如果数据库里动态增加了 D 或 E F G.....,右边能正常显示不?
-------------------------------------------------
----------------------------------------
-----------------------------
-------------------
旅途愉快

TOP

"加入右边的字母标签所要执行的代码,同时给该标签加上对鼠标事件的监听,以便可以去相应用户的鼠标点击动作"-------------提到的代码和对鼠标事件的监听,在源文件哪个地方啊?找不到的说
-------------------------------------------------
----------------------------------------
-----------------------------
-------------------
旅途愉快

TOP