Mighty Webdeveloper » Coding http://www.mightywebdeveloper.com Webdevelopment Blog Fri, 14 Mar 2014 11:19:39 +0000 en-US hourly 1 http://wordpress.org/?v=4.2.2 Faceted navigation in PHP and MySQL Tutorial – part 1 /coding/faceted-navigation-in-php-mysql/ /coding/faceted-navigation-in-php-mysql/#comments Sun, 02 Mar 2014 18:26:02 +0000 /?p=375 Continue reading...]]> In this tutorial we are going to build a simple PHP/MySQL faceted navigation from scratch. In case you don’t know what faceted navigation is (or faceted search, layered navigation), it’s the nice filtering mechanism you see on most e-commerce sites in some form or another next to the product listing (see image).

Magento faceted navigation example

Magento faceted navigation example (zumiez.com)

With each newly selected filter the resultset is narrowed down accordingly which allows user to quickly find the items (products, classifieds, articles, etc.) that meet their criteria. This search mechanism is most useful when a dataset needs to be filtered based on multiple properties.

Unfortunately MySQL does not support faceted search out-of-the-box. There are dedicated external search applications such as SOLR or ElasticSearch which index the facets automatically for filtering. However not everyone has the knowledge or resources required to run such an application. Luckily we can achieve similar results while maintaining good performance using MySQL and PHP by setting up an index table and making some clever table joins.

The example data

You can download an SQL export of all the example data here.
Let me first introduce the dataset we’re going to work our magic on for this example:

table: products
+----+-----------------------+----------+-----------------+--------+
| id | name                  | type     | brand           | colour |
+----+-----------------------+----------+-----------------+--------+
|  1 | Black Jacket by Acme  | jacket   | Acme Apparel    | black  |
|  2 | Blue Jacket by Acme   | jacket   | Acme Apparel    | blue   |
|  3 | Blue Jacket by FF     | jacket   | Fictive Fashion | blue   |
|  4 | Orange Trousers by FF | trousers | Fictive Fashion | orange |
+----+-----------------------+----------+-----------------+--------+

The faceted navigation in this example without any of the filters selected will look something like this:

Type:
Jacket (3)
Trousers (1)
Brand:
Acme Apparel (2)
Fictive Fashion (2)
Colour:
Black (1)
Blue (2)
Orange (1)

The user can filter the product overview simply clicking on the filter links which makes it a form of navigation to the user (hence the term faceted navigation).

Note the item counts next to each facet value, these will be updated to reflect the current resultset whenever a filter is added or removed.

]]>
/coding/faceted-navigation-in-php-mysql/feed/ 14
Bootstrap 2.0 Tabs JQuery Ajax Example /coding/bootstrap-2-tabs-jquery-load-content/ /coding/bootstrap-2-tabs-jquery-load-content/#comments Sun, 20 May 2012 15:06:42 +0000 /?p=235 Continue reading...]]> In the project I’m currently working on we are moving from JQuery UI to a Twitter Bootstrap/JQuery approach. In JQuery UI it is very easy to setup your tabs so that content gets dynamically loaded. Getting the same functionality in Bootstrap requires a little bit of extra coding so here’s an example of how to load content into your Twitter Bootstrap tab elements using JQuery.  After some searching I found a couple of examples but they all seem to be built for earlier Bootstrap versions and won’t work for Bootstrap version 2.0 and up. This example is based on this post but has been updated to work with the latest version of Bootstrap (2.0.3 as of writing).

This example obviously requires JQuery and the Twitter Bootstrap Tabs plugin. Make sure you load both before the JavaScript snippet below.

Here’s the HTML for the tab elements.

 
<div class="tabbable">
    <ul class="nav nav-tabs" id="myTabs">    
        <li><a href="#home"  class="active" data-toggle="tab">Home</a></li>
        <li><a href="#foo" data-toggle="tab">Foo</a></li>
        <li><a href="#bar" data-toggle="tab">Bar</a></li>
    </ul>

    <div class="tab-content">
        <div class="tab-pane active" id="home"></div>
        <div class="tab-pane" id="foo"></div>
        <div class="tab-pane" id="bar">Some static text. (displayed if AJAX request fails)</div>
    </div>
</div>

As you can see we don’t specify any content for the default tab as we’ll load this using AJAX. In the code below the default content will be loaded from the URL http://yourdomain.com/ajax/home.

After the HTML add the following JavaScript to initialize the first tab with content and bind the dynamic loading of content to all tabs.

<script>
    $(function() {
        var baseURL = 'http://yourdomain.com/ajax/';
        //load content for first tab and initialize
        $('#home').load(baseURL+'home', function() {
            $('#myTabs').tab(); //initialize tabs
        });    
        $('#myTabs').bind('show', function(e) {    
           var pattern=/#.+/gi //use regex to get anchor(==selector)
           var contentID = e.target.toString().match(pattern)[0]; //get anchor         
           //load content for selected tab
            $(contentID).load(baseURL+contentID.replace('#',''), function(){
                $('#myTabs').tab(); //reinitialize tabs
            });
        });
    });
</script>

The event target contains the full URL including the anchor so we use a regex expression to grab the anchor (which equals #<id>, which equals the CSS selector!) value.

Now in order to load the content we append the id to create the Ajax URL’s so make sure the names of your Ajax handler functions correspond with these id’s. You can easily alter this and set up alternate logic to load other URL’s. Note that if the URL cannot be found the tab will display the static content that is defined in the corresponding div with class tab-pane.

Note that in pre-2.0 Bootstrap the function to initialize the tabs was called tabs() (plural) whereas in 2.0 and above it is just tab().

As always if you have any questions feel free to post in the comment section!

]]>
/coding/bootstrap-2-tabs-jquery-load-content/feed/ 24
SharePoint Lists Webservice – Traverse all Folders and Files /coding/sharepoint-lists-webservice-traverse-all-folders-and-files/ /coding/sharepoint-lists-webservice-traverse-all-folders-and-files/#comments Fri, 18 May 2012 13:24:09 +0000 /?p=218 Continue reading...]]> How can we produce a list of all files and folders inside a SharePoint List using the GetListItems method of the Lists.asmx webservice? As the webservice documentation is clearly lacking in some respects here’s an example of how to do it.

This post might seem a bit random but it took me quite some googling before I got the XML correct so I figured this might help someone else facing the same problem.

There’s no need to write a recursive function or anything, we simply specify the ViewAttributes parameter in the CAML query to produce a flat list of all the files (and folders) inside the list. The syntax might be a bit confusing so here’s an example using the List ID:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>{ECBA10EA-3E46-4211-A54A-1DD97AAC40BF}</listName>
      <queryOptions>
        <QueryOptions>
           <ViewAttributes Scope="RecursiveAll"/>
         </QueryOptions>
       </queryOptions>
      <rowLimit>100000</rowLimit>
    </GetListItems>
  </soap:Body>
</soap:Envelope>

Without setting the

<ViewAttributes Scope="RecursiveAll"/>

we would only get items at the root level of the List. Note that we also added a rowLimit of 1000 as the standard rowLimit appears to be set to 100 when not specified. As you can see the QueryOptions needs to be embedded inside another queryOptions tag and will fail without it!

]]>
/coding/sharepoint-lists-webservice-traverse-all-folders-and-files/feed/ 1
PHP XPath Generator /coding/php-xpath-generator/ /coding/php-xpath-generator/#comments Fri, 02 Sep 2011 09:47:10 +0000 /?p=89 Continue reading...]]> In this post I’ll explain a clever way to automatically generate a list of XPath expressions that can be used to select any element and attribute in an XML document. We’ll use PHP’s SimpleXML extension to easily parse and traverse the XML document and to build a simple XPath generator.

I’ll start with a simple example XML document and the resulting output. Say that we are trying to import an XML feed with books:

<?xml version="1.0" encoding="UTF-8"?>
<products>
	<book type="paperback">
		<title lang="english">Snowcrash</title>
		<price currency="euro">3,99</price>
		<price currency="dollar">5,49</price>
		<weightGrams>247</weightGrams>
		<isbn10>0140232923</isbn10>
		<isbn13>9780140232929</isbn13>
	</book>
</products>

Running this through our XPath generator function results in the following list of XPath expressions:

products
products/book
products/book/@type
products/book[@type='paperback']
products/book/title
products/book/title/@lang
products/book/title[@lang='english']
products/book/price
products/book/price/@currency
products/book/price[@currency='euro']
products/book/price
products/book/price/@currency
products/book/price[@currency='dollar']
products/book/weightGrams
products/book/isbn10
products/book/isbn13

Generally you will only need the selectors for one particular element, in this case the book element. We’ll use an XPath expression to select this context element to limit the scope of our XPath generator.

An example of where this type of functionality might come in handy is when unknown XML data needs to be mapped into predefined fields such as columns of a database table or content types in a CMS. For example the Drupal Feeds module allows you to import XML data into existing Drupal content types. The source XML fields are mapped to the Drupal content type fields by means of user-defined XPath expressions. Currently the user has to specify these expressions by hand for each field. Wouldn’t it be nice to have a dropdown box available next to each field that contains a list of XPath expressions for all XML elements and attributes (especially when the user is not a progammer/XML expert)?

Here’s the full code, the comments should make it self-explanatory. If you are not familiar with the concept of recursion take a look at this article. In the code below the XML is supplied using the form POST method. You can try out a slightly modified version here.

<?php
$simpleXML = new SimpleXMLElement($_POST['XML']);          //create a SimpleXMLElement object from the XML document
$contextElements = $simpleXML->xpath($_POST['context']);   //select the context nodes
$contextElement = $contextElements[0];                     //grab the first context node
$xpathList = XMLElementToXPath($contextElement->getName(),$contextElement); 

foreach($xpathList as $xpath)
	echo $xpath."\n";

//recursive function that takes a SimpleXMLElement object and returns a list of XPath expressions
function XMLElementToXPath($currentXPath, $myXMLElement)
{
  $xpathList = array();
  $attributes = $myXMLElement->attributes();              //grab attributes from current root element

  foreach($attributes as $att_key=>$att_value)            //process element attributes (if any)
  {
    $xpathList[] = ($currentXPath!=''?$currentXPath.'/':'').'@'. $att_key;  //create XPath for attribute
    $xpathList[] = ($currentXPath!=''?$currentXPath:'').'[@'. $att_key.'=\''.$att_value.'\']'; //create XPath expression for element with certain attribute value
  }	

  foreach($myXMLElement->children() as $childElement)     //process children (if any)
  {
    $xpathList[]= ($currentXPath!=''?$currentXPath.'/':'').(string) $childElement->getName();  //create XPath expression for element
    if($childElement instanceof SimpleXMLElement)                              //if child is an XML node itself then go into recursion
    {
      $xpathList = array_merge($xpathList,XMLElementToXPath(($currentXPath!=''?$currentXPath.'/':'').(string)$childElement->getName(),$childElement));
    }
  }
  return $xpathList;
}
?>

As mentioned you can see a slightly modified version of the script in action here and you can download the source here. The generated list of XPath expressions isn’t complete, for example it doesn’t produce XPath expressions with combinations of multiple attributes. However this should be sufficient in most cases and can be easily extended when extra types of XPath expressions are needed. Feel free to drop any questions/comments below!

]]>
/coding/php-xpath-generator/feed/ 0
Convert MySQL to XML using PHP /coding/mysql-to-xml-php/ /coding/mysql-to-xml-php/#comments Thu, 09 Jun 2011 15:20:51 +0000 /?p=4 Continue reading...]]> How to  convert any MySQL table and data to a well-formed XML document using PHP. Building a  generic solution to a common problem.

In this tutorial we will create a standardized script that will convert a MySQL table of any shape or size into a valid XML document. This can be useful for any situation where you have to transfer data from a MySQL database into an XML based system. In some cases the “mysqldump –xml” might be sufficient. If you require output that’s different from the mysqldump format, or if you don’t have access to the mysqldump tool you will need to code your own solution. Creating a single-use script to handle specific data is of course quite easy, but would require custom coding for each table that needs to be converted to XML. I’m going to show you how (using a handy PHP function) you can build a more generalized solution. This mechanism will allow you to convert a MySQL table to XML, but also to a PHP array, CSV file (even though MySQL already supports CSV natively) or any other required format.

Let’s start with an example table and some data:

Table name: fruit

+--------------+----------------+------------------+--------------+
| fruit_id     | fruit_name     | fruit_colour     | price_per_kg |
+--------------+----------------+------------------+--------------+
| 1            | Banana         | yellow           | 2,99         |
| 2            | Orange         | orange           | 2,45         |
| 3            | Strawberries   | red              | 4,99         |
+--------------+----------------+------------------+--------------+

After running our PHP script the resulting XML will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<fruits>
   <fruit>
      <fruit_id>1</fruit_id>
      <fruit_name>Banana</fruit_name>
      <fruit_colour>yellow</fruit_colour>
      <price_per_kg>2,99</price_per_kg>
   </fruit>
   <fruit>
      <fruit_id>2</fruit_id>
      <fruit_name>Orange</fruit_name>
      <fruit_colour>orange</fruit_colour>
      <price_per_kg>2,45</price_per_kg>
   </fruit>
   <fruit>
      <fruit_id>3</fruit_id>
      <fruit_name>Strawberry</fruit_name>
      <fruit_colour>red</fruit_colour>
      <price_per_kg>4,99</price_per_kg>
   </fruit>
</fruits>

Pretty neat huh? 😉 So let’s get down to business and start by setting up our database connection:

<?php
//database configuration
$config['mysql_host'] = "localhost";
$config['mysql_user'] = "root";
$config['mysql_pass'] = "grape01";
$config['db_name']    = "fruit_store";
$config['table_name'] = "fruit";

//connect to host
mysql_connect($config['mysql_host'],$config['mysql_user'],$config['mysql_pass']);
//select database
@mysql_select_db($config['db_name']) or die( "Unable to select database");
]]>
/coding/mysql-to-xml-php/feed/ 51