LSL to PHP

Requirements: To follow this tutorial you need FTP access to a web server with PHP 4 or higher and access to either Second Life, or an off-world LSL editor.  Furthermore, this tutorial assumes you understand how to create objects, add scripts to those objects, and are in a location that allows scripts to be ran.  I also recommend you view the documentation on llHTTPRequest in the LSL Wiki.  You don't have to understand it, not yet anyhow.

To begin, we are going to be operating solely with two files, the first being the Second Life script.  The second file is a PHP file, now you can choose to edit it remotely or locally, but for the sake of simplicity the tutorial will assume you are editing the file on your computer and then uploading it to your web server when finished.

Part I – Second Life

To begin create a cube and add a script inside the object, name this script whatever you want, I usually call my scripts Core.  First I’m going to show you the code, and then explain it.

string serverPath = "http://www.phyrax.com/SL/test.php";
key http_request_id; // internal id for every http sender request/response.
list params = [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"];
string yourString = "Add something here.";

default
{
    state_entry()
    {
        list sendData = ["string",yourString,"question","How are you today?"];
        integer len=llGetListLength(sendData) & 0xFFFE; // make it even
        string httpBody;
        integer i;
        for (i=0;i<len;i+=2)
        {
            string varname=llList2String(sendData,i);
            string varvalue=llList2String(sendData,i + 1);
            if (i>0) httpBody+="&";
            httpBody+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
        }
        http_request_id = llHTTPRequest(serverPath, params, httpBody);
    }
    http_response(key request_id, integer status, list metadata, string body)
    {
        if(request_id == http_request_id){  // Make sure we get what we asked for.
            llSay(0,body);
        }
    }
}

I like to use variables throughout my scripts, and to make it easier to change them, we can define global variables before the default state occurs.

string serverPath = "http://www.phyrax.com/SL/test.php";
key http_request_id; // internal id for every http sender request/response.
list params = [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"];
string yourString = "Add something here.";

We need to set a server path, this is the EXACT URL we are going to communicate with.  The http_request_id MUST be a KEY value type, and is used for a sort of confirmation.  The params MUST be a list seeing that llHTTPRequest states that it’s parameters is a list.  Your choice of methods can be GET, POST, PUT, or DELETE.  For the tutorial we are using POST because this coupled with the MIME type, this tells our PHP script to act as if it’s receiving form data, like from a contact form.  The yourString variable is for you to see that the PHP script isn’t lying to you when it responds, we’ll cover that in a few.  For now, please change it to something else, like “this is my script” or whatever.

Now lets get down to business, since the variables are done.

        list sendData = ["string",yourString,"question","How are you today?"];
        integer len=llGetListLength(sendData) & 0xFFFE; // make it even
        string httpBody;
        integer i;
        for (i=0;i<len;i+=2)
        {
            string varname=llList2String(sendData,i);
            string varvalue=llList2String(sendData,i + 1);
            if (i>0) httpBody+="&";
            httpBody+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
        }
        http_request_id = llHTTPRequest(serverPath, params, httpBody);

You can use this inside any event type, I just chose start_event( ) because it was fast and simple, but hey, I’m not the lazy one here…. The sendData variable is a list of information, in a key/value pair setup, sort of like an array.  The first value is a variable name, the second value is the variables value, however, the LSL doesn’t really care, this is for the PHP to understand we’ll get to that in a minute.  Just in case your list isn’t even, the len variable makes sure it is so we can do some URL generation.  This is REQUIRED for our loop to work, don’t get ahead of me now.  Next up is some variables we’re going to use, but don’t want to assign anything to them, so we just declare them, that’s it.

Now I’m not going to get into the purpose of a for loop but I will tell you this; the loops jumps through that key/value list setup we made.  It firsts take that first value we made (string) and turns it in to a variable name.  It then takes the second value and turns it into the previously designated variable’s value (yourString).  Since we defined the yourString variable earlier it turns into whatever you changed it to.  This loop then checks to see if it’s on a second key/value pair, if it is, the loop then inserts the ampersand inside the httpBody variable so PHP knows the next key/value pair is coming.  Finally the loop turns the data into a complete string and encodes the appropriate variables, which looks like this:


httpBody = "string=Add%20something%20here&question=How%20are%20you%20today?"

Now we finally utilize that poor ‘ol lonely key variable, the http_request_id, we assign that variable to llHTTPRequest and input the values we have made over time.  The serverPath was defined a while back, along with the params variable.  The httpBody was just generated by that beautiful loop we made.  Since we’re calling llHTTPRequest, it makes a callback to the http_response event.  Let’s get to that, but we’ll save it for part III.

PERFORMANCE NOTE: llHTTPRequest() is limited to a maximum of 25 requests every 20 seconds on a per-object basis.

Part II – PHP

The PHP portion of this is amazingly simple, but for the sake of the tutorial and to be sure I cover EVERYTHING, I’ll still post the code.

<?PHP

$string = $_POST['string'];
$question = $_POST['question'];

$dataReturn = "\r\n This is the server talking and I heard the following. \r\n String: ".$string."\r Question: ".$question;
echo($dataReturn);

?>

You remember that list I called key/value pairs?  Well here’s where they come in.  Being the method that was used (line 03 of the LSL) was POST, we utilize the $_POST variable type in PHP.  Furthermore, we convert them to a usable variable.  Now you can do as you wish when you wish with the variables.  You just need to remember the variable names from the LSL file. For instance,  $_POST['string'] refers back to “Add something here.” Therefore $string refers to “Add something here.”  The data return variable is just a combination of info, It’s going to talk to our script in SL via the echo() command.  This is important, and I mean very important.  ANY command that is meant to display text, this includes print, print_r, vardump, etc… will talk to the Second Life script calling the PHP script.  Since we use the echo() command, the script inside Second Life will receive the following.

This is the server talking and I heard the following.
String: Add something here
Question: How are you today?

The main ideology here is that once you get your $_POST variables sorted out, you can do what ever you want with them, be it deposit them into a database, calculate something, relay messages to another website (twitter for example), or whatever you can do with regular PHP coding.  The possibilities are endless, the script doesn’t even have to return anything, though I suggest at least returning something to know the script completed.  You could even get a little elaborate with it and return a colon delimited string like “this:is:a:string” and use LSL to break up and use it as needed.  Now since the script has finished it’s computations and talked back to our Second Life script, we move on to part III to handle the return call.

Part III – Second Life

First off, when llHTTPRequest is called, it always enacts an event called http_response.  Now http_response has four possible variables; request_id, status, metadata, and body.  We only need to use request_id and body for this tutorial.  It’s time to see what we are going to do with what is returned to our Second Life script from the server.  Our http_response looks like this:

   http_response(key request_id, integer status, list metadata, string body)
    {
        if(request_id == http_request_id){  // Make sure we get what we asked for.
            llSay(0,body);
        }
    }

The above code FIRST and foremost, checks the request_id against the one we sent out, if it’s the same, then we continue.  This is a sort of checksum to be sure we utilize the correct portion of code according to the appropriate request_id.  Now since our PHP script was designed solely to return three lines of text, and nothing special, we just use the llSay() function to say it in channel zero, the default chat channel for Second Life.  And that’s pretty much it, nothing major, I hope I didn’t confuse you too much anyhow :)  How about I throw in a bonus round?  Yea, I knew you would go for it :)

Bonus – Delimited Strings

A delimited string is merely a huge string consisting of user defined separators.  I say user-defined because it’s entirely up to you how you want to translate that string from point A to point B.  Here I’ll show you an example of dealing with two delimited strings returned by your server.  If you know PHP, or most other languages, they all have a command similar to explode(), which takes data, and separates it by user-defined separators and arranges the data into a single variable array.  Well guess what, so does LSL, have a look at the two delimited strings we’re going to be dealing with.

The body of the http_response would be one of the following
string:partII:test
double:delimited-string:set

To the average LSL coder, this is a simple task to undertake but not everyone is an “average” LSL coder.  With LSL we use llParseString2List to break apart a user defined delimited string

http_response(key request_id, integer status, list metadata, string body)
	{
		if(request_id == http_request_id){  // Make sure we get what we asked for.
			list bodyList = llParseString2List(body,[":"],[]);
			string body0 = llList2String(bodyList,0); // Will return "string"
			string body2 = llList2String(bodyList,2); // Will return "test"
		}
	}

Well that’s all fine and dandy, but let’s say you got a multi-format delimited string, well that’s easy, just call llParseString2List twice, not that hard!

http_response(key request_id, integer status, list metadata, string body)
{
if(request_id == http_request_id){  // Make sure we get what we asked for.
list bodyList = llParseString2List(body,[":"],[]);
string body3 = llList2String(bodyList,0);  // Returns "double"
string body1 = llList2String(bodyList,1); //  Returns "delimited-string"
list body2List = llParseString2List(body1,["-"],[]);  // Turns body1 into a list of two values "delimited" and "string"
string body2List01 = llList2String(body2List, 1); // Returns "string"
}
}

Okay guys, I hope this can get most of you coders using this llHTTPRequest function, it’s really handy and has endless possibilities, both on the Second Life side, and the internet side.  I’ll probably expand this tutorial later to show you some cool tricks, but for now leave a comment and tell me what ya think :)

  • #1 written by Fede
    about 3 months ago

    Really, really useful. You save my day!
    Thanks!!!!!!!!
    From South America.

  • #2 written by Wili clip
    about 2 months ago

    Thanks for a great tutorial! Its really well written :)
    This will really help me to create better scripts or whole lsl/php/mysql systems.
    ^^

  • #3 written by Jay
    about 2 months ago

    Glad to help :)

  • #4 written by Jay
    about 2 months ago

    Cool, glad that I could help.