Learn / eZ Publish / A Joyride to eZ Components beta2

A Joyride to eZ Components beta2

Taking a solid Road

For our joyride, we will take a solid road: The eZ Components beta2 . Since the beta1 release of the eZ Components, we - the eZ systems developers - have put a lot of effort into making the enterprise PHP plattform usable for early adopters. So, relax and enjoy while I first talk about the global changes being introduced in the beta2 release, which have affected all components. After that I will tell you about two specific components which where modified to be more reliable.

We introduced some changes which affected all eZ components equally. Most notably, we put a lot of effort into writing good inline documentation and decided to use structs instead of arrays whenever applicable.

High Quality Documentation

I have to admit that I never wrote that much documentation within a software project, although I always assumed that I did write a lot in previous times. Hence, concerning the eZ components, I promise to you, you will not find one element which is not thoroughly documented. When browsing the code in the online documentation, you will see that there is information available for all class/method/constant/attribute/property/.

No doubts, the quality standards for the eZ components documentation have been raised from beta1 to beta2 and the complete API docs are now much more structured and complete. Each main class has a clear usage example shipping with its documentation and the different framework elements are well linked, if dependencies exist. Besides that, there is information available about all thrown exceptions and almost all inherited exceptions.

Structs instead of Arrays

The biggest changes have taken place when it comes to code clean-up and the unification of implementation approaches. This includes the usage of so-called structs in favor of arrays. A struct modelled in PHP is basically a class that has only public attributes and a constructor. Doing data storage within structs has four major benefits when compared to the use of arrays:

  1. Structs are much more readable than arrays.
  2. Structs are fully documentable (not only by using embedded HTML) when working with phpDocumentor.
  3. In cases of emergency, you can extend structs easily to become a real class.
  4. Imagine using overloading, then you can even implement automatic value checks into your data structures.

An argument against using structs in PHP is usually the speed penalty you encounter when using many classes, but we found that PHP 5.1's OO is fast enough to replace the complex arrays by simple classes .

Some of the changes affected only single eZ Components. Although there is a long list of available components, I will concentrate on the modification of two of them, the Translation and ConsoleTools components.

Translation

The Translation component reads XML translation definitions (the Qt Linguist format), supports caching of translation contexts and presents you with a class to apply translations to strings. A filter system allows you to transform translation definitions for special use.

Derick Rethans added an implementation of the SPL Iterator interface to allow faster and more convenient looping through translation backend contexts like this:

<?php
foreach ( ezcTranslationTsBackend as $contextName => $contextData)
?>

In beta1 you had to use explicit haveMore() and currentContext() calls to do this.

ConsoleTools

The ConsoleTools component is a set of classes to do different actions with the console (also called shell). It assists you with printing formated text to the console and can render progress bars, tables as well as status bars and contains a class for parsing command line options.

I myself did a lot of work on this package (which I initially created). The idea was basically, to take over the small parts of eZ Publish code that handles console output and put it into a cute API. While desining the API, we had the idea of adding some new stuff to the implementation like the Progressbar and the Table class.

I actively used this component in a project already, thus I put much work in getting this package smooth after all. Now, the API is really cool and I very much enjoy using it.

One of the most significant changes is a kind of pseudo struct. It is being used in the ezcConsoleOutput class, which allows the output of formated text to the console. A format is defined by a fore- and background color as well as style attributes like bold.

Let's take a look of the benefits gained by introducing the pseudo struct. In beta1 you did:

<?php
'format' => array</a>(
  'default' => array(   // pseudo format (used when no format given)
    'color' => 'green', // green foreground color)

  <'success' => array // define format "success"     
     'color' => 'white', // white foreground color
       'style' => 'bold',  // bold font style
  ),
  'failure' => array(   // Define format "failur"
    'color' => 'black', // black foreground color
      'bgcolor' => 'red', // red background color
      'style' => 'bold',  // bold font style
  ),
),
?>

In eZ Components beta2 you write:

<?php
$out->formats->default->color = 'green';
 
$out->formats->success->color = 'white';
$out->formats->success->style = <a href="http://www.php.net/array" mce_href="http://www.php.net/array">array</a>( 'bold'>);
 
$out->formats->failure->color = 'red';
$out->formats->failure->style = <a href="http://www.php.net/array" mce_href="http://www.php.net/array">array</a>('bold');
$out->formats->failure->bgcolor = 'blue';
?>

Much easier, isn't it? What happens here is that in the background, struct (or struct-like) classes are generated on the fly, which automatically validate the provided values.

Even nicer is the new interface for the ezcConsoleTable class, which manages the generation of tables on the shell for you. I do not dare to show to you the code of beta1 as it was simply not satisfying.

When working on the beta2 version, I sat back and asked myself this basic question: "How would one access the data of a table structure?" The answer was simple: "Through an array!" You will understand when you consider that two-dimensional arrays are simply table structures (presuming that they have indices with int > 0).

So far, so good, and I continued asking myself: "How would one access the formating of a table?" The answer was just as simple as before: "Through an object!" Now, the ezcConsoleTable* classes implement one or more of the SPL interfaces to emulate array-like access as demonstrated further below. I heard Marcus Börger talking about SPL and iterators at several conferences. "Interesting stuff", I always thought to myself, but I never really had a concrete use for it ? in the ConsoleTools component I finally got to use them.

As software code can say more then a thousand words, let's take a look at the following sample. Please note that rows of ezcConsoleTableinherit the format and alignment from the global default values if no other values have been provided. Furthermore, the cells inherit the row format if they were set to become the default value. Same applies to borderFormat for the rows, which inherits from the global default if not explicitly changed.

For demonstration purposes, we create a simple table which is going to look like this:

The implementation of this table with the help of the ConsoleTools component makes up the following code. Please take a look at the inline comments to understand the routines.

<?php
// Create a new table, $out is an ezcConsoleOutput instance
$table = new ezcConsoleTable( $out, 60 );

// Create first row and in it the first cell
// Note that during the array access, this cell is created on the fly
$table[0][0]->content = 'Headline 1'; 
  
// Create 3 more cells in row 0
for ( $i = 2; $i < 5; $i++ ) 
{   
     // Each array-append creates a new ezcConsoleTableCell object
     // transparently and we can directly access it.
     $table[0][]->content = "Headline $i"; 
     }   
$data = array( 1, 2, 3, 4);
// Create some more data in the table...
foreach ( $data as $value ) {      
     // Create a new row each time and set it's contents to the actual value
     // In this place we generate rows on the fly, using the array-append syntax
     // While the cell is explicitly accessed and created automatically
     $table[][0]->content = $value; }   

// Set a format to be used for the first table row's border
// All other rows have "default" assigned</em> 
$table[0]->borderFormat = 'headline';

// Set the content format for all cells of the 3rd row to "sum"
$table[2]->format = 'sum';  
//Print the table, through the output object, we supllied during construction
$table->outputTable();
?>

Cool thing, isn't it? Let's look at another sample table so you can better understand how this works. First, I will show the screenshot of the console output to you, then you will see the source code. Again, further explanations are given in the inline comments.

<?php
// Initialize the console output handler
// We left that out in the last sample
$out = new ezcConsoleOutput();   
// Define format schemes for even and odd rows, named effectively
// Each format can be defined by a color, a bgcolor and an array of style-
// attributes
$out->formats->evenRow->color = 'red'; 
$out->formats->evenRow->style = array( 'bold' );   

$out->formats->oddRow->color = 'blue'; 
$out->formats->oddRow->style = array( 'bold' );   

// Define format schemes for even and odd cells</i> 
$out->formats->evenCell->color = 'red'; 
$out->formats->evenCell->style = array( 'negative' );  
 
$out->formats->oddCell->color = 'blue'; 
$out->formats->oddCell->style = array( 'negative' );  
 
// Create a new table with a width of 60 chars</i> 
$table = <b>new</b> ezcConsoleTable( $out, 60 );   
// Set global cell content alignmengt to right align
$table->options->defaultAlign = ezcConsoleTable::ALIGN_CENTER;   

// Make iteration for a 5x5 table
 for ( $i = 0; $i < 5; $i ++ ) 
{     
     for ( $j = 0; $j < 5; $j++ )     
{         
     // Fill each table cell with the string ##         
     $table[$i][$j]->content = '##';         
     if ( $i === $j )         
{
     // On diagonal line set explicit cell format             
     // Choose wether to set the even or odd format
     $table[$i][$j]->format = $j % 2 == 0 ? 'evenCell' : 'oddCell';         
       }    
    }     
    // Set global format for even/odd rows
    // Each cell in this row which was not explicitly touched in the each above
    // will inherite the format chosen    
    $table[$i]->format = $i % 2 == 0 ? 'evenRow' : 'oddRow'; 
    // Set border format for even/odd rows
    $table[$i]->borderFormat = $i % 2 == 0 ? 'evenRow' : 'oddRow'; 
}   
$table->outputTable(); 

?>