Unknown error communicating between PHP and Actionscript - php

I've got a problem that's either insanely simple or complex, it's up to you to find out. I've been working on trying to incorporate the URL Loader class into the beginners graphics program - Stencyl. I am fluent in HTML, CSS and PHP but actionscript is completely new to me so I really could use with a hand. Here's what I've got:
There are 4 files hosted on my domain:
Webpage.html
Stylesheet.css
RequestData.php
FlashDoc.swf
The html and css code is simple, no problems there and the swf file embed in the html document. The flash file is a simple form with a text field, submit button and two dynamic text fields. The code goes as follows:
// Btn listener
submit_btn.addEventListener(MouseEvent.CLICK, btnDown);
// Btn Down function
function btnDown(event:MouseEvent):void {
// Assign a variable name for our URLVariables object
var variables:URLVariables = new URLVariables();
// Build the varSend variable
// Be sure you place the proper location reference to your PHP config file here
var varSend:URLRequest = new URLRequest("http://www.mywebsite.com/config_flash.php");
varSend.method = URLRequestMethod.POST;
varSend.data = variables;
// Build the varLoader variable
var varLoader:URLLoader = new URLLoader;
varLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
varLoader.addEventListener(Event.COMPLETE, completeHandler);
variables.uname = uname_txt.text;
variables.sendRequest = "parse";
// Send the data to the php file
varLoader.load(varSend);
// When the data comes back from PHP we display it here
function completeHandler(event:Event):void{
var phpVar1 = event.target.data.var1;
var phpVar2 = event.target.data.var2;
result1_txt.text = phpVar1;
result2_txt.text = phpVar2;
}
}
I then have a small PHP file with this code:
<?php
// Only run this script if the sendRequest is from our flash application
if ($_POST['sendRequest'] == "parse") {
// Access the value of the dynamic text field variable sent from flash
$uname = $_POST['uname'];
// Print two vars back to flash, you can also use "echo" in place of print
print "var1=My name is $uname...";
print "&var2=...$uname is my name.";
}
?>
This is, for some reason, not working. The result is just two blank text fields and being an actionscript noob, I have no idea what is up. Any help would be greatly appreciated. Thank you for your time.

The answer to your issue is both simple and surprising, if you're not used to AS3.
In AS3, the flash.* classes tend to, when a setter is used, make and store a copy of the passed object.
Since they store a copy, any modification on the original instance after the setter isn't applied on the copy, and thus is ignored.
It is the case of, for example, DisplayObject.filters, ContextMenu.customItems or URLRequest.data.
In your code, you are setting varSend.data = variables before filling variables. You should do the reverse :
variables.uname = uname_txt.text;
variables.sendRequest = "parse";
varSend.data = variables;
// Send the data to the php file
varLoader.load(varSend);
Only some classes do that, and even then, they usually don't do it with all of their setters.

Related

Loading PHP URL in Flash AS3

I am working on an online game in Flash AS3 and utilizing a PHP server with mySQL database. I am manipulating the data in mySQL database using PHP and when I request the PHP file in a browser straightly from 'localhost/php/file.php', the database changes perfectly. I have the following AS3 code:
public function getSite(string):Boolean{
var phpVars:URLVariables = new URLVariables();
var t:Boolean = false;
/*
we use the URLRequest method to get the address of our php file and attach the php vars.
*/
var urlRequest:URLRequest = new URLRequest(string);
/*
the POST method is used here so we can use php's $_POST function in order to recieve our php variables.
*/
urlRequest.method = URLRequestMethod.POST;
/*
this attaches our php variables to the url request
*/
urlRequest.data = phpVars;
/*
we use the URLLoader class to send the request URLVariables to the php file
*/
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlLoader.addEventListener(Event.COMPLETE, check(t));
t = check(t);
/*
runs the function once the php file has spoken to flash
*/
/*
we send the request to the php file
*/
urlLoader.load(urlRequest)
return t;
}
function check(t:Boolean):Function{
return function (event:Event):Boolean{
trace(event.target.data.checkResult);
if(event.target.data.checkResult == "Good"){
t = true;
} else {
t = false;
}
return t;
}
}
Now from here, my "trace" shows that the URL is loaded and the output is "Good", however the database values does not change. This is the PHP file:
<?php
/*
connect to our database
*/
include_once "connect.php";
$sql = "UPDATE accounts SET PlayersOnline = accounts.PlayersOnline + 1";
$query = mysql_query($sql) or exit("checkResult=Bad");
exit("checkResult=Good");
?>
When I go to 'localhost/php/gameSearch.php' in my web browser the database changes, and I am wondering what the problem is.
You have a "caching" problem. In other words, the result of the already requested URL is cached to reduce latency and access times, and what you've represented is the cached copy of the output and not a fresh output resulting from the execution of the instructions on behalf of the server.
To overcome the issue, you could've pushed a no-cache header to the requestHeaders property on your "request" object (the property is of type URLRequestHeader). However, the runtime looks to be ignorant on the header and it always provides the cached copy!
To overcome that issue, however, you need to fool the runtime as if you are requesting a new URL every time by appending a dummy random-valued variable:
getSite("localhost/php/file.php?r="+Math.random());
And regarding your specific provided code; The URLLoader works asynchronously, that's why you register a "on complete" listener! The t = check(t); statement induces you're attempting to "check" the result while it may not be ready by then! You should check it when/after the listener triggered. In addition to the fact that the assignment is syntactically inappropriate (assigning a Function to a Boolean!) and reconsider the logic of the check function!
And in the PHP code, as others have suggested, ultimatly don't use the deprecated mysql_query function and use a more appropriate API.

Actionscript to php then to word template and replace variables

I need to write a code which can do following using actionscript:
1. Send the variables to a php
2. php should open a [re designed word document.
3. Specific word document entries should be replaced with the variables sent from actioncript retaining the formatting of the template.
4. Save the document and provide a link for its download OR just mail it to an address.
I have asked few questions before which very pretty simple compared to this and i did not get any answer for it.. I dont know if this will either. If possible please help me.
To send the variables from ActionScript you would need to do something like the following:
var http:HTTPService = new HTTPService();
http.url = "http://www.yourWebsite.com/yourPhpFile.php";
http.method = "POST";
var variablesToSend:Object = new Object();
for (var varName:String in yourVariables){
variablesToSend[varName] = yourVariables[varName];
}
http.send(variablesToSend);
From "yourPhpFile.php" I would suggest adding some special keywords to search for in the template and do a str_replace() with the variables received through the $_POST object. I'm no php expert but something like:
$yourFilePath = "C:\your\file\path\here.txt";
$yourFileAsString = file_get_contents($yourFilePath);
foreach($_POST as $key=>$value){
$yourFileAsString = str_replace($key,$value,$yourFileAsString);
}
file_put_contents(genNewFileName(),$yourFileAsString);

Retrieving Information from MySQL via PHP to AS3

I am currently doing a tutorial which was found on TutsPlus.
This tutorial was to save information from AS3 to MySQL via PHP and then retrieve this information.
So far, it works. I Can enter a username and score, which saves to the database. There is one problem though, I would like to be able to display ALL the names and scores in a table, instead of having to search for a name and then finding the score for that specific user.
The code in which the information is saved (which works), is below.
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class register extends MovieClip {
public function register ():void {
register_button.buttonMode = true;
register_button.addEventListener(MouseEvent.MOUSE_DOWN, checkForm);
username_text.text = "";
userbio_text.text = "";
}
public function checkForm (e:MouseEvent):void {
if (username_text.text != "" && userbio_text.text != "") {
sendForm();
} else {
result_text.text = "PLEASE ENTER A NAME";
}
}
public function sendForm ():void {
/*
we use the URLVariables class to store our php variables
*/
var phpVars:URLVariables = new URLVariables();
phpVars.username = username_text.text;
phpVars.userbio = userbio_text.text;
/*
we use the URLRequest method to get the address of our php file and attach the php vars.
*/
var urlRequest:URLRequest = new URLRequest("localhost/php/register.php");
/*
the POST method is used here so we can use php's $_POST function in order to recieve our php variables.
*/
urlRequest.method = URLRequestMethod.POST;
/*
this attaches our php variables to the url request
*/
urlRequest.data = phpVars;
/*
we use the URLLoader class to send the request URLVariables to the php file
*/
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
/*
runs the function once the php file has spoken to flash
*/
urlLoader.addEventListener(Event.COMPLETE, showResult);
/*
we send the request to the php file
*/
urlLoader.load(urlRequest);
}
/*
function to show result
*/
public function showResult (e:Event):void {
result_text.text = "" + e.target.data.result_message;
}
}
}
From here, I can go to another application and search the users name, and then displays that users score. Code below:
package actions {
import flash.display.MovieClip;
import flash.events.*;
import flash.net.*;
import flash.text.*;
public class main extends MovieClip {
public function main ():void {
submit_button.buttonMode = true;
submit_button.addEventListener(MouseEvent.MOUSE_DOWN, checkLogin);
username.text = "";
}
public function checkLogin (e:MouseEvent):void {
if (username.text == "") {
username.text = "Enter your username";
}
else {
processLogin();
}
}
public function processLogin ():void {
var phpVars:URLVariables = new URLVariables();
var phpFileRequest:URLRequest = new URLRequest("http://xx.xx.xx.uk/~bf93fv/Source%202/php/controlpanel.php");
phpFileRequest.method = URLRequestMethod.POST;
phpFileRequest.data = phpVars;
var phpLoader:URLLoader = new URLLoader();
phpLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
phpLoader.addEventListener(Event.COMPLETE, showResult);
phpVars.systemCall = "checkLogin";
phpVars.username = username.text;
phpLoader.load(phpFileRequest);
}
public function showResult (event:Event):void {
result_text.autoSize = TextFieldAutoSize.LEFT;
result_text.text = "" + event.target.data.systemResult;
}
}
}
The controlpanel.php file, which displays the username and score individually is below:
<?php
include_once "connect.php";
$username = $_POST['username'];
if ($_POST['systemCall'] == "checkLogin") {
$sql = "SELECT * FROM users WHERE username='$username'";
$query = mysql_query($sql);
$login_counter = mysql_num_rows($query);
if ($login_counter > 0) {
while ($data = mysql_fetch_array($query)) {
$userbio = $data["user_bio"];
print "systemResult=$username Scored $userbio";
}
}
else {
print "systemResult=The login details dont match our records.";
}
}
?>
Does anybody know any easy way in order to view ALL the information from the database into a table?
There are few things you might want to improve in your PHP code (your AS3 is better).
Use PDO instead of the functions that work with particular DBMS. The reason to this is that it is portable (to an extend). Say, if you wanted to ever move the database from MySQL to Postgres, you'd had to rewrite less of your code, then you would have to otherwise. PDO also provides some means of sanitizing the input. It's not bullet proof - still better then nothing. PDO is considered the "good practice", so you would learn to write the good code right away instead of making that journey from writing newby-style code at first and then discovering how to actually do it properly. It might be just a little bit more verbose if you are thinking about a very primitive task such as a single select, but as soon as your task becomes just a little bit more complex it becomes all worth the time.
In your SQL queries make a general rule never to use select *, unless for testing / debugging. That's sort of laziness that in the end will cost you a lot of problems. By doing so you will make it very difficult to maintain your code later, effectively transforming it into "write once - run away" kind of thing. Again, as a simple proof of concept it is OK, - long-term solution - bad. If you are still blur on what I'm trying to say: list all column names explicitly.
Using include / require and their _once family is a bad idea as a long-term solution. Again, OK for a simple test - bad in the long run. Good programs are written in functions / classes and use __autoload() or a framework that uses the ability to load classes automatically. This makes larger applications more manageable, easier to navigate and understand then the web of includes.
You must sanitize input from the user of your web application, that is don't do $_POST['key']. At least write the function that will both check that the key exists and that it is of an expected format.
Now, your actual problem, sending the data.
You can just send the raw SQL output you get in PHP - will spare your server the problem of re-encoding all of it. Works in the very simple cases, but it becomes more complex with more complex tasks. This is also uncommon to do, so you will find that people will not know how to handle that. (No technical restriction, it is just really a historical artefact).
There are a bunch of popular formats that can be digested by variety of applications, not necessary Flash. Those include XML, JSON, Protobuf. There are also some more particular to PHP like the one produced from serialize(). I'd urge you to stick to JSON if you go down this route. XML might be a more mature technology, but JSON has a benefit of the basic type system built in (while in XML it is yet another layer on top of it, which is, beside other things is not implemented in Flash - I'm talking about XSL).
There's AMF (ActionScript Message Format) - it is ideal for Flash. PHP also knows very well how to produce it (there are several popular implementations out there). This format is a lot more compact compared to JSON or XML. It has more expressive power (can describe circular dependencies, many-to-many relationships, has a procedure for introducing custom types, custom [de]serialization routines). It is also self-describing, unless you used custom serialization routine. This is the best option if you aren't planning on moving your application to JavaScript later, because JavaScript has problems consuming binary data. Parsing this format would not be possible there.
Protobuf is a viable option too. This is a data exchange format designed by Google. It is similar in spirit to AMF, however it may not be self-describing. It relies on the application to know how to produced custom objects from it. It has, however, a form, that can be parsed in JavaScript (although you'd lose the the compactness benefit).
Your ActionScript code: If you opt for AMF, you'd need to look into NetConnection class. I'd advise you to take a look in AMFPHP project - it also has examples. Alternatively, Zend Framework has Zend_Amf library to be used for that purpose. But using the entire framework may be overwhelming at start.
If you go with XML - then there's a built-in XML class, there are millions of examples on the web on how to use it.
If you go with JSON, then since not so long ago there's a built-in class for that too. But before there was one, there were several libraries to parse it.
There used to be a project on GoogleCode for Protobuf support in Flash, but it required quite a bit of acquittance and manual labour to get going.
Finally, index of things mentioned here:
http://php.net/manual/en/book.pdo.php - PDO
http://php.net/manual/en/function.json-encode.php - JSON in PHP
http://php.net/manual/en/book.dom.php - XML in PHP (There is no agreement on which XML library is better if PHP is considered. I'd probably stick to this, but ymmv).
http://www.silexlabs.org/amfphp/ - AMF in PHP
http://framework.zend.com/manual/1.12/en/zend.amf.html Zend_Amf library
http://code.google.com/p/protobuf-actionscript3/ Protobuf in ActionScript
https://github.com/drslump/Protobuf-PHP PHP Protobuf (sorry, never used this one, but looks fine)
http://www.blooddy.by/en/crypto/ for older versions of Flash player - this library has the best JSON decoder I know of.
The best way is (I think) to use XML.
On the PHP side, the script output an XML document with all the users :
$sql = "SELECT * FROM users "; // add order statement if needed
$query = mysql_query($sql);
$login_counter = mysql_num_rows($query);
$xml = array('<?xml version="1.0" encoding="UTF-8"?><users>');
if ($login_counter > 0) {
while ($data = mysql_fetch_array($query)) {
$xml[] = '<user name="'.$data['username'].'" bio="'.$data["user_bio"].'" />';
}
}
else {
// do nothing
// you will handle it on the flash side by checking the length of user nodes list
}
$xml[] = '</users>';
header('Content-Type:text/xml');
die(implode('', $xml));
This will output an XML document :
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user name="..." bio="..." />
<user name="..." bio="..." />
[...]
</users>
(There are class on PHP like SimpleXML to deal with XML in a cleaner way)
AS Side :
You can easily browse / display the data on the flash side with the help of the XML / XMLList class
Just adapt the URLLoaderDataFormat to TEXT and convert the data to XML in the complete event handler :
var xml:XML = new XML(event.target.data);
Then iterate the user elements to display them :
var users:XMLList = xml.user;
var user:XML;
for (user in users) {
trace('name->' + user.attribute('name') );
trace('bio->' + user.attribute('bio') );
}

Accessing PHP variables using AS3 without using OO

Really stumped on this one.
I have the following PHP file with a variable I am trying to access to place in a dynamic text box on my flash stage.
PHP code:
$returnVars = array();
$returnVars['username'] = "test";
$returnString = http_build_query($returnVars);
//send variables back to Flash
echo $returnString;
AS3 code:
var request:URLRequest = new URLRequest("http://www.mysite.com/flash.php");
request.method = URLRequestMethod.GET;
var loader2:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, completeHandler);
loader2.dataFormat = URLLoaderDataFormat.VARIABLES;
loader2.load(request);
function completeHandler(event:Event) :void{
var username = event.target.data.username;
// dynamic text box called username
username.text=event.target.data.username;
}
The error:
Error #1009: Cannot access a property
or method of a null object reference.
The code was adapted from a tutorial using a class. However I do not get on with classes so wont be using any.
Any ideas will be most welcome.
-Rob.
When looking at your code, I don't really see anything wrong with the way you are working in AS3 (don't know about Php, but that will be okay too i guess). It's just that you add an eventListener to loader, when you should be adding it to loader2.
And second of all, Why are you naming a variable just the same way as a textBox? that is asking for problems :)
function completeHandler(event:Event) :void{
//Change the variable name of this to something else
var _someOtherVariableName = event.target.data.username;
//dynamic text box called username
username.text = event.target.data.username;
}
The code looks all wrong
First of, are you sure http_build_query is what you need?
Secondly, I'm not an AS veteran, but defining a variable named "username" and then setting it's property "text" in that way looks horribly bad.
Edit: In fact, my observation explains the error. When you define "username", it's obviously not an object. When you try setting the property "text", it won't work for this same reason.
I really think you need to learn the basics of object-oriented programming...
Edit2:
This is the relevant code from the tutorial:
var username = evt.target.data.username;
var email = evt.target.data.email;
trace ('username is ' + username);
trace ('email is ' + email);
As you see, there's no mention of username.text.

How to make returned from PHP Data fill MXML Flex mx:List (Using actionscript and PHP)

I am Using Flex 3 and apache with PHP 5.2.
I am searching for simple as possible way to fill my mx:List with data using POST URLRequest.
In Flex builder I am using the next code
public var variables_se:URLVariables = new URLVariables();
public var varSend_se:URLRequest = new URLRequest("DataProvider.php");
public var varLoader_se:URLLoader = new URLLoader;
public function starter():void
{
varSend_se.method = URLRequestMethod.POST;
varSend_se.data = variables_se;
varLoader_se.dataFormat = URLLoaderDataFormat.VARIABLES;
varLoader_se.addEventListener(Event.COMPLETE, completeHandler_se);
variables_se.CountOflistItemsIWant = 30;
varLoader_se.load(varSend_se);
}
public function completeHandler_se(event:Event):void
{
textFild.text += " " + String(event.target.data) + ";"; // any result will apear in some textFild
// How to make result appear as list lines, how to form PHP answer and AS3 code for it?
}
How to make result appear as list lines, how to form PHP answer and AS3 code for it (If for example I want to return random numbers from PHP in desired in CountOflistItemsIWant cuatety)?
Maybe you could make your php script echo json encoded array like so:
<?php
echo json_encode(array('first', 'second', 'foo', 'bar'));
and in flex get it, decode it and use it as argument for array data provider for your mx:List
You can find information about communicating between php and flex with use of json here: http://www.adobe.com/devnet/flex/articles/flex_php_json.html
IMHO this is a larger architectural question. Here are the options:
Create a RESTful web service and have it output data in some text format (XML or JSON). You can use the HttpService objects in Flex to make request to your PHP restful web service and set result and fault handlers accordingly. Here's the quick start: http://www.adobe.com/devnet/flex/quickstart/httpservice/
If you need to remote objects directly between Flex and PHP, AMFPHP can be used: http://www.amfphp.org/
You can create a SOAP web service in PHP, some references...
http://developer.apple.com/internet/webservices/soapphp.html
http://php.net/manual/en/book.soap.php
... and use the Flex WebService object to make calls:
http://livedocs.adobe.com/flex/3/html/data_access_3.html

Categories