Amfphp Blog/Guestbook
Indledning.
I denne tutorial vil vi lave en Blog/Questbook med mulighed for at tilføje kommentarer. Vi vil sende data mellem flash og server med amfphp og lagre de afsendte data i mySQL. De data flash modtager vil dynamisk tilpasse sidens layout til indholdet.
Det kræver derfor, at du har installeret amfphp og har adgang til mySQL. Se eventuelt Jacob Halskovs tutorial http://flashforum.dk/tutorials/amf-php-del-1 som gennemgår opsætningen af disse ting. Desuden skal du i dette eksempel bruge swffit, som du kan hente her: http://swffit.millermedeiros.com/ . Det er et smart script, som virker sammen med swfObject, som også skal bruges: swfObject. Madster har gennemgået swfObject i en tutorial her på FF. Den kan du finde her: Godt igang med swfObject .
Undervejs i denne tutorial er der link til filer, der svarer til det sted vi er i processen. F.eks kan du her hente start filen (blog_start.fla).
Blogfil.
Start med at oprette en ny mappe og kald den blog. Opret derefter en ny flash as3 fil på 980 px gange 600 px og gem den som blog.fla i mappen. I flash filen starter vi med at lave nogle MovieClips (mc) og et par knapper. På fig. 1 ser du de symboler jeg har lavet.
To af disse mc, buttonHolder og commentHolder er tomme og skal bruges som holdere (DisplayObjectContainers) for de 2 mc, BlogBtn og Comment, som er vores DisplayObjects. De vil blive tilføjet dynamisk, når vi henter data fra mySQL.

fig. 1
For at bruge BlogBtn og Comment som DisplayObjects skal de tildeles et Class name. Højreklik på Comment mc i library og vælg Properties. Kryds af i Export for ActionScript og du vil se, at Class name automatisk bliver sat til Comment, som det skal. Klik ok og gør det samme med BlogBtn mc. Class name for dette mc bliver tilsvarende BlogBtn.
Du vil se, at der står flash.display.MovieClip i feltet Base Class. Flash har altså selv tilføjet MovieClip classen for os.
Resten af indholdet i library kan du vælge vilkårlige navne til. Og grafikken laves efter lyst og evner (blog_indhold.fla). Når du har lavet btn.send skal du lave mc.form, som vi skal kigge på nu.
Mc.form (fig. 2) skal bruges til at skrive navn, email og kommentarer i, som skal sendes til databasen. Vi skal derfor som minimum bruge tre input tekstfelter og en send knap. Jeg har sat grafikken op som du kan se på fig. 2. Bredden på mc.form er i alt 710 px og højden 132 px.

fig. 2
Kald navnefeltet for name_txt, emailfeltet email_txt og feltet til kommentarer kalder du kommentar_txt
. Hvordan tekstfelterne evt. kan sættes op kan du se på fig. 3. Men som en velkommen lettelse, behøver man ikke bekymre sig om embedding. Med amfphp bliver der ikke problemer med æøå da amfphp sender binær data til flash. I fig. 4 kan du se et eksempel på en besked, der er sendt fra tekstfelter som disse til databasen og tilbage igen med amf.

fig. 3
Træk btn.send ind på et nyt lag i mc.form og giv den instance navnet send_btn. Desuden har jeg tilføjet et statisk tekstfelt med teksten ”Tilføj kommentarer:” og to andre statiske tekstfelter med noget tekst, som fortæller, hvad de øvrige felter skal indeholde.

fig. 4
Som det sidste i mc.form skal der tilføjes endnu et tekstfelt. Det skal modtage besked om status i forbindelse med kommunikation med server og flash. Vælg Dynamisk Text og giv det instance navnet status_txt. Jeg har placeret status_txt umiddelbart under kommentar_txt. Så er mc.form færdig.
Når data er sendt fra mc.form og lagt i databasen, skal de hentes igen for at blive vist på siden. De modtagne data skal vises med movieclippet Comment. Gå til edit mode i mc Comment. Her skal vi også have tilføjet tre tekstfelter. Vælg
Dynamisk Text da de jo ikke skal være modtagelige for brugerindtastning, og placer dem evt. som i fig. 5. Bredden på dette mc er 500 px og højden 110 px.

fig. 5
Navngiv felterne returnName, returnDate og textFld. Desuden har jeg tilføjet en streg i toppen af movieclippet for at opdele de enkelte kommentarer visuelt. Det er denne streg, der optræder i library som mc.line. På fig. 6 kan ses et eks. på en besked, der er kommet tilbage til flash og vises med et mc som dette.

fig. 6
Mc kommentar skal indeholde et statisk tekstfelt og et dynamisk. Det dynamiske giver du instansnavnet num og i det statiske skriver du f.eks. ”Kommentar:”. På fig. 7 kan du se, felterne og på fig. 8 ses hvordan de vil tage sig ud på siden, placeret lige over mc Comment.

fig. 7

fig. 8
For at vise blogindlæg skal vi bruge mc.blog, som skal tage sig af det. Opret et dynamisk tekstfelt, som de tidligere og giv det instance navnet blogtextFld. Størrelsen jeg har lavet er 500 px bred og 40 px. høj. Tekstfeltets højde sættes senere med actionscript, når indholdet kommer fra DataBasen. Lav endnu et tekstfelt til en overskrift til indlægget. Giv det navnet overskrift_txt. Størrelsen kan f.eks være 500 x 24 px.
Mc.mainBG skal bruges til baggrund for siden, hvis man ønsker sådan en. I movieclippet har jeg lavet en hvid shape på 110 x 40 px. Størrelsen sætter vi senere med ActionScript. Denne baggrund vil blive skaleret dynamisk alt efter indholdet på siden.
Det var alt hvad der skal bruges for at lave vores interface. I library optræder også mc.formBG og grafik symbolet bg, de er ikke nødvendige. Jeg bruger bg som indhold i mc.formBG. Og mc.formBG bruger jeg som baggrund på tekstfelterne i mc.form (blog_interface.fla).
Adminmodul.
Blog'ens indlæg skal selvfølgelig tilføjes databasen fra et adminmodul, hvor man logger sig ind med brugernavn og adgangskode, så alle og enhver ikke kan skrive indlæg. Fra siden vi laver her, kan man så hente de forskellige indlæg frem fra databasen.
Vi snyder dog lidt med admin delen, da det ellers bliver for omfattende. Men Jacob Halskov har lavet en rigtig god videotutorial i to dele om et Loginsystem i Flash. Første del finder du her http://flashforum.dk/tutorials/amf-php-del-2-12
I stedet kan du i filerne til denne tutorial, finde en ganske enkel ”admin” fil, mySql table og amfphp service Gemindlaeg.php. Med dem kan du sende indlæg til mySql.
Opsætning.
I blog.fla (blog_interface.fla, hvis du har hentet den) skal vi nu have sat nogle af vores mc op. Der er selvfølgelig mange måder at gøre det på men fig. 9 viser placeringen jeg har valgt. I listen kan du se navnene, som de står i

fig. 9
library, instansnavnene på scenen og x og y positioner. Desuden har jeg lavet et dynamisk tekstfelt på scenen, som hedder blogreturnDate og en overskrift i et statisk teksfelt: Tutorial Blog.

Nu kan du hente den færdige fil, blog.fla og de øvrige filer (alle filer) og copy/paste indholdet fra actions laget i blog.fla til din blog.fla's actionscript lag. Så har du alle flashkoderne, der skal bruges. Dem vil vi gennemgå om lidt. I blog.fla skal du først ændre stien i linien (Linje 32):
gw.connect ("http://www.ditdomæne/amfphp/gateway.php");
og i php filerne i mappen Blogservices skal du indsætte de mySql koder, som du har fået af din udbyder, Dbhost, User, Pass, Dbname.
Upload din mappe blog med filen blog.swf til din server og fra de downloadede filer tilføjer du swffit.js, swfobject.js, blog_tutorial.html, admin.html og admin.swf (fig. 10). Derefter finder du mappen amfphp > services i din ftp

fig. 10
klient. I denne mappe uploader du hele mappen Blogservices fra de downloadede filer. Til sidst sætter du de to medfølgende tables op i mysQl. Dem finder du i filen sql.txt.
Inden vi vender tilbage til flash kan vi lige teste siden. Åben en browser og find www.ditdomæne/blog/blog_tutorial.html og i et nyt faneblad åbner du .../blog/admin.html. Blogsiden skulle gerne vise en overskrift – Tutorial Blog, den hvide baggrund, Kommentarer: og form_mc. Gå til admin.html og indtast et eller andet dybsindigt emne/indlæg og klik gem. Du får nu returneret svaret ”Indlæg gemt!”. Refrest blog.html.

fig. 11
Nu er der kommet et blogindlæg på siden (fig 11) og der er tilføjet en knap med det emne du skrev. Der er sat en dato på og form_mc og kommentar_mc har fået justeret deres y pos. Antal kommentarer vises med Kommentar: 0. Lad os gå til flash.
Funktionalitet.
Som det fremgik tilpasser siden sig det indhold, der sendes til og modtages fra databasen. Det vil sige, at de mc der står i ovenstående tabel modtager indhold og/eller justeres i størrelse og y position. Desuden oprettes menuen i buttonHolder, hvor der tilføjes BlogBtn movieclip og kommentarer vil derefter blive tilføjet dynamisk med mc Comment.
I actionscript laget i blog.fla starter vi med at sætte skalering og alignment:
stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP;
Det vil placere swf'en i toppen af browseren og centrere den horisontalt. Derefter sætter vi størrelsen på mainBG, som jeg har valgt til 900 x 600 px og vi opretter 3 variabler til at hente de rigtige data samt variablen fitHeight, som er den relative højde på vores swf. Den værdi sendes til swffit.
var id:int = 1; var indlaegID:int = id; var callLast:Boolean = false; var fitHeight:Number; mainBG.y = 0; mainBG.width = 900; mainBG.height = 600;
Til at kalde vores amfphp services og methods (i amfphp hedder funktioner methods) skal vi bruge fire instances af responder classen. Når der oprettes en ny Responder klasse, skal der sendes to parametre med i constructor funktionen; det første er navnet på den funktion vi ønsker skal håndtere svar fra serveren, og det andet parameter er navnet på den funktion vi ønsker skal håndtere fejl, der opstår på serveren.
var blogres:Responder = new Responder(visBlog, onFault); var knapres:Responder = new Responder(opretKnapper, onFault); var res:Responder = new Responder(onResult, onFault); var datares:Responder = new Responder(hentData, onFault);
Vi kan nu kalde vores services med gw.call metoden, der indeholder en streng med den method vi vil kalde, respondObjectet, og diverse parametre. Vi starter

fig. 12
med den funtion vi lige har set i anvendelse. Når siden refreshes sender vores netconnection gw.call ("Blogservices.Hentindlaeg.hentPost", blogres, id); (fig. 12).
function visBlog (responds:Object):void { blog.blogtextFld.mouseWheelEnabled = false; blog.blogtextFld.autoSize = TextFieldAutoSize.LEFT; var ArrBlog:Array = responds.serverInfo.initialData; blogreturnDate.text = ArrBlog[0][0]; blog.overskrift_txt.htmlText = ArrBlog[0][1]; blog.blogtextFld.htmlText = ArrBlog[0][2]; kommentar_mc.y = blog.y + blog.height + 36; commentHolder.y = kommentar_mc.y + 24; gw.call ("Blogservices.Hentkommentar.hentIndhold", datares, callLast, indlaegID); } gw.call ("Blogservices.Hentindlaeg.hentPost", blogres, id);
Var ArrBlog indeholder de data vi får fra amfphp. Her er det return, der kommer fra Blogservices.Hentindlaeg.hentPost:
return mysql_query("SELECT time, emne, tekst FROM blogartikler WHERE id = '$id' ORDER BY id");
I gw.call sender vi variablen id med, som fra start er sat til 1. Derfor får vi indlæg 1 tilbage og vores service henter desuden tiden og emne som sættes i tekstfeltet overskrift_txt.
Tekstfeltet blog.blogtextFld er sat til autosize og når teksten er fyldt i tekstfeltet ”skubbes” kommentar_mc og commentHolder på plads med blog.height.
Sidste linie er et nyt gw.call, som henter kommentarer med indlaegID = id.
På samme tid som vores første kald, sendes gw.call ("Blogservices.Hentindlaeg.knapTekst", knapres); og nedenstående funktion sætter menuen op:
function opretKnapper (responds:Object):void { var ArrNavn:Array = responds.serverInfo.initialData; for (var i:int = 0; i < ArrNavn.length; i ++) { var btn:MovieClip = new BlogBtn(); btn.emne_txt.mouseEnabled = false; btn.emne_txt.text = ArrNavn[i]; btn.y = 24 * i; btn.x = 0; btn.index = i; btn.name = "btn" + i; btn.buttonMode = true; buttonHolder.addChild (btn); buttonHolder.addEventListener (MouseEvent.CLICK, hentBlog, false, 0, true); } }
Data i ArrNavn sætter navnet i tekstfeltet på BlogBtn knappen, som tilføjes med addChild.
Princippet i resten af scriptet er det samme og vil herefter give sig selv, men lad os prøve at tilføje en kommentar. Udfyld felterne og klik Send kommentar.
Det vil kalde funktionen sendKommentar som sender et nyt call:
gw.call ("Blogproject.Gemkommentar.valider", res, indlaegID, navn, email, kommentar);
Det kalder så funktionen onResult, der sætter callLast = true; - vi vil kun hente sidste kommentar og ikke hele rækken, hvis der var flere ville de jo være hentet allerede. Hvis alt forløber som det skal, sender onResult et nyt gw.call, der kalder funktionen hentData:
gw.call ("Blogservices.Hentkommentar.hentIndhold", datares, callLast, indlaegID); function hentData (responds:Object):void { var numRows:int = responds[0].serverInfo.initialData; kommentar_mc.num.text = numRows; var Arrmd:Array = responds[1].serverInfo.initialData; for (var i:int = 0; i < Arrmd.length; i ++) { var comment_mc:MovieClip = new Comment(); commentHolder.addChild (comment_mc); comment_mc.textFld.mouseWheelEnabled = false; comment_mc.textFld.autoSize = TextFieldAutoSize.LEFT; comment_mc.returnDate.text = Arrmd[i][1]; comment_mc.returnName.text = Arrmd[i][0]; comment_mc.textFld.text = Arrmd[i][2]; if (commentHolder.numChildren > 1) { var lastcomment:MovieClip = MovieClip(commentHolder.getChildAt(commentHolder.numChildren-2)); comment_mc.y = lastcomment.y + lastcomment.height + 12; } else { comment_mc.y = 0; } } opdaterIF (); }
Her modtager vi igen et respond array som deles i Arrmd og numRows. NumRows indeholder antallet af rækker i tabellen, som sendes til tekstfeltet i kommentar_mc. Arrmd indeholder data til at vise tiden, til at fylde tekst i tekstfelterne i Comment mc og til at tilføje det nødvendige antal mc Comment.

fig. 13
I amfphp servicebrowser er der i øvrigt mulighed for at se, hvad der sendes til flash (fig. 13). Det er en god hjælp, når man skal finde frem til indholdet i datastrengen, der modtages. Til sidst opdateres siden med opdaterIF:
function opdaterIF () { form_mc.navn_txt.text = ""; form_mc.email_txt.text = ""; form_mc.kommentar_txt.text = ""; form_mc.status_txt.text = ""; form_mc.send_btn.alpha = 1; form_mc.y = commentHolder.height + commentHolder.y + 50; mainBG.height = form_mc.y + 216; fitHeight = mainBG.height; ExternalInterface.call ("swffit.fit", 'my_flash', '980', fitHeight); }
Tekstfelterne i form_mc nulstilles og y position justeres. Desuden justeres baggrunden med mainBG.height og denne værdi sendes med variablen fitHeight til swffit.js.
ExternallInterface klassen tager sig af kommunikation mellem javascript og actionscript. Og vi sender blot de ønskede parametre med til swffit.js.
ExternalInterface.call ("swffit.fit", 'my_flash', '980', fitHeight);
”my_flash” er object/embed tag'et som vi kender fra swfobject.js, '980' er den nuværende bredde og 'fitHeight' den nuværende højde. Swffit sørger for at tilføje browser scrollbars hvis højden på swf'en overskrider 600 px, som vi har defineret i nedenstående udsnit af blog.html.
<script type="text/javascript"> swfobject.embedSWF("blog.swf", "my_flash", "980", "600", "8.0.0"); swffit.fit("my_flash", 980, 600, 0, 0, true, false); </script>
Hvis blog.swf'en f.eks er uden indhold, som vi så i starten, så vil swffit altså også tilføje scrollbars, hvis browservinduet gøres mindre end de 600 px i højden.
Du kan læse mere om swffit her: http://swffit.millermedeiros.com/
Det var lidt om, hvordan man med amfphp, swffit og flash kan lave en dynamisk side. Jeg håber du kan bruge noget af det. God fornøjelse.
- log ind eller opret konto for at skrive kommentarer


Kommentarer
Hey, fedt med endnu flere tutorials om Amfphp
Mvh. Jakob Halskov
PS jeg hedder Jakob med K
Flash, Flash & Photoshop.
16 år Århus
Hvor blev alle billeder og source af?
Hej kodak
Ja, det var da et godt spørgsmål
Jeg har skiftet server og simpelthen glemt at flytte tingene til denne tut. De er på plads nu, dog ikke demoen.