Learn Haxe

By: Nick Antonaccio
A Haxe Programming Tutorial for Absolute Beginners
Updated 2-26-2013

Contents:

1. Introducing Haxe
2. Getting Started: Downloading and Installing Haxe, Hello World
3. Some Basics of the Neko Api
3.1 Concatenation, Variables, Loops, and Conditions
3.2 More Neko Compilation Options
4. Compiling Haxe Programs for Different Target Platforms
4.1 PHP

1. Introducing Haxe

Haxe is a programming language and development toolkit that allows you to create computer programs of all types: desktop software, dynamic web site and server applications, rich mobile apps, and more. Haxe's blend of power, consistent cross-platform functionality, multimedia capability, compact size, easy installation, and more, enable it to gracefully replace many common tools such as PHP, Javascript, Java, Visual Basic, C, C++, Python, Perl, Ruby, Flash, wxWidgets, QT, and others, all with one simple paradigm.

Despite its power and broad usefulness, Haxe is easy to install and simple to use. It can be downloaded and put to use on all supported operating systems in just a few minutes, even over a slow dialup connection. Haxe includes GUI, network, graphics, sound, database, image manipulation, math, parsing, compression, and other functions built-in. No external modules, tool kits, or IDEs are required for any essential functionality. A useful online repository of free libraries is made available directly within the Haxe installation, to enable more powerful add-on features. Installing libraries is as simple as typing "haxelib install library-name". Haxe is easy enough for beginners to use, but powerful and rich enough for a wide variety of complex professional work. Haxe's language structure uses a traditional syntax familiar to anyone who's been exposed to Javascript, Java, C++, PHP, or other mainstream languages. Haxe is free and open source (libraries are BSD, compiler GPLv2+, neko runtime LGPLv2+).

Unlike other programming languages, code written in Haxe can be compiled to run on several different "targets". The Haxe language contains a complete Actionscript API which can be compiled directly to binary .swf (Flash) files by the blazing fast Haxe compiler, or to Actionscript code, or to HTML5 (using the free 3rd party Neash library), or to C++ code (using the free 3rd party NME library). This allows rich multimedia Haxe/Flash applications to run on any platform that has a C++ compiler - even those which don't support the Flash runtime or HTML5. NME apps can be cross-compiled from any Windows, Mac, or Linux machine, directly to any of the most popular mobile, desktop, and web platforms. NME apps are actually compiled and run in the native environments of Android, iPhone, WebOS, Windows, Mac, Linux, as well as HTML5, Flash, Adobe Air, etc., so they are fast. You can see a variety of mature, complex, and beautiful modern apps built with HaxeNME at http://www.haxenme.org/showcase/. Haxe source code can also be compiled - or rather - converted directly to code in other popular languages such as PHP, Javascript, Java, Actionscript, C++, and C#. This code can then be run directly by a PHP interpreter on your web site, by the Javascript interpreter in various browsers or Node.js, in desktop or server Java virtual machines, or compiled by any common C++ compiler for use in high performance applications. Reliable translation to all the most popular languages and runtimes allows Haxe generated code to be used by just about any commercial development team who relies on mainstream programming tools.

Haxe code can also be compiled to bytecode which is run by the Neko VM (a tiny, cross platform interpreter/virtual machine). Neko applications can be packaged directly as native Windows, Mac and Linux standalone executable programs (i.e., ".exe" files in Windows), so that users don't need to have any VM installed. Transferring data and sharing code between all these Haxe platforms is very simple using Haxe's built in remoting ability.

Writing code in Haxe allows you to deliver complete, compiled applications that run natively, and communicate easily between a truly enormous variety of development platforms and operating systems - more than any other language. It also allows you to deliver fully working source code that can be run and/or compiled by the most trusted and popular interpreted and compiled development tools in common use, all using a single consistent API and an extremely compact and powerful modern toolset.

2. Getting Started: Downloading and Installing Haxe, Hello World

To begin using Haxe, download and run the installer from:

http://haxe.org/download

To write Haxe code, you can choose to use an IDE such as flashdevelop or FDT, but Windows Notepad or any other plain text editor will work fine for now. To compile your first program, you need to create 2 separate text files. The first is the source code that defines your program's actions. Copy the following source code example into a new text file, and save it as Hello.hx:

class Hello {
    public static function main() {
        trace("Hello World!");
    }
}

Now copy the following compiler directives into a new text file, and save it as hello.hxml:

-main Hello
-neko Hello.n

Now double click on the icon for the hello.hxml file, in your file manager (i.e., if you saved these files on your desktop in Windows, go to your desktop and double click the hello.hxml icon). This will run the Haxe compiler, which will create a Neko version of your application, called Hello.n. Because the Neko VM is installed with Haxe, you can double click on the Hello.n file, and it will run just like an .exe file. Try it now.

3. Some Basics of the Neko Api

Neko is one of the targets supported natively by Haxe. The Neko virtual machine is a tiny code interpreter that runs the exact same way on Windows, Mac, and Linux. The Neko toolkit contains a built in packager to create stand alone executable programs that users can run, without any need to install Haxe or Neko. Neko is useful for interfacing with the operating system to perform file management, network operations, console interactions, database connectivity, CGI processing, and other fundamental desktop and server programming tasks.

http://haxe.org/api contains a list of all the functions contained in the Haxe programming language. If you've installed Haxe, you can also find a local copy of this documentation on your hard drive (in Windows, the default location is file:///C:/Motion-Twin/haxe/doc/index.html). Be sure to bookmark this page in your browser. You will use it regularly as you learn the Haxe language. Clicking on the "Neko" link in the Haxe API documentation will display all of the functions that are specific to the Neko virtual machine target. If you click the "Lib" link under the Neko menu, you'll see a variety of function specifications displayed (found online at http://haxe.org/api/neko/lib), along with a brief description of what each function does. Take a look at the "println" function:

static function println( v : Dynamic ) : Void

    Print the specified value on the default output followed by a newline
    character.

This specification tells you that the "println" function takes one input parameter (of type Dynamic), and returns a value of type Void. For our purposes, at this point the parameter (or "argument") is the most important part of the definition. The parameter is the data which must be fed the function, in order for it to perform some action. Here is how the println function is used in code:

neko.Lib.println("Hello World");

Notice that to use the println function, we need to tell Haxe where to find it in the API. Remember, we are looking in the Neko Api, in the Lib class, at the println function, so we reference that function in code using the dot syntax neko.Lib.println. The parameter for the println function (in this case, the text which gets printed), goes inside parentheses. Because the data being printed is a string of text, it needs to be enclosed in quotation marks. Notice also that the line ends with a semicolon. ALL lines of Haxe code end in a semicolon.

In order for your program to compile properly, it needs to be enclosed in a "class". The class name is just a label for the package of code that makes up your program. The class name of your program must match exactly the file name in which the code is saved. If you save your program in a file named Demo.hx, you must label your class "Demo". Your code must also be wrapped in a "main" function, as shown below. This is all boilerplate code. It's not complicated - just memorize the format, and for now, get used to wrapping every bit of code as shown below:

class Demo {
    public static function main() {
        neko.Lib.println("Hello World");
    }
}

Save the program above as Demo.hx (so that it matches the class label), and then save the following compiler directives as demo.hxml:

-main Demo
-neko Demo.n
# this is a compiler comment line - it doesn't do anything

Notice that the name of the class (and the file name of your program) is written on the line with the "-main" switch. The "-neko" switch on the second line tells the compiler to create a Neko application (i.e., this application will be compiled to run on the Neko VM target). Following the Neko directive on the second line is the name that the compiled bytecode file should be given, when created.

Double click the demo.hxml file in your file manager, and after a moment, you'll see the Demo.n file created, in the same folder. Double click the Demo.n file, and you'll see the program run. Unfortunately, all you'll see is a quick flash, as the single line program runs and then exits. In order to get the program to pause long enough for the user to see it run, take a look at the "getChar" function in the Haxe API documentation, under Neko -> IO -> File:

static function getChar( echo : Bool ) : Int

    Reads a character from the console. Can be used to cause a program
    to wait for input.

Here's how we'll use the function in code. Notice that its position in the API is given with dot syntax, and that the line ends with a semicolon. The false parameter tells the function not to display the character entered by the user. So, basically, all this function does is wait for the user to enter a keystroke before ending the program:

neko.io.File.getChar(false);

Add this line to our program above, and the code now looks like this:

class Demo {
    public static function main() {
        neko.Lib.println("Hello World");
        neko.io.File.getChar(false);
    }
}

Recompile the code by clicking demo.hxml, and then run it again by clicking Demo.n, and now you'll see the program display "Hello World", and then wait for you to click a key before ending. Try it now.

3.1 Concatenation, Variables, Loops, and Conditions

One of the most common tasks in programming is "concatenation", or joining together strings of text. In Haxe, strings are concatenated using the "+" symbol. You can print strings that are concatenated, right inside the function parameter's parentheses:

neko.Lib.println("Hello World " + "- I'm very happy to be here!");

That doesn't seem especially useful ... until you see how to use one more extremely important component in every programming language: variables. Variables allow you to give data a label, and then use that label to represent the data. Here's one way to assign variable labels to some text data in Haxe:

var first = "Hello World ";
var second = "- I'm very happy to be here!";

The word "first" now represents the text "Hello World", and the word "second" now represents the text "- I'm very happy to be here!". You can join together those two lines, and print them as follows:

neko.Lib.println(first + second);

Try saving the following full program in Demo.hx, click demo.hxml to compile it again, and then run the program by clicking Demo.n:

class Demo {
    public static function main() {
        neko.Lib.println("Hello World " + "- I'm very happy to be here!");
        var first = "Hello World ";
        var second = "- I'm very happy to be here!";
        neko.Lib.println(first + second);
        neko.io.File.getChar(false);
    }
}

Variables are extremely important in every type of programming because they represent changable ("variable") data. Data input by a user, read from a file, calculated and returned by a function, etc., can all be represented by variables. You choose a name to label the data, and from there on, any time you use the chosen label, you're actually referring to all the data it refers to. You could store the entire text for a book read from the hard drive into a variable labeled "book". You could read the file names contained in a folder on your hard drive and give that list the label "files". You could ask your user to select an MP3 file from your hard drive and assign it the variable label "song". In any of these cases, you can use the labels you've given the data to load, save, display, manipulate and otherwise process the represented data, all using a single variable word. Here's an example:

class Demo {
    public static function main() {
        var x = neko.io.File.getChar(false);
        neko.Lib.println("You typed:  " + x);
        neko.Sys.sleep(2);
    }
}

The example above assigns the variable "x" to the single character entered by the user, using the "getChar" function. That character's ASCII value (the standard number representation for the character) is then concatenated with the text "You typed: ", and that joined text is printed using the "println" function. Finally, the "sleep" function from the neko.Sys API is used to pause for 2 seconds before quiting the program.

You can put comments in your code to remind yourself of what certain parts of the program do. Multiline comments start with the characters /* and end with the characters */. Short comments on a single line begin with the characters //:

/* 
This is a multiline comment.
The compiler ignores it completely.
It's just here to remind the programmer
what the code does.

This program gets one character of
keyboard input from the user, displays
the ASCII code for that character, waits
2 seconds, and then ends.
*/

class Demo {                                   // name of the file
    public static function main() {            // standard boilerplate
        var x = neko.io.File.getChar(false);   // get keystroke from user
        neko.Lib.println("You typed:  " + x);  // join and print text
        neko.Sys.sleep(2);                     // wait 2 seconds then end
    }
}

Two more extremely important parts of all programming languages are loops and conditions. Loops allow the computer to repeat a given action many times. Conditional operations allow the computer to make "decisions" to perform selected operations based on whether a given condition is true or false. The "while" loop below executes the block of code enclosed in the following curly braces. The condition that the while loop checks for is enclosed in parentheses. In this case, the condition is set to "true", so this while loop simply repeats the following code endlessly. Inside the looped block of code, the same code from the above program is executed: a character is gotten from the user, and it's ASCII code is printed. The "if" condition inside the loop checks to see if the user has typed the character "x" (ASCII code 120). If that condition is true, the loop is stopped with the "break" function. After the loop has stopped, the following 2 lines of code are executed. The message "Goodbye!" is printed and the program waits 2 seconds before ending. Notice that the "=" sign is used to set variable names to a value, and the "==" symbol is used to test whether two values are equal:

class Demo {
    public static function main() {
        while(true) {             // repeat the following lines endlessly:
            var x = neko.io.File.getChar(false);
            neko.Lib.println("You typed:  " + x);
            if (x == 120) {break;};  // if the user types "x" end the loop
        }
        neko.Lib.println("Goodbye!");
        neko.Sys.sleep(2);
    }
}

The "for" loop is another very important repeating structure to learn. For takes a list of items and repeatedly does the same thing with/to each item in the list. The following code gets a list of file names in the current folder, and prints a nicely formatted directory listing:

class Demo {
    public static function main() {

        // This line of code just prints some message text for the user.
        // Notice that the function used here is not "println", but
        // "print".  The "print" function does not automatically print
        // a carriage return after each line.  Instead, the characters
        // "\n" are used to print a carriage return.  This provides more
        // control over how lines are printed out:

        neko.Lib.print("\n\nFolders contained in this file: \n");

        // This next line reads the file names from the current folder
        // and assigns the variable label "myfiles" to the list returned
        // by the "readDirectory" function (on most operating systems, the
        // current folder is labeled by the characters "./"):

        var myfiles = neko.FileSystem.readDirectory("./");

        // This final line uses a for loop to step through each of the
        // files in the "myfiles" list.  As the loop progresses through
        // each successive file in the myfiles list, the variable "file"
        // is assigned to the current element in the list.  Each time
        // through the loop, the current file name is concatenated with
        // some text containing a newline character, and 4 empty spaces.
        // This makes each file name print indented on a separate line:

        for (file in myfiles) neko.Lib.print("\n    " + file);

        // Print 2 blank lines, then wait for the user to press a key to
        // end the program:

        neko.Lib.print("\n\n");
        neko.io.File.getChar(false);
        neko.Lib.println("Goodbye!");
        neko.Sys.sleep(2);            
    }
}

The following example demonstrates the common technique of "incrementing" a counter variable. This creates a numbered listing of the files in the previous example. There are only 3 lines changed:

class Demo {
    public static function main() {

        // create a counter variable:

        var counter = 1;

        neko.Lib.print("\n\nSelect a file to read: \n");
        var myfiles = neko.FileSystem.readDirectory("./");

        // Print the counter variable with each file name, and add 1
        // to it (increment it) each time through the loop, so that
        // a different successive number is given to each file name.
        // Notice that there are now 2 actions performed during each
        // iteration of the for loop, so they are enclosed in a "block"
        // (surrounded by curly braces), and put on separate lines, each
        // ending with a semi colon:

        for (file in myfiles) {
            neko.Lib.print("\n    " + counter + " - " + file);
            counter++ ;
        }
        neko.Lib.print("\n\n");
        neko.io.File.getChar(false);
        neko.Lib.println("Goodbye!");
        neko.Sys.sleep(2);            
    }
}

The following code takes the previous example, and extends it with several functions which allow the user to type the number of a desired file. The text in the chosen file is then read and printed:

class Demo {
    public static function main() {

        // All the code inside this while loop repeats endlessly,
        // until stopped:

        while (1==1) {
            var counter = 1;
            neko.Lib.print("\n\nSelect a file to read: \n");
            var myfiles = neko.FileSystem.readDirectory("./");
            for (file in myfiles) {
                neko.Lib.print("\n    " + counter + " - " + file);
                counter++ ;
            }
            neko.Lib.print('\n    "q" - quit');            
            neko.Lib.print("\n\nFile Choice:  ");

            // These 2 lines get a line of text input from the user
            // and stores it in the variable "filechoice":

            var stdin : neko.io.FileInput = neko.io.File.stdin();
            var filechoice : String = stdin.readLine();

            // This line exits the program if the user has entered
            // the letter "q":

            if (filechoice == "q") neko.Sys.exit(1);

            // This loop increments the variable "i" each time
            // through, from the number 0 to the number of files in
            // the directory list: 

            for (i in 0...(myfiles.length + 1)) {

            // The "filechoice" variable above is created as a String
            // (a series of text characters).  In order to compare the
            // numerical value contained in that text to the integer
            // contained in the "i" variable, the "parseInt" function
            // is used to convert ("cast") the string value to an
            // integer:

                if (i == Std.parseInt(filechoice)) {

                    // This println function prints the name of the
                    // file selected by the user, and the contents
                    // read from that file.  Notice that the index
                    // number of the selected file is referenced
                    // using i - 1.  That's because list indexes in
                    // Haxe are 0 based (the first item in a list
                    // is item 0, the second item is at index 1,
                    // etc.):

                    neko.Lib.println(
                        "\nFile:  " + myfiles[i - 1] +
                        "\n\n" + neko.io.File.getContent(myfiles[i-1])
                        + "\n\n\nPress any key to continue..."
                    );
                    neko.io.File.getChar(false);
                }
            }
        }
    }
}

Here's the entire program above, without comments. It's a simple little menu based file reader - our first practical app in Haxe/Neko:

class Demo {
    public static function main() {
        while (1==1) {
            var counter = 1;
            neko.Lib.print("\n\nSelect a file to read: \n");
            var myfiles = neko.FileSystem.readDirectory("./");
            for (file in myfiles) {
                neko.Lib.print("\n    " + counter + " - " + file);
                counter++ ;
            }
            neko.Lib.print('\n    "q" - quit');            
            neko.Lib.print("\n\nFile Choice:  ");
            var stdin : neko.io.FileInput = neko.io.File.stdin();
            var filechoice : String = stdin.readLine();
            if (filechoice == "q") neko.Sys.exit(1);
            for (i in 0...(myfiles.length + 1)) {
                if (i == Std.parseInt(filechoice)) {
                    neko.Lib.println(
                        "\nFile:  " + myfiles[i - 1] +
                        "\n\n" + neko.io.File.getContent(myfiles[i-1])
                        + "\n\n\nPress any key to continue..."
                    );
                    neko.io.File.getChar(false);
                }
            }
        }
    }
}

Now is a good time to read the tutorials at http://haxe.org/doc/neko. Those tutorials demonstrate how to use more functions in the Neko API to perform file I/O operations, access databases, send data across network sockets, access zip and tar compressed files, created multitasking applications, and more.

3.2 More Neko Compilation Options

Another way to run the Haxe compiler is to open your operating system's command line (in Windows, click Start -> All Programs -> Accessories -> Command Prompt), change directories to the folder containing Demo.hx (cd C:\Users\User\Desktop\), and enter the following command:

haxe -main Demo -neko Demo.n

You can also type the name of the .hxml file at the command line, to run it:

demo.hxml

The benefit of compiling from the command line is that you can read any errors generated during the compile process (when clicking an .hxml file icon, the errors will flash and close too quickly to be read). If you're using Windows OS, take a look at dosdrop for a small program that makes it easier to open the Windows console directly to the folder where your .hx code and .hxml files are located.

To create a stand alone executable from the Demo.n file above, go to your operating system's command line, change to your work folder (as above), and type in "nekotools boot Demo.n" - REPLACE Demo.n with the folder path and filename of the Neko file you've created (i.e., something like C:\Users\User\Desktop\Demo.n for the example above). This will create an executable file that can be run on any machine, without needing to install Haxe or Neko. You can compile the same code on Windows, Mac, or Linux, and a stand alone application will be created that will run on any other Windows, Mac, or Linux computer, respectively.

4. Compiling Haxe Programs for Different Target Platforms

4.1 PHP

The Neko API is particularly useful for creating console and server applications that interact with the OS and which perform basic data management operations. If that's all that Haxe could do, it would be a very useful programming language/tool. But we've only just scratched the surface of Haxe's capabilities.

The PHP target of the Haxe compiler is useful for creating web based applications. You'll notice that many, but not all of the functions in the Neko API are also available in the PHP API, and visa versa. All of the functions in the core Haxe API can be used regardless of compilation target (i.e., you can use the functions in the array, list, math, string, etc. APIs, whether you're creating an application to run in the Neko VM, PHP, Flash, etc.).

PHP is the most popular scripting language for web site development. It's free and open source, and its functions are geared towards manipulating data on web sites, such as info submitted by HTML forms. Most web hosting companies offer free access to the PHP interpreter, and many "AMP" software packages containing the Apache web server, MySQL database, and PHP interpreter can be downloaded for free, to easily install a complete server setup on any mainstream desktop operating system. To run applications written with Haxe/PHP, you'll need a working web server. http://www.zymic.com offers free hosting accounts with PHP and all the other tools you'll need to create live, dynamic web sites on the Internet. You can also use The Uniform Server to test Haxe/PHP on your desktop/laptop computer. If you use any other free AMP software, just be sure that PHP version 5.1.x or higher is installed, as it's required for Haxe/PHP applications to run properly.

To create your first Haxe/PHP application, you'll need to create 2 new text files, just like you did for the Neko target. First, copy the following code and save it to a file named Demophp.hx. Notice again that the class name in the code must match the file name (Demophp):

class Demophp {
    static function main() {  
        php.Lib.print('Hello World!');
    }
}

Second, save the following compiler directives to demophp.hxml, in the same folder as Demophp.hx. Notice that the -php flag is given, to tell Haxe to compile to the PHP target. The "www" after the -php flag tells Haxe to put the compiled PHP files into a folder named www (the folder will be created if it doesn't exist). The -main flag is the same "Demophp" class name we used to name the source code file above:

-php www
-main Demophp

Click the demophp.hxml file, and your PHP code files will be created in the www folder (as a subdirectory of wherever your demophp.hxml and Demophp.hx are located). Use your favorite FTP program, or your web host's file manager to copy (upload) all of the files and subfolders from the newly compiled www folder, into the publicly viewable folder on your web server (the publicly viewable root folder is typically named "public_html" or "www"). Be sure that the subdirectory folder structure of the compiled www folder is maintained (i.e., the www folder contains a folder named "lib", which in turn contains a folder named "php", and all those folders contain a specific set of .php files). If you're using a local AMP server to test your PHP files, just copy/paste the files to the local folder which is used to serve files, or move your .hx and .hxml files to your server folder, and edit/compile them there directly. If you're using a Linux or Unix hosting server, make sure that file permissions are set properly for your PHP files (execute permissions of "755" will work for most servers). There are many tutorials available online which explain how to upload files and set file permissions. Talk to the tech support service at your web host company, or ask questions in the online forums, if you have questions.

To run your new PHP program, open your browser and surf to the index.php page at the location where you've uploaded the compiled files. For example, if you're using an AMP server on your local computer, and you've saved your files to the root publicly viewable folder, you'll most likely surf to http://localhost/index.php to see your program run. If you've uploaded the files to an online web host, go to http://yourdomain.com/index.php (or http://yourdomain.com/folder/index.php if you uploaded the files into a subfolder on the server), and you'll see the program run live on the Internet.

Now take a look at the Demophp.hx source code file we created above. Notice that the "php.Lib.print" function is used to print text to the visitor's browser. You can print any content you want to appear on your web page, using this function. Edit the Demophp.hx file to print the following HTML source, recompile it by clicking the demophp.hxml file, re-upload (re-copy) the newly compiled PHP files to your server, and then refresh the index.php page in your browser, and you should see a page that looks just like http://haxe.us/basic_html_demo.html:

class Demophp {
    static function main() {  
        php.Lib.print('

    <h1>This is some header text</h1>
    <h3>This header text is smaller</h3>
    In HTML, all spaces, tabs, newlines and other white spaces
    are compressed (i.e., this text is all printed on the same
    line, and wrapped to the length of the screen, and these
    spaces             are all compressed to one space.  If
    you want to explicitly display a certain number of spaces,
    use these characters:  &nbsp; &nbsp;  For newlines (carriage
    returns), use the "br" tag: <br><br>
    You can also use "p" tags to create separate lines.
    <p>To adjust text size and color, use the "font" tag:</p>
    <font size=1 color=blue>Little blue text</font><br>
    <font size=6 color=red>Big red text</font><br><br>
    To display a link to a web site, use the "a" tag: <br><br>
    <a href="http://yahoo.com">yahoo.com</a><br><br>
    To display images, use the "img" tag: <br><br>
    <img src="http://adopt-cats.com/header.jpg"><br><br>
    To make an image link to a URL, use "img" and "a": <br><br>
    <a href="http://adopt-cats.com" target=_blank>
        click the image:<br>
        <img src="http://adopt-cats.com/header.jpg">
    </a><br><br>
    <strong>This text is bolded.</strong><br><br>
    <pre>
        The "pre" tag displays preformatted text.
        Spaces, tabs, newlines, etc. are kept intact.
    </pre>
    You can add a horizontal separator line with the "hr" tag:
    <br><br><hr width=80%><br>
    Center anything on a page with the "center" tag: <br><br>
    <center>Centered Text</center><br>
    Tables are used to display rows and columns of data.  They
    can also be used to align portions of an HTML page in certain
    areas of the screen (i.e., to layout menu bar areas, headers,
    main content areas, and footers): <br><br>
    <center>
        <table border=0 cellpadding=10 width=80%>
            <tr>
                <td width=33%>"tr" tags</td>
                <td width=33%>are</td>
                <td width=33%>rows</td>
            </tr>
            <tr>
                <td width=33%>"td" tags</td>
                <td width=33%>are</td>
                <td width=33%>columns</td>
            </tr>
            <tr>
                <td valign=top colspan=2 bgcolor=#CCCCCC>
                    You can set "td"s to span as many columns as
                    needed, using the "colspan" setting, and you
                    can use the "valign" property to set where
                    in the cell text is placed.  "bgcolor" sets
                    the cell\'s background color.
                </td>
                <td width=20 bgcolor=#000000>
                    <font color=white size=2>
                        You can set size properties of all different
                        parts of the table, using either percentage
                        or pixel values.
                    </font>
                </td>
            </tr>
        </table>
    </center>
    Try resizing the page to see how centering, text wrapping and
    table layouts work.

        ');
    }
}

Learning HTML is absolutely essential if you want to create any PHP programs. It's used to layout pages on the Internet. There are an endless supply of free HTML tutorials around the Internet. Use Google to find a few, and dig in. The example above demonstrates how to use the most basic tags. Here are a couple more examples of simple page layouts you can use. Notice where "Page Content" is pointed out in each example. Also, notice that all the printed HTML is enclosed in single quotes. When single quotes are required within the HTML, they're preceded by the escape character "\". Edit and recompile the Demophp.hx file, copy the PHP files to your server, and refresh index.php in your browser to see the following examples:

class Demophp {
    static function main() {  
        php.Lib.print('

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
      <TITLE>Generic HTML Page With Tables</TITLE>    
      <META 
            http-equiv=Content-Type content="text/html; 
            charset=windows-1252"
      >
    </HEAD>    
    <BODY bgColor=#CCCCCC>
        <TABLE align=center background="" border=0 
            cellPadding=20 cellSpacing=2 height="95%" width="85%"
        >
            <TR>
                <TD background="" bgColor=white vAlign=top>
                    YOUR PAGE CONTENT GOES HERE.
                </TD>
            </TR>
        </TABLE>
        <TABLE align=center background="" border=0 cellPadding=2
            cellSpacing=2 width="85%" height="5%"
        >
            <TR>
                <TD cellPadding=2 bgColor=#000000 height=5>
                    <P align=center>
                        <FONT color=white size=1>
                            Copyright  2010 Yoursite.com.
                            All rights reserved.
                        </FONT>
                    </P>
                </TD>
            </TR>
        </TABLE>
    </BODY>
    </HTML>

        ');
    }
}

Here's a simple table based page layout, without a menu:

class Demophp {
    static function main() {  
        php.Lib.print('

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
    <TITLE>Table Based Page Layout, No Menu</TITLE>
    <META http-equiv=Content-Type content="text/html;
         charset=windows-1252"
    >
    <META 
        HTTP-EQUIV="Page-Enter" 
        CONTENT="RevealTrans(Duration=2,Transition=14)"
    >
    <STYLE TYPE="text/css">
        a:hover {
            color: blue;
            text-decoration: underline;
            background: #F9EDED
        }
    </STYLE>
</HEAD>
<BODY bgColor=#000000>
<TABLE align=center background="" border=0 cellPadding=2 cellSpacing=2
    height="100%" width="95%"
>
    <TR>
        <TD background="" bgColor=lightgrey vAlign=top>
            <TABLE background="" border=0 cellPadding=2 cellSpacing=2
                height="100%" width="100%"
            >
                <TR>
                    <TD background="" bgColor=black height=10>
                        <P align=center>
                            <a href="./index.html">
                                <IMG align=baseline alt="HEADER IMAGE"
                                    border=0 hspace=0 src="header.jpg"
                                >
                            </a>
                        </P>
                    </TD>
                </TR>
                <TR>
                <TD background="" vAlign=top>
                    <TABLE bgColor=#ffffff border=0 cellPadding=2
                        cellSpacing=2 height="100%" width="100%"
                    >
                        <TR> 
                            <TD bgColor=lightgrey height=20>
                                <center></center>
                            </TD>
                            <TD bgColor=lightgrey height=10 width="90%">
                                <center>
                                    <a href="./Home.html">
                                        Home
                                    </a> : Contact
                                </center>
                            </TD>
                            <TD bgColor=lightgrey height=20>
                                <center></center>
                            </td>
                        </TR>
                        <TR>
                            <TD background="" colSpan=3 height="100%">
                                <TABLE border=0 cellPadding=15 
                                    cellSpacing=2 height="100%"
                                    width="100%"
                                >
                                    <TR>
                                        <TD background="" vAlign=top>
                                            YOUR PAGE CONTENT GOES HERE
                                        </TD>
                                    </TR>
                                </TABLE>
                            </TD>
                        </TR>
                    </TABLE>
                </TD>
            </TR>
            <TR>
                <TD background="" bgColor=#000000 height=5>
                    <P align=center>
                        <FONT color=white size=1>
                            Copyright  2010 This Web Site.
                            All rights reserved.
                        </FONT>
                    </P>
                </TD>
            </TR>
        </TABLE>
    </TD>
</TR>
</TABLE>
</BODY>
</HTML>

        ');
    }
}

The following table based page layout has a menu bar on the right side:

class Demophp {
    static function main() {  
        php.Lib.print('

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
    <TITLE>Table Based Layout Template, With Menu</TITLE>
    <META http-equiv=Content-Type content="text/html;
        charset=windows-1252"
    >
    <META HTTP-EQUIV="Page-Enter" 
        CONTENT="RevealTrans(Duration=2,Transition=12)"
    >
    <STYLE TYPE="text/css">
        a:hover {
            color: blue; 
            text-decoration: underline; 
            background: #F9EDED
        }
    </STYLE>
</HEAD>
<BODY bgColor=#000000>
    <TABLE align=center background="" border=0 cellPadding=2
        cellSpacing=2 height="100%" width="95%"
    >
        <TR>
            <TD background="" bgColor=lightgrey vAlign=top>
                <TABLE background="" border=0 cellPadding=2
                    cellSpacing=2 height="100%" width="100%"
                >
                    <TR>
                        <TD background="" bgColor=lightgrey width="23%">
                            <TABLE bgColor=white border=1 cellPadding=10
                                cellSpacing=2 height="100%" width="100%">
                                <TR>
                                    <TD>
                                        <P align=center>
                                            <FONT color=Black size=3>
                                               <STRONG>
                                                  <a href="index.html">
                                                     Home
                                                  </a>
                                               </STRONG>
                                            </FONT>
                                        </P>
                                    </TD>
                                </TR>
                            </TABLE>
                        </TD>
                        <TD background="" bgColor=black height=10>
                            <P align=center>
                                <a href="./index.html"> 
                                    <IMG 
                                        alt="HEADER IMAGE" 
                                        src="./header.jpg"
                                    >
                                </a>
                            </P>
                        </TD>
                    </TR>
                    <TR>
                        <TD vAlign=top>
                            <TABLE background="" bgColor=black border=0
                                cellPadding=2 cellSpacing=2 height="100%"
                                width="100%"
                            >
                                <TR>
                                    <TD background="" height=20>
                                        <P align=center>
                                            <FONT color=white size=2>
                                                <STRONG>Menu</STRONG>
                                            </FONT>
                                        </P>
                                    </TD>
                                </TR>
                                <TR>
                                    <TD bgColor=lightgrey vAlign=top>
                                        <P align=center>
                                            <BR>
                                            <TABLE width=95%>
    <CENTER>
        <TR>
            <TD style="border: solid" 
                onmouseOver="this.bgColor=\'#FFFFFF\'";
                onmouseOut="this.bgColor=\'#D3D3D3\'";
            > 
                <CENTER>
                    <FONT face="Arial, Verdana, MS Sans Serif" size=1>
                        <A HREF="./page1.html">
                            Page1
                        </A>
                    </FONT>                          
                </CENTER>
            </TD>
        </TR>
        <TR>
            <TD style="border: solid"
                onmouseOver="this.bgColor=\'#FFFFFF\'";
                onmouseOut="this.bgColor=\'#D3D3D3\'";
            > 
                <CENTER>
                    <FONT face="Arial, Verdana, MS Sans Serif" size=1>
                        <A HREF="./page2.html">
                            Page2
                        </A>
                    </FONT>
                </CENTER>
            </TD>
        </TR>
    </CENTER>
                                            </TABLE>
                                        </P>
                                    </TD>
                                </TR>
                            </TABLE> <br>
                        </TD>
                        <TD background="" vAlign=top>
                            <TABLE bgColor=#ffffff border=0 cellPadding=2
                                 cellSpacing=2 height="100%" width="100%"
                            >
                                <TR>
                                    <td bgColor=lightgrey height=20>
                                        <center></center>
                                    </td>
                                    <td bgColor=lightgrey height=20
                                        width="90%"
                                    >
                                        <FONT size=3>
                                            <center>Home</center>
                                        </font>
                                    </td>
                                    <td bgColor=lightgrey height=20>
                                        <center></center>
                                    </td>
                                </TR>
                                <TR>
                                    <TD colSpan=3 height="100%">
                                        <TABLE border=0 cellPadding=15 
                                            cellSpacing=2 height="100%"
                                            width="100%"
                                        >
                                            <TR>
                                                <TD vAlign=top>
                                                    YOUR CONTENT GOES HERE
                                                </TD>
                                            </TR>
                                        </TABLE>
                                    </TD>
                                </TR>
                            </TABLE>
                        </TD>
                    </TR>
                    <TR>
                        <TD background="" bgColor=#d3d3d3 height=5>
                            <P align=center></P>
                        </TD>
                        <TD background="" bgColor=#000000 height=5>
                            <P align=center>
                                <FONT color=white size=1>
                                    Copyright  2010 This Web Site.
                                    All rights reserved.
                                </FONT>
                            </P>
                        </TD>
                    </TR>
                </TABLE>
            </TD>
        </TR>
    </TABLE>
</BODY>
</HTML>

        ');
    }
}

The pages above are just static HTML - they can only display a single, unchanging display, and you don't need a scripting language to display them (just save the HTML in a .html file on your server). The real benefit of Haxe/PHP is that you can use the entire power of the Haxe language to process data, and print dynamically changable output for visitors to see, respond to user input, and interact with visitors. Here's a simple program that displays all the images in a folder on your web server. Recompile, copy to the server, and copy a collection of images to the same folder as index.php. This program will create an HTML page that displays all the images, however many there are, every time it's run (i.e., every time a visitor opens index.php):

class Demophp {
    static function main() { 

        // Print some header HTML:

        php.Lib.print(
            '<HTML><HEAD><TITLE>Photos</TITLE></HEAD><BODY><CENTER>'
        );

        // Read the names of the files in the current folder to an
        // array (list) referred to by the variable "folder", and
        // set a counter variable to 0: 

        var folder = php.FileSystem.readDirectory("./");
        var count = 0

        // For each file in the folder list, if the file isn't named
        // "index.php", print the HTML to disply the image:

        for (file in folder) {
            if (file != "index.php") {
                print '<BR><img src="' + file + '">'
                count++
            }
        }

        // Print the total image count, plus some closing HTML:

        php.Lib.print(
            '<BR>Total Images: ' + count + '</CENTER></BODY></HTML>'
        );
    }
}

4.1.1 HTML Forms

User input in web applications can be accomplished using HTML "forms". Form fields, textareas, check boxes, dropdown selectors, submit buttons, etc., take the place of familiar GUI widgets in desktop applications, to get data from users. To understand how forms work, edit Demophp.hx to contain the following code (compile and copy to your server). Pay particular attention to the "php.Web.getParams" function:

class Demophp {
    static function main() {  
        var params = php.Web.getParams();
        php.Lib.print(params);
    }
}

Now go to http://yourdomain.com/index.php?name=bob&id=1234567 ("yourdomain.com" will be "localhost" if you're running your server on a local computer). Notice that this URL is just the URL of your PHP program, followed by a question mark, followed by "name=bob" and "id=1234567", with those two pieces of data separated by an "&" symbol. Try going to http://yourdomain.com/index.php?name=john&id=7654321 , and see the PHP program print out John's name and ID. You can use that format to input ANY data you want to the PHP program. Here's a slightly more useful example that demonstrates how to use the data returned by the "php.Web.getParams" function:

class Demophp {
    static function main() {  
        var params = php.Web.getParams();

        // Check to see if the name and id data fields have data
        // submitted.  If so, assign the variables "name" and "id"
        // the submitted data values.  If not, assign the text "none"
        // to those variables:

        var nm = params.exists('name') ? params.get('name') : 'none';
        var id = params.exists('id') ? params.get('id') : 'none';

        // Print the data refered to by the variables:

        php.Lib.print('Name: ' + nm + '<BR><BR> ID: ' + id);
    }
}

Copy the following HTML form into a file named form_example.html, and save it to your server. Notice that the "action" link in the code below is pointing to the URL of the index.php script that we've already created:

<FORM ACTION="index.php">
    Name:  <INPUT TYPE="TEXT" NAME="name" SIZE="25">
    ID:  <INPUT TYPE="TEXT" NAME="id" SIZE="25">
    <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">
</FORM>

Now go to http://yourdomain.com/form_example.html , fill out and submit the form, and pay attention to the link to which you are transferred, as well as the data printed by the script. It works exactly the same as the links that we hand coded above (i.e., the above form transfers you to http://yourdomain.com/index.php?name=john&id=7654321). The form just provides a useful interface that your web site visitors can use to enter their name and ID (instead of having to type in an archaic URL).

The following script saves the name and ID of every visitor who submits the form, to the file "visitors.html" on your web server, and then prints out a neatly formatted list of every previous visitor. This should start to give you some idea of how PHP can become useful - you can write ANY submitted data to your web server, retrieve it, manipulate it, and display it to your visitors:

class Demophp {
    static function main() {  
        var params = php.Web.getParams();
        var nm = params.exists('name') ? params.get('name') : 'none';
        var id = params.exists('id') ? params.get('id') : 'none';

        // Create a new data file, if it doesn't already exist:

        var fname = "visitors.html";
        if (!php.FileSystem.exists(fname)) {
            var fout = php.io.File.write(fname, false);
            fout.close();
        }

        // Read all the text currently contained in the visitors.html
        // file:

        var fileContent = php.io.File.getContent(fname);

        // Append the submitted submitted name and ID data, to the
        // above file content, along with some HTML tags, and write
        // the new data back to the visitors.html file:

        var newContent = 'Name: ' + nm + ' &nbsp; &nbsp; ' +
            'ID: ' + id + '<BR>' + fileContent;
        var fout = php.io.File.write(fname, false);
        fout.writeString (newContent);
        fout.close();

        // Print out the content of the visitors.html file:

        php.Lib.print(
            'The following visitors have logged into this page:
            <br><br>' + newContent
        );
    }
}

As it stands, our example program is made up of 2 separate files on the web server: the file containing the HTML form, and the file containing the Haxe/PHP code. We can combine the 2 files into a single script by simply having the program print the HTML form, with an "action" URL in the form which points directly back to the script. The script can then check whether or not the user has entered some data (i.e., if submitted values are not "none", some data has been entered by the user). If so, it will perform the actions currently in the demophp.hx script above. Edit/recompile/upload your demophp.hx file as follows, and then refresh http://yourdomain.com/index.php to see it run:

class Demophp {
    static function main() {  
        var params = php.Web.getParams();
        var nm = params.exists('name') ? params.get('name') : 'none';
        var id = params.exists('id') ? params.get('id') : 'none';

        // If no data has been submitted by the user (i.e., they are
        // just arriving at the web page), print the HTML form:

        if ((nm == "none") && (id == "none")) {
            php.Lib.print ('
                <FORM METHOD="post" ACTION="./index.php">
                    Name:  <INPUT TYPE="TEXT" NAME="name" SIZE="25">
                    ID:  <INPUT TYPE="TEXT" NAME="id" SIZE="25">
                    <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">
                </FORM>
            ');
            php.Sys.exit(1);
        }

        // Otherwise (if data has been submitted), do the script from
        // above:

        var fname = "visitors.html";
        if (!php.FileSystem.exists(fname)) {
            var fout = php.io.File.write(fname, false);
            fout.close();
        }
        var fileContent = php.io.File.getContent(fname);
        var newContent = 'Name: ' + nm + ' &nbsp; &nbsp; ' +
            'ID: ' + id + '<BR>' + fileContent;
        var fout = php.io.File.write(fname, false);
        fout.writeString (newContent);
        fout.close();
        php.Lib.print(
            'The following visitors have logged into this page:
            <br><br>' + newContent
        );
        php.Sys.exit(1);
    }
}

Notice the "php.Sys.exit" function after the printed HTML form. If the user is just coming to the page (i.e., has not yet submitted any data), we want them to see the input form, and nothing else, so we print the form and then quit the script. When the user fills out the form and clicks the submit button, the action points directly back to this same script, so the script runs again, this time with some submitted data, and only the second half of the program gets executed. Study that logic until it makes sense. All your PHP programs can follow this simple pattern. In larger programs you'll likely just have more input options to decipher (more forms to print, more "if" evaluations, etc.) and perhaps some more complex data manipulations to perform.

Here's an example that allows the user to choose between options from a dropdown box in an HTML form, and then responds to that input appropriately. Notice that the dropdown code is dynamically created, instead of being typed in explicitly. This code allows you to more easily create drop down boxes containing many items (lists of times, colors, dates, etc.), just by putting them in an array (a list of items):

class Demophp {
    static function main() {  
        var params = php.Web.getParams();
        var optn = params.exists('opt') ? params.get('opt') : 'none';

        // Do different things, depending on the option submitted by
        // the user:

        if (optn == "option1") {
            php.Lib.print ('Now Doing Code For Option 1');
            php.Sys.exit(1);
        }
        if (optn == "option2") {
            php.Lib.print ('Now Doing Code For Option 2');
            php.Sys.exit(1);
        }
        if (optn == "option3") {
            php.Lib.print ('Now Doing Code For Option 3');
            php.Sys.exit(1);
        }

        // If none of the above cases is true (i.e., the user is just
        // visiting the page and hasn't yet selected an option), print
        // the following HTML form by default.

        // 3 options given to visitor:

        var options = ["option1" , "option2" , "option3"]; 
        php.Lib.print ('
            <FORM ACTION="./index.php">
            <select NAME="opt">
        ');
        for (o in options) {
            php.Lib.print ('<option>' + o);
        }
        php.Lib.print ('
            </option> </select>
            <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">
            </FORM>
            </BODY></HTML>
        ');
        php.Sys.exit(1);
    }
}

4.1.2 POST Data

The method that you've seen so far for transferring data from HTML forms to PHP scripts is called "GET". It uses the "?" and "&" symbols to transfer data to a URL using the format http://yourdomain.com/index.php?label1=data1&label2=data2&label3=data3. The submitted data is visible in the user's browser address bar and is saved in their browsing history, so it's not secure in any way. There is also a limit to how much data can be sent using the GET method (that varies between browsers and web servers, but it's typically limited to a small number of pages of text). If you want to send large amounts of data, or if you don't want visitors to easily see data which is being transferred by your web application, you must use the "POST" method. Post data is NOT visible in the address bar of the user's browser. To use the POST method of data submission simply add the following text to your HTML forms: method="POST" . Try compiling and testing the example below to see just how much data can be set via a POST request. You could use this example to accept large form message submission from users on your web site. Simple variations of this script could also be used to edit text files on your server:

class Demophp {
    static function main() {  
        var params = php.Web.getParams();
        var nm = params.exists('name') ? params.get('name') : 'none';
        var ml = params.exists('mail') ? params.get('mail') : 'none';
        var ms = params.exists('mesg') ? params.get('mesg') : 'none';
        if ((nm == "none") && (ml == "none") && (ms == "none")) {
            php.Lib.print ('
                <FORM method="POST" action="index.php">
                    Name:<BR><INPUT type="TEXT" name="name"><BR><BR>
                    Email:<BR><INPUT type="TEXT" name="mail"><BR><BR>
                    Message:<BR>
                        <TEXTAREA cols="75" rows="5" name="mesg">
                        </TEXTAREA><BR><BR>
                    <INPUT type="SUBMIT" name="Submit" value="Submit">
                </FORM>
            ');
            php.Sys.exit(1);
        }
        var fname = "data.txt";
        if (!php.FileSystem.exists(fname)) {
            var fout = php.io.File.write(fname, false);
            fout.close();
        }
        var fileContent = php.io.File.getContent(fname);
        var newContent = 'Name: ' + nm + ' &nbsp; &nbsp; ' +
            'ID: ' + ml + '<BR>' + ms + '<BR><BR>'+ fileContent;
        var fout = php.io.File.write(fname, false);
        fout.writeString (newContent);
        fout.close();
        php.Lib.print(
            'The following messages have been entered:
            <br><br>' + newContent
        );
        php.Sys.exit(1);
    }
}

See easiestprogramminglanguage.com for another interesting language to look at, and freeconsignmentsoftware.com for a project written in it.

created 27-Feb-2013