Kristo Vaher

inventas vitam iuvat excoluisse per artes

Skip to: Content | Sidebar | Footer

AJAX controller also released as a class

20 June, 2010 (11:54) | Web Development | By: Kristo Vaher

For phpclasses.org purposes I also converted the Smart AJAX Controller into a class, it is available here. While there aren’t big differences between the two, class structure makes the backend script more seamless and easy to use. Another improvement is the ability to return the result from the server compressed with GZip, thus making the whole communication very lightweight.

Smart AJAX/JSON/PHP solution with jQuery

1 June, 2010 (23:45) | Web Development | By: Kristo Vaher

I have seen a number of complicated solutions for front-end AJAX development and it has become quite clear such solutions are difficult thing to grasp for someone not that experienced with AJAX. Today I am offering a very simple and easy to extend solution that not only is less than two hundred lines of code in total – together with detailed comments – but also gives the ropes to jQuery AJAX development and using JSON as the preferred type of returned data from the server. Fear not, this is actually easier than it sounds.

For those of you looking for the files directly, they can grab them here. Individual source code can be viewed here: index.htm, javascript.js, ajax.php. Note that jquery.js file is also required (1.4.2), should you copy-paste from the source code instead of downloading the archive.

The code is licensed under LGPL, so you can use it for personal as well as commercial purposes. All files are commented and a working example is provided within. You do not need a firm grasp of jQuery in order to understand this example and you do not need experience with JSON data format. PHP and jQuery handle the conversions for you. I will not explain everything step by step – for that refer to the files and the example provided – but I will give a general overview of what is happening here.

Front-end user-interface has the various actions built through a uiAction() javascript function. This is a general-use function that takes two variables, an ‘action’ that acts as an action identifier, and ‘data’ variable. Data variable can be whatever you want, it can be a string, integer, array or an object, depending on your needs. Since you will control how the ‘data’ variable will be used, it is entirely up to you. In the example files I am calling the uiAction() on a <button> element like this:

uiAction(‘alertLowercaseString’,$(‘#example’).val());

For those of you who know jQuery, know that I am sending the value of an input field with an id of ‘example’ to the function. Action’s name itself is ‘alertLowercaseString’ in that case. Then, within uiAction() function in the ‘action’-switch I am executing the function that sends data to AJAX, like this:

input['string']=data;
executeAjaxAction(action,input);

Action is, by default, the same as action identifier used to call uiAction(). executeAjaxAction() is a function that submits data to PHP backend (but you can customize it, such as have different uiAction() calls execute same function in back-end). ‘input’ is an uiAction() specific javascript object. This is defined at the start of the uiAction() function and is used for convenience in order to send specific data to AJAX. ‘executeAjaxAction()’ expects ‘input’ to be an object or an array, since this is what will be sent to PHP backend. After submitting data to executeAjaxAction() the front-end will connect PHP back-end with AJAX. In this case I am sending an ‘action’ of alertLowercaseString. PHP backend will solve the ‘input’ into a variable named $inputVariables and again – as it was in front-end, within a switch you can define what you want to take place in the back-end and what will be returned. In this example it is:

$return['action']=’alert’;
$return['message']=’Your string lowercased: ‘.strtolower($inputVariables['string']);

‘$return’ is an array that is used to create a JSON object from. ‘action’ for ‘$return’ needs to be always defined, but every other variable can be whatever you want, since – as before – you get to decide what data you need to use later on in front end. Basically everything you want to return to front-end should be placed in ‘$return’ array. PHP then creates a JSON string of the ‘$return’ array and returns it to the browser. executeAjaxAction() function will then call a javascript function parseAjaxReturn(), which will check what action PHP defined for callback (if any) and then – in this example of ‘alert’ as the action – does the following:

alert(json['message']);

And this alerts to the user the lowercased string.

This quick explanation may be difficult to understand at first, but I strongly suggest that you take a look at the fully working examples provided within. Files are fully commented and examples provided within are minimal, so you can take this into production use right away should you want.

Download fully working example files here

If you have any questions, go ahead and contact me directly or comment this article. I will get back to you as soon as possible.

All the best!

A simple PHP pathfinder class – as promised

25 May, 2010 (22:55) | Web Development | By: Kristo Vaher

I recently shared a simple PHP and jQuery animated pathfinding tech-demo through my Twitter account and promised to share the simple pathfinding class used for pathfinding calculations. The example shared in Twitter is still available here.

This example has a few limits, that is you can easily confuse it by clicking on two tile locations in a row. But in general it works and what I will be using this for will be something a bit different, so this limitation was of no concern to me. However the entire pathfinding calculation takes place on PHP backend. Each map is essentially a square (currently a limitation of pathfinder, but can easily be tweaked) and stored as an associative array, every tile in that array like this:

$map['1x1']['weight']=1.0;

The first key is the coordinate of the single map tile and the weight key is used to store weight of this map tile for calculations. Nothing else is needed (and an example is provided in the files below). For actual game purposes or whatnot you can store additional information on that very map as long as the coordinate and weight are assigned as shown in the example. For example, in my own tech-demo I also store the graphic tile used in the map array.

Finding the actual path is just as simple:

$map=getMap();
require(‘class.pathfinder.php’);
$path=new PathFinder();
//Create new pathfinder object
$path->setOrigin(1,1);
//Set the start location
$path->setDestination(20,20);
//Set the destination
$path->setMap($map);
//Assign the map to use for calculations
$result=$path->returnPath();
//Returns an array of all the walked steps

Working example, as well as commented pathfinder class is available below:

Download the class and example file here

Please note that this is not a definitive pathfinder. It only takes into account one square ahead and on very large maps I am sure there are more ideal solutions. But for your basic browser based game this is a good starting point and I learned a lot by creating it. This is also easy to expand based on your needs.

If you have any other questions, let me know.

The code is shared entirely free for personal or commercial use.

Cheers!

Implementing tree traversal architecture for OriginNode

9 May, 2010 (13:35) | OriginNode | By: Kristo Vaher

In my various old projects for one reason or another a very recursive algorithm was used to fetch data that was structured in a tree. In some cases multiple trees were stored within the same table, which caused problems when trying to implement faster and better algorithms when fetching data from the tree, adding new nodes to the tree or removing nodes from the tree in general.

In OridinNode the entire system assumes that every tree has a single parent node. But in OridinNode there are also situations where one tree can be a child of another trees node, which causes conflict for the traversal algorithms. To make traversal work every tree needs to have at least one element that is considered ‘parent’. But if a parent happens to be a node from another tree, then it became important to implement a ‘ghost node’ to every module that has a parent in another tree. The user never sees such a ghost node, but that ghost node is used to traversing within the tree when fetching data to the actual parent element. To give an example, a website has a tree of pages. One of those pages however displays categories for products. There is no ‘main category’ as all of the categories are children of the page node from pages tree, but the categories table does need a ghost parent for quick traversal purposes.

The tree structure model used in OriginNode is a Nested Set Model. Basically every node within the tree is given two values, left and right, which carries their position information within the tree as well as basic information on their children and parents. This allows to completely throw out the recursive set of algorithms that are commonly used and makes it possible to build a whole array of the entire structure with just a few queries. For more detailed description please read through the link I posted above, I will be covering how this will be implemented within the structure of OriginNode below.

In OriginNode, the values often associated with recursive methods will still remain, this means that the nodes in OriginNode will also have information stored on direct ID values of their parents as well as their module identifiers. While those values will not be used to fetch trees, they are still used for other purposes, especially when connecting a number of nodes with one another. Instead of storing this information within the same tables, all this information is stored in a separate table for fetching data.

I have posted the basic table setup of OriginNode before, however the new and (yet again rewritten!) method has changed the structure quite a bit and it requires a revision here. This can be helpful for some of you readers out there who might face a similar challenge in setting up your infosystem architecture for your next project, so I will be giving a revised yet brief overview of the updated structure below.

Node Table
This table stores all nodes that share similar parameters. Every Node Table has a single parent node, but whether this parent is displayed for the user within the UI is up to the developer. This parent node within the table is automatically made invisible if the tree is assigned a parent from another tree. Fields within this node table are as follows:

  • id = Primary key of the field.
  • identifier = URL friendly string that is optional for the tree. When traversing the OriginNode architecture then both id’s and identifiers can be used to solving the path. For example, when one fetches data by using a string of ‘products/cars/112′, then OriginNode can find identifiers for products and cars, but not one for 112, in which case it will look for id of 112 instead from among the children of ‘cars’ node.
  • traversal_left = This is the left integer value for the tree traversal.
  • traversal_right = This is the right integer value for the tree traversal.
  • active = True or false flag whether the element is returned when data is being fetched from OriginNode.
  • period_start = Timestamp from what time the data is considered ‘active’ and thus returned when data is being fetched. This can be used for various purposes, such as pages that are ‘released’ at specific dates and periods. If this value is not set on the node, then the start time is ignored and data is always returned (unless restricted by the period_end field).
  • period_end = Timestamp until what time the data is considered ‘active’ and thus returned when data is being fetched. This can be used for various purposes, such as pages that are ‘closed’ after specific dates and periods. If this value is not set on the node, then the end time is ignored and data is always returned (unless restricted by the period_start field).
  • rights_read = This is a list of user group identifiers which have the right to see and read that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.
  • rights_edit = This is a list of user group identifiers which have the right to edit the data within that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.
  • rights_delete = This is a list of user group identifiers which have the right to remove that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.
  • f_* = Every custom field from Node Parameters Table (below) has its value stored in f_ prefix fields.

Node Parameters Table
This table stores all the custom fields that are stored within the Node Table. Every custom field is stored in Node Table with an f_ index.

  • identifier = String identifier that is also the field name, with a f_ prefix, stored in Node Table. This value is enforced to be unique.
  • type = this is a type keyword that determines what type of custom field it is. This ranges from simple fields such as checkboxes, radio buttons and dropdowns to WYSIWYG editors, color pickers, and connections with other nodes.
  • configuration = This is a serialized array, stored as a string. This carries whatever custom information the field type or its extension require, such as field length, allowed letters and other restrictions.
  • tab_identifier = This is the identifier string of the tab this field is displayed under when viewing the node of the Node Table. Fields with same tab identifiers are stored under the same tab. This value is always required or it will never be shown to the user.
  • fieldset_identifier = This is the identifier string of the fieldset this field is displayed under when viewing the node and the tab of the Node Table. Fields with same fieldset identifiers are stored under the same fieldset. This value can be null, which means that the field is not displayed within a fieldset.
  • weight = This is the weight of the field. Every node view will be built by taking into account the weights of the fields. First tab in node view will always be the one that has a field with the lowest weight. First fieldset under a tab will be the fieldset that has a field with the lowest weight. And fields with the same tab and fieldset identifiers will also be ordered based on the lowest weight first, and highest last. Basically the heavier a custom field is, the further back it is displayed.
  • table_display = Whether this custom field is also displayed in the Module view, in a tree or a list.
  • table_filter = Whether this custom field can be filtered in the Module view, in a tree or a list.
  • table_sortable = Whether this custom field can be sorted in a Module view, in a tree or a list.
  • rights_read = Whether these user groups have the rights to see and read the values of this field. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.
  • rights_edit = Whether these user groups have the rights to edit the values of this field. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.
  • value_required = Whether value within this field is required and cannot be null. This is not applicable to connections custom field types.
  • value_unique = Whether value within this field is required to be unique. This is not applicable to connections custom field types.
  • value_default = Default value stored within this field. This is not applicable to connections custom field types.
  • languages_dependant = Whether this field is languages dependant and has a new field for each of the languages. This means that in the case of – for example a page title – there will be three fields instead of one when viewing the node, one for each language. If this is set and the custom field is connections, then the connections will be only made with objects that are not language dependant or are of only the same language as the custom field.

Node Connections Table
This table has all the connections stored. In most cases this table is not used when fetching structure from the Node tables. All the connections however are still stored within this table and the traversal left and right values can be restored with the help of this table should something happen with the original tables. All subconnections (of the connections custom field type) are also stored in this table.

  • from_module = module identifier that the connection is from.
  • from_id = id of the node from the from_module that the connection is from.
  • to_module = module that this connection is created to.
  • to_id = id of the node that this connection is created to.
  • type = the type of this connection. This can be either [primary] (when the connection is part of the whole tree and deals with linked module nodes for traversal) or [secondary=field_name] (when the connection is not part of main structure and is only used to link another object, the field_name value identifies the custom field that this connection is used for).

In general this whole system is a little bit more complicated than the earlier versions of OriginNode concept, but the speed benefits here are rather impressive. Cutting down recursive searches will mean that even larger structures can be built with OriginNode with less problems when fetching large amounts of data. When this is paired with MySQL caching – which will be supported by OriginNode in ‘demand’ mode – then OriginNode architecture will be able to support even large scale infosystems of hundreds of thousands node objects.

How to use multiple domains within one environment

4 May, 2010 (11:17) | Web Development | By: Kristo Vaher

This is a quick and unrelated post to all readers out there who pay for hosting services in shared virtualhost environments. I have been asked this question a few times in the past, but I figured it is good to share the tips here. In Estonia there are a number of hosting services for relatively low price, but one of the complications comes when you happen to own numerous domain names and would like these domain names to be run within the same environment. You could essentially run a number of WordPress blogs with entirely different domain names under the same hosting service.

What this needs is that all but one of your domain names should be an alias domain name for your main domain name. Most hosting services allow this without additional cost and in fact allow you to set it up yourself (should this be a problem, contact your hosting services customer support). You would then own a number of domain names for which you do still have to pay a fee (usually yearly), but you would only need to pay for only one hosting environment. Drawback of this is that the space and resources used by that environment would then be shared, but as long as you run small scale websites there (blogs and other sites for personal use), it will not become a problem.

To make this happen you need to set up a new index file on your web server which would be run first by PHP. In this index file you would detect the address that the user was trying to access and then direct them to the proper files or project. In case of wordpress you should rename its index.php to something like wpindex.php (alternative is to direct Apache to use another file for index, however many hosting services disable use of .htaccess commands). If I wanted my blog waher.net to always show my blog, but would like my other domain wearenixy.net work as an alias domain name for the domain without having to pay extra for hosting services I would set up something like this:

<?php
    if($_SERVER['SERVER_NAME']=='waher.net' || $_SERVER['SERVER_NAME']=='www.waher.net'){
        include('wpindex.php');
    } else if($_SERVER['SERVER_NAME']=='wearenixy.net' || $_SERVER['SERVER_NAME']=='www.wearenixy.net'){
        include('wearenixy.php');
    }
?>

If the user types in waher.net they would be redirected to wpindex.php and if the user is redirected through my waher.net alias name wearenixy.net, another script would be executed for that purpose.

This is essentially setting up your hosting service to work as a mini ‘domain routing’ service within your own virtualhost.

All the best!