Archive for November, 2009

Create simple WordPress plugins

Creating a Simple WordPress Plugin

You can use this as a code snippet for your projects. I am going to create a simple plugin that does nothing but display “Hello World”. I’ll leave the actual functionality of the plugin to you

Create a new php file in your plugin directory called my-hello-world.php, and type the following plugin code:

<?php
/*
Plugin Name: Hello World
Plugin URI: http://lonewolf-online.net/
Description: Sample Hello World Plugin
Author: Tim Trott
Version: 1
Author URI: http://lonewolf-online.net/
*/function sampleHelloWorld()
{
echo “<h2>Hello World</h2>”;
}
?>

The lines inside /* and */ are used by WordPress to find out about the plugin. We have one function called sampleHelloWorld which does exactly that.

Now, traditionally we would have had to open up the sidebar of the theme you are using, find the location of where you want the Hello World displayed, and hard code the function in. Upload to the server and test. If for some reason there is a problem with your plugin (or a third party plugin) then your site would almost certainly stop working. Changing the location from the left to the right sidebar means editing both files accordingly. This isn’t very good.

Widgets

Widgets take away the need for editing the sidebar files of a theme and allow for a drag and drop interface in the admin panel. Lets have a look at how we can wiget enable our plugin.

Open up the Hello World plugin file again and add these lines:

function widget_myHelloWorld() {
?>
<h2 class=”widgettitle”>My Widget Title</h2>
<?php sampleHelloWorld(); ?>
<?php
}function myHelloWorld_init()
{
register_sidebar_widget(__(‘Hello World’), ‘widget_myHelloWorld’);
}
add_action(“plugins_loaded”, “myHelloWorld_init”);

The first function here is what will be displayed on the sidebar when its set-up correctly. Notice that we are calling on our old function. This is upgrading the existing plugin to be widget enabled. You can if you like replace the function call with the function statements and combine the two functions.

The second function is called by WordPress when the plugin is activated. It calls a WordPress function that will register a new widget which will be called “Hello World” which will call our new widget function.

Add action just tells WordPress to call myHelloWorld_init when the plugin is loaded.

Enhancements for Theme Compatibility

While this widget will function fine, we can make some improvements to enable greater theme compatibility – not everyone uses the same themes as you test on.

WordPress will pass parameters to your widget, which contain information about the sidebar and the CSS classes. We should process these parameters and output the correct tags, or you risk breaking some themes.

The first thing we need to do is change our sampleHelloWorld function so that it will accept parameters, then to process these parameters into variables. This is done using the extract function.

function widget_myHelloWorld($args) {
extract($args);
?>
<h2 class=”widgettitle”>My Widget Title</h2>
<?php sampleHelloWorld(); ?>
<?php
}

These two lines will allow us to reference some variables and output correct html structure for the theme being used. The most important variables are before_widget, after_widget, before_title and after_title. Previously we have surrounded the widget title with a hard coded H2 tag with a css class widgettitle, but many themes do not support these tags. They may use a div, or a h1 or a span, so we need our widget to be flexible.

function widget_myHelloWorld($args) {
extract($args);
echo $before_widget;
echo $before_title;?>My Widget Title<?php echo $after_title;
sampleHelloWorld();
echo $after_widget;
}

These changes will allow our plugin to use the same tags as the theme author informs us we need to use, and will allow your widget to look the same as the other widgets in the sidebar.

To configure these options inside a theme, please see the section below on theme support.

Complete Plugin:

<?php
/*
Plugin Name: Hello World
Plugin URI: http://lonewolf-online.net/
Description: Sample Hello World Plugin
Author: Tim Trott
Version: 1
Author URI: http://lonewolf-online.net/
*/function sampleHelloWorld()
{
echo “<h2>Hello World</h2>”;
}function widget_myHelloWorld($args) {
extract($args);
echo $before_widget;
echo $before_title;?>My Widget Title<?php echo $after_title;
sampleHelloWorld();
echo $after_widget;
}

function myHelloWorld_init()
{
register_sidebar_widget(__(‘Hello World’), ‘widget_myHelloWorld’);
}
add_action(“plugins_loaded”, “myHelloWorld_init”);
?>

Testing your Plugin

If you check your plugins page now, you should now have a new plugin listed called Hello World which you can activate. On the Presentation tab, select widgets, and you should see your new widget available to be dragged onto a sidebar. Save your changes and admire your new work.

t is more than likely that your WordPress Widget will need to have some user configurable settings, so why not include a settings form within your widget?These settings pages (admin panels, configuration screen and so on…) are accessed from within the Presentation » Widgets screen from WordPress 2 and from Design » Widgets in WordPress 2.5. When you add a widget to a sidebar, you may notice a little icon on the right hand side of the widget. Clicking on this will open up the widget admin panel where your users can customize your widget to their needs.

Lets use the code from the Hello World widget of the last tutorial and change it around so that we have a settings page. We will see how to create the settings page, how to store/save and retrieve/load settings using the WordPress database and how to handle user inputs.

<?php
/*
Plugin Name: Hello World
Plugin URI: http://lonewolf-online.net/
Description: Sample Hello World Plugin
Author: Tim Trott
Version: 1
Author URI: http://lonewolf-online.net/
*/function sampleHelloWorld()
{
echo “<h2>Hello World</h2>”;
}

 

function widget_myHelloWorld($args) {
extract($args);
echo $before_widget;
echo $before_title;?>My Widget Title<?php echo $after_title;
sampleHelloWorld();
echo $after_widget;
}

function myHelloWorld_init()
{
register_sidebar_widget(__(‘Hello World’), ‘widget_myHelloWorld’);
}
add_action(“plugins_loaded”, “myHelloWorld_init”);
?>

The first thing we are going to create is the icon on the Widget sidebar screen, and get it to open up a blank screen which we will later fill with input controls.

We need to create a function that will be used to display and process the options. The convention is to use the plugin name appended with _control for the control panel page.

function myHelloWorld_control()
{
}

We will come back to this function a bit later on. For now, we will just get WordPress to use our blank form.

In the _init function where we register the sidebar widget, we need to add another function call that will tell WordPress that we have a control panel associated with our plugin.

function myHelloWorld_init()
{
register_sidebar_widget(__(‘Hello World’), ‘widget_myHelloWorld’);
register_widget_control(   ‘Hello World’, ‘myHelloWorld_control’, 300, 200 );
}

This extra function specifies the title of the page, the function that will be called (in this example it does nothing yet) and the widget control panel screen will be 300 pixels wide by 200 pixels tall. You can test this now, or continue and add some content.

WordPress Options

Before we get started on the admin panel, lets first have a look at how we can use the WordPress options database to store values. WordPress has a nice function that will do all the hard work for you called update_option. This function simply takes a key name and the data to store under that key, be it a string, integer or an array. You should try and use a unique, but meaningful, key name to avoid conflicts with other plugins or WordPress itself. I also use a prefix of “widget_” to identify that the settings are for a widget.

The WordPress options database is a table called by default wp_options, and maintains a list of key name and value pairs.

update_options(“widget_myHelloWorld”, “This is a test”);

This will update the key named widget_myHelloWorld in the WordPress database and set the value to “This is a test”. You can retrieve the information at a later date using the get_option function. This function only takes one parameter – the key name to retrieve.

$title = get_option(“widget_myHelloWorld”);
echo $title;

In this example we would expect to see “This is a test” on the screen.

Constructing our Admin Page

I am going to create the admin panel in four stages in this tutorial, you may wish to merge these all into one, or do them in a different order – its entirely up to you.

1. Create the Form Controls

To begin with you are going to need a form design. In this example we are going to simply use a text box and a label. I’ll leave the for design to you!

Each line on the form should be contained within a paragraph block to keep a nice uniform spacing between all elements. By default the items will be centred on the form, so if you need them to be left or right aligned, you will need to specify this in the p tag.

This is the code for my simple html form. You must use unique name and id attributes on the form. You will notice that there is no <form> element in the code. This is because a form element is provided by WordPress which encompass all the widgets that have been loaded.

function myHelloWorld_control()
{
?>
<p>
<label for=”myHelloWorld-WidgetTitle”>Widget Title: </label>
<input type=”text” id=”myHelloWorld-WidgetTitle” name=”myHelloWorld-WidgetTitle” value=”” />
</p>
<?php
}

If you test now you should have a label and text box centred on the widget control form. It is more than likely that you will need more than one form control, however I will let you work on that now you have a grasp of the basics.

2. Get Existing Data and Default Values

The next stage it to populate the form controls with either default values, or values obtained from the database with the get_options function.

Lets get the data from the database, perform a test on it to see if we have valid data, fill the data with default values if necessary then populate the form controls.

function myHelloWorld_control()
{
$options = get_option(“widget_myHelloWorld”);
if (!is_array( $options ))
{
$options = array(
‘title’ => ‘My Widget Title’
);
}?>
<p>
<label for=”myHelloWorld-WidgetTitle”>Widget Title: </label>
<input type=”text” id=”myHelloWorld-WidgetTitle” name=”myHelloWorld-WidgetTitle” value=”<?php echo $options[‘title’];?>” />
</p>
<?php
}

 

The first new line in this code will get the previously stored values from the database. We then test the output variable to see if it is null (no data was retrieved from the database) and if it is we create a new array with one element for the widget title. This method will guarantee that we have a valid value for the title (or an other setting) from the database or a default value. We can then use the title stored in the array to output into the text box value attribute.

3. Get User Input and Store the New Settings

We need some way of capturing the value a user may type in the box and storing it in the database to be re-used. For this we will need another form element that will identify our data when it is submitted. This new element is a hidden value which we will test against.

function myHelloWorld_control()
{
$options = get_option(“widget_myHelloWorld”);
if (!is_array( $options ))
{
$options = array(
‘title’ => ‘My Widget Title’
);
}if ($_POST[‘myHelloWorld-Submit’])
{
$options[‘title’] = htmlspecialchars($_POST[‘myHelloWorld-WidgetTitle’]);
update_option(“widget_myHelloWorld”, $options);
}

 

?>
<p>
<label for=”myHelloWorld-WidgetTitle”>Widget Title: </label>
<input type=”text” id=”myHelloWorld-WidgetTitle” name=”myHelloWorld-WidgetTitle” value=”<?php echo $options[‘title’];?>” />
<input type=”hidden” id=”myHelloWorld-Submit” name=”myHelloWorld-Submit” value=”1″ />
</p>
<?php
}

In this new code segment, we look at the PHP POST variable for an element called myHelloWorld-Submit (the same as the hidden field) and if we found it we extract the widget title from the post variable. It is important to ensure that the code we are about to insert into the database does not contain any malicious code, so we can use the htmlspecialchars function to help prevent SQL injections. We then make a call to update_option to save the new values to the database.

4. Using the Data

What is the point of doing all this and not using the data? None what so ever. Using the data within the widget is just as easy (in fact its the same) as using the data on the form.

In our code that outputs the widget title, you simply need to get the values for the database with get_option, make sure we have valid information and then output the value. We have already seen this in action on the widget control stage, so I will just go straight to the full code listing for this tutorial.

Complete Code

<?php
/*
Plugin Name: Hello World
Plugin URI: http://lonewolf-online.net/
Description: Sample Hello World Plugin
Author: Tim Trott
Version: 2
Author URI: http://lonewolf-online.net/
*/function sampleHelloWorld()
{
echo “<h2>Hello World</h2>”;
}

 

function widget_myHelloWorld($args) {
extract($args);

$options = get_option(“widget_myHelloWorld”);
if (!is_array( $options ))
{
$options = array(
‘title’ => ‘My Widget Title’
);
}

echo $before_widget;
echo $before_title;
echo $options[‘title’];
echo $after_title;

//Our Widget Content
sampleHelloWorld();
echo $after_widget;
}

function myHelloWorld_control()
{
$options = get_option(“widget_myHelloWorld”);<br/>
if (!is_array( $options ))
{
$options = array(
‘title’ => ‘My Widget Title’
);
}

if ($_POST[‘myHelloWorld-Submit’])
{
$options[‘title’] = htmlspecialchars($_POST[‘myHelloWorld-WidgetTitle’]);
update_option(“widget_myHelloWorld”, $options);
}

?>
<p>
<label for=”myHelloWorld-WidgetTitle”>Widget Title: </label>
<input type=”text” id=”myHelloWorld-WidgetTitle” name=”myHelloWorld-WidgetTitle” value=”<?php echo $options[‘title’];?>” />
<input type=”hidden” id=”myHelloWorld-Submit” name=”myHelloWorld-Submit” value=”1″ />
</p>
<?php
}

function myHelloWorld_init()
{
register_sidebar_widget(__(‘Hello World’), ‘widget_myHelloWorld’);
register_widget_control(   ‘Hello World’, ‘myHelloWorld_control’, 300, 200 );
}
add_action(“plugins_loaded”, “myHelloWorld_init”);
?>

Bookmark and Share
Advertisements

Flex & PHP – Transmitting data using JSON

In almost every RIA data needs to be transmitted from a server to the client. Now there are many ways to accomplish this task—web services, HTTP requests, remote objects, etc. But one sticks out as a simplistic and useful solution to this problem, this is using HTTP requests. Using a simple HTTP request, you can send data to a server and receive data back from the server.

Adobe Flex makes implementing this solution an easy task. The solution explained in this tutorial uses PHP for the server-side programming and sends the data using JSON (JavaScript Object Notation) encoding. By the end of the tutorial you will be sending simple objects along with arrays of objects from your PHP code to your Flex client.

Requirements

Flex Builder 2 (or Flex 2 SDK)

PHP (version 5.2 or higher, installed on a local web server)

Adobe Flex corelib

Sample files:

This sample file contains the following:

  • Flex Builder project with source
  • PHP source code
  • corelib.swc

Prerequisite knowledge

To benefit most from this tutorial, it is best if you have:

  • Built simple Flex applications before
  • A basic understanding of PHP
  • A basic knowledge of JSON

Setting up the development environment

This is actually a lot easier than it sounds because PHP and Flex both have functions to handle JSON data transmissions. For Flex, the one thing you need to make sure is that you have the corelib from Adobe in order to use the JSON functions—you can download it from Adobe Flex corelib. You can add this to a project in Flex Builder by going into the properties of a project then to “Flex Build Path” and adding the .swc to the library path. For PHP, if you have a version greater than 5.2, you are all set. If not, you can either upgrade, or install the php-json extension.

At this point you can also open up the provided ZIP file and you will find a couple of items. The first is the Flex source code that was used to create the application. You will also find the corelib library that is used in this project under the lib folder. You can proceed in multiple ways from here: create a new Flex Project in Flex Builder and then add the source and lib directory or use the SDK binaries to compile the application. Once it is built, it can be run and this will get data from a PHP file on the Paranoid Ferret server. I will go over the source code for both the PHP and Flex in depth later on in the tutorial.

Getting the PHP code ready

The first thing we are going to go over is the PHP code (json_tutorial.php), which you can find in the sample ZIP file. The PHP code creates a few classes for the objects that we will pass to our Flex application. We also have code to check if a GET variable has been set. We use this to tell the PHP code what we are requesting. If the variable getPerson is set, we create a person and echo it (after we encode it into JSON using json_encode) to send it to the Flex application. Ideally your data would be stored in a database, but for simplicity, we’re just creating Person objects directly in the PHP code.

The following is all the PHP code we are going to use and should meet our needs:

<?php
    
    class Person
    {
        public $first_name;
        public $last_name;
        public $email;
        public $address;
    }
    
    class Manager extends Person
    {
        public $title;
        public $employees;
    }
    
    if(isset($_GET['getPerson']))
    {
        $p = new Person();
        $p->first_name = 'John';
        $p->last_name = 'Doe';
        $p->email = 'fake@email.com';
        $p->address = '5555 Some Street City, State 52423';
        echo json_encode($p);
    }
    
    if(isset($_GET['getManager']))
    {
        $p1 = new Person();
        $p1->first_name = 'Joe';
        $p1->last_name = 'Doe';
        $p1->email = 'joe.doe@email.com';
        $p1->address = '5424 Some Street City, State 12314';
        $p2 = new Person();
        $p2->first_name = 'Bob';
        $p2->last_name = 'Doe';
        $p2->email = 'bob.doe@email.com';
        $p2->address = '1414 Some Street City, State 12412';
        $p3 = new Person();
        $p3->first_name = 'Kevin';
        $p3->last_name = 'Doe';
        $p3->email = 'kevin.doe@email.com';
        $p3->address = '6123 Some Street City, State 41241'; 
      
        $m = new Manager();
        $m->first_name = 'Manager';
        $m->last_name = 'Doe';
        $m->email = 'manager.doe@email.com';
        $m->address = '5534 Some Other Street City, State 91230';
        $m->title = 'Office Manager';
        $m->employees = array($p1, $p2, $p3);
        echo json_encode($m);
        
    }
    ?>

Creating the Flex user interface

The next thing to do is to set up the basic application for Flex. All the code from here on is found in the JSONTutorial.mxml file in the Flex Builder Project included in the sample ZIP file. The following code is the simplest Flex application. This sets up an application with specified height and width and also adds the view source option to the movie, with the source file specified by viewSourceURL. The URL can be any path that points to the correct file to display the source code:

<?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="500" height="410" 
    viewSourceURL="../files/JSONTutorial.mxml">
    </mx:Application>

The next thing you do is to set up the user interface. This is pretty standard Flex mxml. Nothing should look out of place. The user interface has a couple of text fields for the data we get back from the PHP code, a datagrid, and two buttons. This is all set up on a panel. The one important thing to observe is the dataField properties on the DataGridColumns. These names correspond to the variables from the objects in the PHP code.

The following code goes inside the Application block:

<mx:Panel x="0" y="0" width="500" height="410" layout="absolute" title="Simple JSON Example">
        <mx:DataGrid x="10" y="174" width="460" enabled="true" editable="false" id="dgEmployees">
            <mx:columns>
                <mx:DataGridColumn headerText="First Name" dataField="first_name"/>
                <mx:DataGridColumn headerText="Last Name" dataField="last_name"/>
                <mx:DataGridColumn headerText="Email" dataField="email"/>
                <mx:DataGridColumn headerText="Address" dataField="address"/>
            </mx:columns>
        </mx:DataGrid>
        <mx:Button x="116" y="338" label="Get Employee" id="getPerson" />
        <mx:Button x="266" y="338" label="Get Manager" id="getManager" />
        <mx:Label x="131" y="12" text="Name"/>
        <mx:TextInput x="189" y="10" id="txtName" editable="false"/>
        <mx:Label x="131" y="42" text="E-mail"/>
        <mx:TextInput x="189" y="40" id="txtEmail" editable="false"/>
        <mx:Label x="131" y="68" text="Address"/>
        <mx:TextInput x="189" y="66" id="txtAddress" editable="false"/>
        <mx:Label x="131" y="94" text="Title"/>
        <mx:TextInput x="189" y="92" id="txtTitle" editable="false"/>
        <mx:Label x="131" y="122" text="Has Employees"/>
        <mx:TextInput x="229" y="120" width="120" editable="false" id="txtEmployees" text="No"/>
        <mx:Label x="10" y="148" text="Employees:"/>
    </mx:Panel>

Using HTTPService to ask PHP for data

Now that the user interface is set up and ready to go you can add the HTTP services to go ask for the data from the PHP code. In Flex you can set up all kinds of different services. Today you are just going to set up a simple HTTP request service that sets a GET variable and tells the services a function should be ran once the results are back. As you can see in the code below, both services are sending out to the same PHP page, which is the one that was made earlier. Also each one sets one GET variable, which is done inside the mx:request block. Lastly, the result is an event which we hook to, to process the results of the request (our JSON data). This code goes at the very beginning of the file right after the Application opening element:

<mx:HTTPService id="personRequest" 
        url="../files/json_tutorial.php" 
        useProxy="false" method="GET" resultFormat="text" 
        result="personJSON(event)">
        <mx:request xmlns="">
            <getPerson>true</getPerson>
        </mx:request>
    </mx:HTTPService>
    <mx:HTTPService id="managerRequest" 
        url="../files/json_tutorial.php" 
        useProxy="false" method="GET" resultFormat="text" 
        result="managerJSON(event)">
        <mx:request xmlns="">
            <getManager>true</getManager>
        </mx:request>
</mx:HTTPService>

Decoding the JSON data

Now you can get into the actual JSON decoding, which is really simple. At this point if you’re using Flex Builder you will be getting an error message about an undefined method for personJSON(event) and managerJSON(event). This is going to be solved right now. First things first—put in the appropriate method signatures so the application can build and run. You do this by inputting a script tag and adding the ActionScript functions inside of it. You’ll notice the added import statements, in the code, to import our JSON serialization functions and use the result event. This code will go right above the HTTP services we just set up and below the Application opening element:

<mx:Script>
        <![CDATA[
        import mx.rpc.events.ResultEvent;
        import com.adobe.serialization.json.JSON;
        
        private function personJSON(event:ResultEvent):void
        {
        }
        
        private function managerJSON(event:ResultEvent):void
        {
        }
        ]]>
</mx:Script>

Now down to the actual work of the application, the first thing that needs to be done in both of the functions is to get the result back and store it as a string. The next thing to do is to call the function JSON.decode on the string. This function will return us an object with all the same properties of the one sent by PHP—we set this equal to a variable. This can now be used as a normal object and to reference the properties using the . (dot) notation. To get the first name of the person you can simply use variable.first_name and so on for the rest of the variables. This takes care of getting a person from PHP. And the above code is changed like so:

<mx:Script>
        <![CDATA[
        import mx.rpc.events.ResultEvent;
        import com.adobe.serialization.json.JSON;
        
        private function personJSON(event:ResultEvent):void
        {
            //get the raw JSON data and cast to String
            var rawData:String = String(event.result);
            var person:Object = JSON.decode(rawData);
            txtName.text = person.first_name + " " + person.last_name;
            txtEmail.text = person.email;
            txtAddress.text = person.address;
            txtEmployees.text = "No";
            txtTitle.text = "No Title";
        }
        
        private function managerJSON(event:ResultEvent):void
        {
            //get the raw JSON data and cast to String
            var rawData:String = String(event.result);
            var manager:Object = JSON.decode(rawData);
            txtName.text = manager.first_name + " " + 
                     
            manager.last_name;
            txtEmail.text = manager.email;
            txtAddress.text = manager.address;
            txtEmployees.text = "Yes";
            txtTitle.text = manager.title;
        }
        ]]>
</mx:Script>

Hooking data to datagrid

All that is left is to worry about the datagrid you created, and you might have noticed that employees of the manager haven’t been dealt with yet. This is handled pretty nicely in the manager function. You are going to add a new var called employees and this will be an array. Because of the JSON.decode function, you can simply cast the employees as an array and all will be fine.

The next thing to do is actually creating an ArrayCollection to use for the data provider for the datagrid. This is a best practice when using array data for the provider because the ArrayCollection allows for some extra functionality. The final setup is to set the dataGrid.dataProvider equal to the ArrayCollection. You also set the dataProvider equal to null in the person function to clear out the data in the datagrid. To make all this work you need to add another import statement for ArrayCollection. This leaves you with the following code:

<mx:Script>
        <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.rpc.events.ResultEvent;
        import com.adobe.serialization.json.JSON;
        
        private function personJSON(event:ResultEvent):void
        {
            //get the raw JSON data and cast to String
            var rawData:String = String(event.result);
            var person:Object = JSON.decode(rawData);
            txtName.text = person.first_name + " "  + person.last_name;
            txtEmail.text = person.email;
            txtAddress.text = person.address;
            txtEmployees.text = "No";
            txtTitle.text = "No Title";
            
            //Data Grid Code
            dgEmployees.dataProvider = null;
        }
        
        private function managerJSON(event:ResultEvent):void
        {
            //get the raw JSON data and cast to String
            var rawData:String = String(event.result);
            var manager:Object = JSON.decode(rawData);
            txtName.text = manager.first_name + " " + manager.last_name;
            txtEmail.text = manager.email;
            txtAddress.text = manager.address;
            txtEmployees.text = "Yes";
            txtTitle.text = manager.title;
            
            //Data Grid Code
            var employees:Array = manager.employees as Array;
            var employeesCollection:ArrayCollection = new ArrayCollection(employees); 
            dgEmployees.dataProvider = employeesCollection;
        }
        ]]>
    </mx:Script>

Now you might have tried it at this point and said, “Hey, this isn’t working!”. That is true. This is because you never hooked the buttons up to send the requests. This is really simple. You just add click events for both buttons and the corresponding service.send() commands to the click events. The following code replaces the old buttons:

<mx:Button x="116" y="338" label="Get Employee" id="getPerson" click="personRequest.send();"/>
<mx:Button x="266" y="338" label="Get Manager" id="getManager" click="managerRequest.send();"/>

Finally this puts the whole thing together and we end up with the following code for our Flex application:

<?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" width="500" height="410" 
    viewSourceURL="../files/JSONTutorial.mxml">
    <mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;
    import mx.rpc.events.ResultEvent;
    import com.adobe.serialization.json.JSON;
    
    private function personJSON(event:ResultEvent):void
    {
        //get the raw JSON data and cast to String
        var rawData:String = String(event.result);
        var person:Object = JSON.decode(rawData);
        txtName.text = person.first_name + " " + person.last_name;
        txtEmail.text = person.email;
        txtAddress.text = person.address;
        txtEmployees.text = "No";
        txtTitle.text = "No Title";
        
        //Data Grid Code
        dgEmployees.dataProvider = null;
    }
    
    private function managerJSON(event:ResultEvent):void
    {
        //get the raw JSON data and cast to String
        var rawData:String = String(event.result);
        var manager:Object = JSON.decode(rawData);
        txtName.text = manager.first_name + " " + manager.last_name;
        txtEmail.text = manager.email;
        txtAddress.text = manager.address;
        txtEmployees.text = "Yes";
        txtTitle.text = manager.title;
        
        //Data Grid Code
        var employees:Array = manager.employees as Array;
        var employeesCollection:ArrayCollection = new ArrayCollection(employees); 
        dgEmployees.dataProvider = employeesCollection;
    }
    ]]>
</mx:Script>
    <mx:HTTPService id="personRequest" url="../files/json_tutorial.php" 
        useProxy="false" method="GET" resultFormat="text" 
        result="personJSON(event)">
        <mx:request xmlns="">
            <getPerson>"true"</getPerson>
        </mx:request>
    </mx:HTTPService>
    <mx:HTTPService id="managerRequest" 
        url="../files/json_tutorial.php" 
        useProxy="false" method="GET" resultFormat="text" 
        result="managerJSON(event)">
        <mx:request xmlns="">
            <getManager>"true"</getManager>
        </mx:request>
    </mx:HTTPService>
    <mx:Panel x="0" y="0" width="500" height="410" layout="absolute" title="Simple JSON Example">
        <mx:DataGrid x="10" y="174" width="460" enabled="true" 
        editable="false" id="dgEmployees">
            <mx:columns>
                <mx:DataGridColumn headerText="First Name" dataField="first_name"/>
                <mx:DataGridColumn headerText="Last Name" dataField="last_name"/>
                <mx:DataGridColumn headerText="Email" dataField="email"/>
                <mx:DataGridColumn headerText="Address" dataField="address"/>
            </mx:columns>
        </mx:DataGrid>
        <mx:Button x="116" y="338" label="Get Employee" id="getPerson" click="personRequest.send();"/>
        <mx:Button x="266" y="338" label="Get Manager" id="getManager" click="managerRequest.send();"/>
        <mx:Label x="131" y="12" text="Name"/>
        <mx:TextInput x="189" y="10" id="txtName" editable="false"/>
        <mx:Label x="131" y="42" text="E-mail"/>
        <mx:TextInput x="189" y="40" id="txtEmail" editable="false"/>
        <mx:Label x="131" y="68" text="Address"/>
        <mx:TextInput x="189" y="66" id="txtAddress" editable="false"/>
        <mx:Label x="131" y="94" text="Title"/>
        <mx:TextInput x="189" y="92" id="txtTitle" editable="false"/>
        <mx:Label x="131" y="122" text="Has Employees"/>
        <mx:TextInput x="229" y="120" width="120" editable="false" id="txtEmployees" text="No"/>
        <mx:Label x="10" y="148" text="Employees:"/>
    </mx:Panel>
    </mx:Application>

You now have a small application that will get data from PHP using JSON.

Where to go from here

After learning the basics of sending data from PHP to Flex using JSON, you might still have some yearning for learning. (Oh, that is cheesy!) If you are still looking for more information on transmitting data between Flex and PHP I recommend you to go to http://blog.paranoidferret.com and check out some of the other Flex and PHP tutorials out there.

If you want to explore other possible solutions to transmitting data, check the tutorial Using Flex 2 and AMFPHP by Mike Potter in the Flex Developer Center.

Lastly if you found some of this to go over your head, check out the other tutorial by Mike Potter on Flex 2 and PHP basics, Integrating Flex 2 and PHP.

Bookmark and Share

Running the Flex/PHP code (XAMPP, MAMP)

The sample files contain a Flex Builder 3 archive project that includes all of the examples discussed in this article. You can import this project directly into Flex Builder or Eclipse (after installing the Flex Builder plug-in) by selecting File > Import > Flex Project and navigating to the file.

Open the project “src” directory to see the MXML files. Each of these MXML files, which are also called applications, can be run in a web browser. Right-click the file in the Flex Navigator (or the Package Explorer in Eclipse) and choose the option to “Run Application”. MXML files differ from HTML files in that MXML files are compiled into a SWF file, which is then run from within an HTML page referencing the SWF file.

Flex Builder 3 automatically compiles the MXML code into a SWF file every time you save the file or the first time you choose “Run Application” from the Flex Builder menu. When you run the application, Flex Builder also automatically opens the application in the default browser on your system.

To specify the default application, right-click a file name and select the option to “Set as Default Application” from the context menu. The blue dot signifies the default application to run.

Note: The Flex Builder 3 project contains a folder of PHP files, which must be deployed to a PHP web application server (see the following instructions) in order to run the examples. Once the server is setup, described below, Flex Builder copies this folder to the web server when the project is built.

Deploying Flex examples on your local workstation web server

Follow the steps below to publish the PHP files to your local web server so that you can view them:

  1. If you do not already have a PHP-enabled web server installed, install XAMPP (for Windows) or MAMP (for Macintosh OS X).
  2. After installing the appropriate software linked above, start your local web server.
  3. In Flex Builder 3, choose Project > Properties. The Flex Builder 3 Project Properties window appears.
  4. Select the Flex Build Path tab. In the output folder, choose a directory on your localhost web server.
    1. On Windows, the path is:
      C:\XAMPP\xampp\htdocs or C:\XAMPP\xampp\htdocs\myproject
    2. On Mac, the path is:
      /Applications/MAMP/htdocs or /Applications/MAMP/projects/test
  5. In the Output folder URL field, enter the URL to the output folder.
    1. On Windows, enter: http://localhost/ or http://localhost/myproject
    2. On Mac, enter: http://localhost:8888 or http://localhost:8888/projects/test

After setting up the local web server, you can test your projects in Flex Builder and they will launch in the browser and run from the server (http://localhost) rather than the local file system (file://path/to/project/bin-debug/myproject.html).

 

 

Sphinx Search Installation

Sphinx search introduction

507110_binocular

After reading my introduction to full text search or you have read article somewhere else and decided to go with full text search in your next project, but you still confuse what full text search engine to use. One implementation of full text search engine is Sphinx. And I’ll give you a short course on how you installing Sphinx for your full text search engine.

Sphinx is a full-text search engine, distributed under GPL version 2. It is not only fast in searching but it is also fast in indexing your data. Currently, Sphinx API has binding in PHP, Python, Perl, Ruby and Java.

Sphinx features

  • high indexing speed (upto 10 MB/sec on modern CPUs);
  • high search speed (avg query is under 0.1 sec on 2-4 GB text collections);
  • high scalability (upto 100 GB of text, upto 100 M documents on a single CPU);
  • provides good relevance ranking through combination of phrase proximity ranking and statistical (BM25) ranking;
  • provides distributed searching capabilities;
  • provides document exceprts generation;
  • provides searching from within MySQL through pluggable storage engine;
  • supports boolean, phrase, and word proximity queries;
  • supports multiple full-text fields per document (upto 32 by default);
  • supports multiple additional attributes per document (ie. groups, timestamps, etc);
  • supports stopwords;
  • supports both single-byte encodings and UTF-8;
  • supports English stemming, Russian stemming, and Soundex for morphology;
  • supports MySQL natively (MyISAM and InnoDB tables are both supported);
  • supports PostgreSQL natively.

There you go, so fire up your terminal or console, and let’s get thing done.

Installing sphinxsearch

  1. Download sphinx at sphinxsearch.com, for this tutorial, I use Sphinx 0.9.8.1
    $wget http://sphinxsearch.com/downloads/sphinx-0.9.8.1.tar.gz
  2. Open your terminal, extract and install sphinx
    $tar -xvf sphinx-0.9.8.1.tar.gz
  3. sphinx need mysql-dev install, if you use ubuntu linux install this
    $sudo apt get install libmysqlclient15-dev
  4. Install sphinx to your system
    $cd sphinx-0.9.8.1/
    $./configure
    $make
    $sudo make install

    Note if you want to use sphinx with PostgreSQL, configure with this argument –with-pgsql

    $./configure --with-pgsql
  5. Test your installation

    $search

    This should come up in your terminal

    Sphinx 0.9.8.1-release (r1533)
    Copyright (c) 2001-2008, Andrew Aksyonoff
    
    Usage: search [OPTIONS] [word2 [word3 [...]]]
    
    Options are:
    -c, --config 	use given config file instead of defaults
    -i, --index 	search given index only (default: all indexes)
    -a, --any		match any query word (default: match all words)
    -b, --boolean		match in boolean mode
    -p, --phrase		match exact phrase
    -e, --extended		match in extended mode
    -f, --filter  	only match if attribute attr value is v
    -s, --sortby 	sort matches by 'CLAUSE' in sort_extended mode
    -S, --sortexpr 	sort matches by 'EXPR' DESC in sort_expr mode
    -o, --offset 	print matches starting from this offset (default: 0)
    -l, --limit 	print this many matches (default: 20)
    -q, --noinfo		dont print document info from SQL database
    -g, --group 	group by attribute named attr
    -gs,--groupsort 	sort groups by
    --sort=date		sort by date, descending
    --rsort=date		sort by date, ascending
    --sort=ts		sort by time segments
    --stdin			read query from stdin
    
    This program (CLI search) is for testing and debugging purposes only;
    it is NOT intended for production use.

Well done. You have Sphinx at your service. But before you can play with this full text search engine you have just installed, you have to understand how Sphinx works.

Sphinx installed 4 program in your environment, but most of the time we will only use indexer, search and searchd. To begin with, we have to create an index for our source. Let’s create a file name sphinx.conf, and here is a sample of sphinx.conf look like.

source book
{
    type            = mysql
    sql_host        = localhost
    sql_user        = root
    sql_pass        = root
    sql_db          = library
    sql_port        = 3306# optional, default is 3306
    sql_query       = SELECT id, title, summary, author from library
    sql_query_info  = SELECT * FROM library_book WHERE id=$id
}

index book
{
    source          = book
    path            = data/book
    docinfo         = extern
    charset_type    = sbcs
}

indexer
{
    mem_limit       = 32M
}

searchd
{
    port            = 3312
    log             = log/searchd.log
    query_log       = log/query.log
    read_timeout    = 5
    max_children    = 30
    pid_file        = log/searchd.pid
    max_matches     = 1000
}

For more information about sphinx configuration, please go to sphinx documentation.

Create log folder for our searchd log file and another folder named data for our index data. Run indexer to index our database.

$mkdir log
$mkdir data
$indexer --all
Sphinx 0.9.8.1-release(r1533)
Copyright (c) 2001-2008, Andrew Aksyonoff

using config file ./sphinx.conf'...
indexing index 'book'...
collected 12 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 12 docs, 10319 bytes
total 0.018 sec, 571436.48 bytes/sec, 664.53 docs/sec

You can use search program to test search index you have just created. Assuming you have book with title contain PHP in your database, then run search PHP will give you some results.

$search PHP

Create subdomains using PHP?

subdomainform.php

<html>
<head>
<title>create a subdomain</title>
</head>
<body>
<form name “form1” method “post” action “addsubdomain.php”>
<h1>create Sub Domains</h1>
Sub Domain Name : <input type “text” name “subdomain”><br />
<input type “submit” name “Submit” value “Submit”>
</form>
</body>
</html>

addsubdomain.php

<?php

ini_set(‘display_errors’ 1);

$host “domainname.com”; // your domain name without the www
$port 2082;
$path “/frontend/x/subdomain/doadddomain.html?domain “.$_POST[‘subdomain’].”&rootdomain “.$host; //or .dll etc. for authnet etc.

// these lines are changed
$cpaneluser “username”;
$cpanelpass “pass”;
$authstr “$cpaneluser:$cpanelpass”;
//****************************

// Setup the Auth String
$pass base64_encode($authstr);

$fp fsockopen($host $port $errno $errstr $timeout 30);

if(!$fp){
//error tell us
echo “$errstr ($errno)n”;

}else{

//send the server request

fputs($fp “POST $path HTTP/1.1rn”);
fputs($fp “Host: $hostrn”);
fputs($fp “Authorization: Basic $pass rn”);
fputs($fp “Content-type: application/x-www-form-urlencodedrn”);
fputs($fp “Content-length: “.strlen($poststring).”rn”);
fputs($fp “Connection: closernrn”);
fputs($fp $poststring . “rnrn”);

//*************************************
// Remove this to stop it from displaying the output fron the CPanel
//*************************************
//loop through the response from the server
/*
while(!feof($fp)) {
echo fgets($fp 4096);
}

*/
while(!feof($fp)) { fgets($fp 4096); }
//close fp – we are done with it
fclose($fp);
}

*****************************

  1. In you main httpd.conf add the following line at the bottom:Include /path/to/subdomains.conf

file name subdomains.conf

@mkdir ( /path/to/subdirectory/ .$name );

  1. $vhost
  2. ServerAdmin yourname@yourserver.com
  3. DocumentRoot /path/to/subdirectory/ .$name.
  4. ServerName .$name. .yourserver.com
  5. ErrorLog /path/to/logs/ .$name. _error_log
  6. ;
  7. $fo fopen ( /path/to/subdomains.conf a );
  8. $fw fwrite ( $fo $vhost );
  9. fclose ( $fo );

******************************

Bookmark and Share

Upload files using PHP

Consider the html form:

<html>
<body>
<form action=”upload_file.php” method=”post” enctype=”multipart/form-data”>
<label for=”file”>Filename:</label>
<input type=”file” name=”file” id=”file” size=”20″ /><br />
<input type=”submit” name=”submit” value=”Submit” />
</form>
</body>
</html>

Script for saving the uploaded file://upload_file.php
<?php
if (file_exists(“upload/” . $_FILES[“file”][“name”]))
{
echo $_FILES[“file”][“name”] . ” already exists. “;
}
else
{
move_uploaded_file($_FILES[“file”][“tmp_name”],”upload/” . $_FILES[“file”][“name”]);
echo “Stored in: ” . “upload/” . $_FILES[“file”][“name”];
}
?>

The script above checks if the file already exists, if it does not, it copies the file to the specified folder.This example saves the file to a new folder called “upload”

 

 

MySQL Improved Extension (mysqli)

Overview

This section provides an introduction to the options available to you when developing a PHP application that needs to interact with a MySQL database.

What is an API?

An Application Programming Interface, or API, defines the classes, methods, functions and variables that your application will need to call in order to carry out its desired task. In the case of PHP applications that need to communicate with databases the necessary APIs are usually exposed via PHP extensions.

APIs can be procedural or object-oriented. With a procedural API you call functions to carry out tasks, with the object-oriented API you instantiate classes and then call methods on the resulting objects. Of the two the latter is usually the preferred interface, as it is more modern and leads to better organised code.

When writing PHP applications that need to connect to the MySQL server there are several API options available. This document discusses what is available and how to select the best solution for your application.

What is a Connector?

In the MySQL documentation, the term connector refers to a piece of software that allows your application to connect to the MySQL database server. MySQL provides connectors for a variety of languages, including PHP.

If your PHP application needs to communicate with a database server you will need to write PHP code to perform such activities as connecting to the database server, querying the database and other database-related functions. Software is required to provide the API that your PHP application will use, and also handle the communication between your application and the database server, possibly using other intermediate libraries where necessary. This software is known generically as a connector, as it allows your application to connect to a database server.

What is a Driver?

A driver is a piece of software designed to communicate with a specific type of database server. The driver may also call a library, such as the MySQL Client Library or the MySQL Native Driver. These libraries implement the low-level protocol used to communicate with the MySQL database server.

By way of an example, the PHP Data Objects (PDO) database abstraction layer may use one of several database-specific drivers. One of the drivers it has available is the PDO MYSQL driver, which allows it to interface with the MySQL server.

Sometimes people use the terms connector and driver interchangeably, this can be confusing. In the MySQL-related documentation the term “driver” is reserved for software that provides the database-specific part of a connector package.

What is an Extension?

PHP’s mysqli Extension PDO (Using PDO MySQL Driver and MySQL Native Driver) PHP’s MySQL Extension
PHP version introduced 5.0 5.0 Prior to 3.0
Included with PHP 5.x yes yes Yes
Comes with PHP 6.0 Yes Yes Yes
MySQL development status Active development Active development as of PHP 5.3 Maintenance only
Recommended by MySQL for new projects Yes – preferred option Yes No
API supports Charsets Yes Yes No
API supports server-side Prepared Statements Yes Yes No
API supports client-side Prepared Statements No Yes No
API supports Stored Procedures Yes Yes No
API supports Multiple Statements Yes Most No
Supports all MySQL 4.1+ functionality Yes Most No

In the PHP documentation you will come across another term – extension. The PHP code consists of a core, with optional extensions to the core functionality. PHP’s MySQL-related extensions, such as the mysqli extension, and the mysql extension, are implemented using the PHP extension framework.

An extension typically exposes an API to the PHP programmer, to allow its facilities to be used programmatically. However, some extensions which use the PHP extension framework do not expose an API to the PHP programmer.

The PDO MySQL driver extension, for example, does not expose an API to the PHP programmer, but provides an interface to the PDO layer above it.

The terms API and extension should not be taken to mean the same thing, as an extension may not necessarily expose an API to the programmer.

What are the main PHP API offerings for using MySQL?

There are three main API options when considering connecting to a MySQL database server:

  • PHP’s MySQL Extension
  • PHP’s mysqli Extension
  • PHP Data Objects (PDO)

Each has its own advantages and disadvantages. The following discussion aims to give a brief introduction to the key aspects of each API.

What is PHP’s MySQL Extension?

This is the original extension designed to allow you to develop PHP applications that interact with a MySQL database. The mysql extension provides a procedural interface and is intended for use only with MySQL versions older than 4.1.3. This extension can be used with versions of MySQL 4.1.3 or newer, but not all of the latest MySQL server features will be available.

Note: If you are using MySQL versions 4.1.3 or later it is strongly recommended that you use the mysqli extension instead.

The mysql extension source code is located in the PHP extension directory ext/mysql.

For further information on the mysql extension, see MySQL.

What is PHP’s mysqli Extension?

The mysqli extension, or as it is sometimes known, the MySQL improved extension, was developed to take advantage of new features found in MySQL systems versions 4.1.3 and newer. The mysqli extension is included with PHP versions 5 and later.

The mysqli extension has a number of benefits, the key enhancements over the mysql extension being:

  • Object-oriented interface
  • Support for Prepared Statements
  • Support for Multiple Statements
  • Support for Transactions
  • Enhanced debugging capabilities
  • Embedded server support

Note: If you are using MySQL versions 4.1.3 or later it is strongly recommended that you use this extension.

As well as the object-oriented interface the extension also provides a procedural interface.

The mysqli extension is built using the PHP extension framework, its source code is located in the directory ext/mysqli.

For further information on the mysqli extension, see Mysqli.

What is PDO?

PHP Data Objects, or PDO, is a database abstraction layer specifically for PHP applications. PDO provides a consistent API for your PHP application regardless of the type of database server your application will connect to. In theory, if you are using the PDO API, you could switch the database server you used, from say Firebird to MySQL, and only need to make minor changes to your PHP code.

Other examples of database abstraction layers include JDBC for Java applications and DBI for Perl.

While PDO has its advantages, such as a clean, simple, portable API, its main disadvantage is that it doesn’t allow you to use all of the advanced features that are available in the latest versions of MySQL server. For example, PDO does not allow you to use MySQL’s support for Multiple Statements.

PDO is implemented using the PHP extension framework, its source code is located in the directory ext/pdo.

For further information on PDO, see the PDO.

What is the PDO MYSQL driver?

The PDO MYSQL driver is not an API as such, at least from the PHP programmer’s perspective. In fact the PDO MYSQL driver sits in the layer below PDO itself and provides MySQL-specific functionality. The programmer still calls the PDO API, but PDO uses the PDO MYSQL driver to carry out communication with the MySQL server.

The PDO MYSQL driver is one of several available PDO drivers. Other PDO drivers available include those for the Firebird and PostgreSQL database servers.

The PDO MYSQL driver is implemented using the PHP extension framework. Its source code is located in the directory ext/pdo_mysql. It does not expose an API to the PHP programmer.

For further information on the PDO MYSQL driver, see MySQL (PDO).

What is PHP’s MySQL Native Driver?

In order to communicate with the MySQL database server the mysql extension, mysqli and the PDO MYSQL driver each use a low-level library that implements the required protocol. In the past, the only available library was the MySQL Client Library, otherwise known as libmysql.

However, the interface presented by libmysql was not optimized for communication with PHP applications, as libmysql was originally designed with C applications in mind. For this reason the MySQL Native Driver, mysqlnd, was developed as an alternative to libmysql for PHP applications.
PHP’s mysqli Extension PDO (Using PDO MySQL Driver and MySQL Native Driver) PHP’s MySQL Extension
PHP version introduced 5.0 5.0 Prior to 3.0
Included with PHP 5.x yes yes Yes
Comes with PHP 6.0 Yes Yes Yes
MySQL development status Active development Active development as of PHP 5.3 Maintenance only
Recommended by MySQL for new projects Yes – preferred option Yes No
API supports Charsets Yes Yes No
API supports server-side Prepared Statements Yes Yes No
API supports client-side Prepared Statements No Yes No
API supports Stored Procedures Yes Yes No
API supports Multiple Statements Yes Most No
Supports all MySQL 4.1+ functionality Yes Most No
The mysql extension, the mysqli extension and the PDO MySQL driver can each be individually configured to use either libmysql or mysqlnd. As mysqlnd is designed specifically to be utilised in the PHP system it has numerous memory and speed enhancements over libmysql. You are strongly encouraged to take advantage of these improvements.

Note: The MySQL Native Driver can only be used with MySQL server versions 4.1.3 and later.

The MySQL Native Driver is implemented using the PHP extension framework. The source code is located in ext/mysqlnd. It does not expose an API to the PHP programmer.

Comparison of Features

The following table compares the functionality of the three main methods of connecting to MySQL from PHP:
PHP’s mysqli Extension PDO (Using PDO MySQL Driver and MySQL Native Driver) PHP’s MySQL Extension
PHP version introduced 5.0 5.0 Prior to 3.0
Included with PHP 5.x yes yes Yes
Comes with PHP 6.0 Yes Yes Yes
MySQL development status Active development Active development as of PHP 5.3 Maintenance only
Recommended by MySQL for new projects Yes – preferred option Yes No
API supports Charsets Yes Yes No
API supports server-side Prepared Statements Yes Yes No
API supports client-side Prepared Statements No Yes No
API supports Stored Procedures Yes Yes No
API supports Multiple Statements Yes Most No
Supports all MySQL 4.1+ functionality Yes Most No

PHP’s mysqli Extension PDO (Using PDO MySQL Driver and MySQL Native Driver) PHP’s MySQL Extension
PHP version introduced 5.0 5.0 Prior to 3.0
Included with PHP 5.x yes yes Yes
Comes with PHP 6.0 Yes Yes Yes
MySQL development status Active development Active development as of PHP 5.3 Maintenance only
Recommended by MySQL for new projects Yes – preferred option Yes No
API supports Charsets Yes Yes No
API supports server-side Prepared Statements Yes Yes No
API supports client-side Prepared Statements No Yes No
API supports Stored Procedures Yes Yes No
API supports Multiple Statements Yes Most No
Supports all MySQL 4.1+ functionality Yes Most No
Bookmark and Share