Developer Blog

Now you can have your composer dependencies usable from inside PHPixie. Create your composer.json in PHPixie root directory and add this to your configuration:

1
2
3
4
5
// /application/config/core.php
return array(
    //..Rest of the config
    'composer' => true
);

this will register composers’ autoloader wiht PHPixie and allow you to use vendor classes installed with it.

on 30 January 2013

Haml is a very efficient way of creating your HTML templates. It allows you to write shorter tags and avoid the need of closing the tags yourself. This second feature is especially useful because it allows you to avoid situations like hunting unclosed blocks throughout the page. Consider this piece of HTML:

1
2
3
4
5
6
<div id="fairies" class="wide">
    <div class="fairy">
        <div class="name">Tinkerbell</div>
        <div class="tree">Oak</div>
    </div>
</div>

In haml it would look like this

1
2
3
4
5
6
#fairies.wide
    .fairy
        .name
            Tinkerbell
        .tree
            Oak

In Haml indents describe element nesting, and you may also notice that class and id notations look just like in jQuery which may make your code even more readable. You can add php code and display your variables in Haml like this:

1
2
3
4
5
#fairies.wide
    - foreach($fairies as $fairy)
        .fairy
            .name
                = $fairy->name

The ‘- ‘ marks this line as PHP code and ‘= ‘ displays a variable. Placing a code inside a loop is done also using indenting.
PHPixies’ version of Haml also allows you to split your templates into multiple files and then include them like this:

1
2
3
#fairies.wide
    - foreach($fairies as $fairy)
        partial:fairy

The ‘partial’ keyword includes a haml subtemplate, in this case fairy.haml.
Filters for javascript and css are supported so you can include css and javascript in your markup like this:

1
2
3
4
:javascript
    <some javascript code here>
:css
    <some css rules here>

You don’t have to worry about using Haml impacting your performance. PHPixie caches rendered templates and later checks their modification time against the modification time of the source haml file, this way each template is rerendered only when it’s modified.
You can read more about using haml on http://haml.info.

on 28 January 2013

A new PHPixie Validation module is available. It allows you to easily validate user input and present the user with a list of errors he made while filling a form. Let’s try validating form POST data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$validate=Validate::factory(%this->request->post());
$validate
    //Username must be filled
    ->rule('username','filled')

    //Password must be filled and at least 5 characters long
    ->rule('password',array(
        'filled',
        array('min_length',5)
    ));

//Check if the input is valid
if($validate->valid()){
    echo 'Thanks!';
}else {

    //Get the array of errors for each field
    print_r($validate->errors());
}

By default all fields are optional, so if don’t add a ‘filled’ rule and the field is empty it will always be considered valid. The rule() expects three parameters: field name, an array of rules applied to this field, conditions that must be met for this rule to apply. Let’s take a closer look at the second parameter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//If you just need to add a single rule that doesn't require
//any additional parameters you can just pass it's name 
$validate->rule('username','filled');

//Otherwise you pass an array
$validate->rule('username',array(
    array('min_length',7);
));

//If the rule you wish to use requires more then one parameter
//you have to pass them as array
$validate->rule('age',array(
    array('between',array(13,60));
));

//If you wish the rule NOT to match place a '!' before it's name
//like this:
$validate->rule('username','!filled');
//It will become useful later on

If you call rule() multiple times passing the same field such rule sets will have an OR logic, so if any of them matches a field is considered valid:

1
2
3
//this way 'contact' can be either a url or an email
$validate->rule('contact','url');
$validate->rule('contact','email');

This becomes much more useful when combined with conditional rules. Conditions follow the same structure as a standart result set. The ruleset is only applied if those conditions are met.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Height must be between 3 and 7 inches if
//type is 'fairy'
$validate->rule('height',array(
        array('between',array(3,7))
    ),array(
        array('type',array(
            array('equals','fairy');
        ))
)
);

//Or it must be between 1 and 2 inches if
//type is 'pixie'
$validate->rule('height',array(
        array('between',array(1,2))
    ),array(
        array('type',array(
            array('equals','pixie');
        ))
    )
);

Of course you always could wrap those rules inside and if statement and just apply them whenever you would need them. But the largest drawback of such an approach would be that it would be far less portable. This way you could set you could set your Validate object once and then use it to validate different arrays of data like this:

1
2
3
//Validate new data
$validate->inputs($data);
print_r($validate->errors());

Lets now look at how the error array looks:

1
2
3
4
5
6
7
8
9
10
11
12
13
Array
(
    [username] => Array
        (
            [0] => filled
        )

    [password] => Array
        (
            [0] => min_length
        )

)

This would mean that username was not filled and password didn’t meet minimum length. You can set other identifiers for a rule like this:

1
2
3
4
5
6
//This would return a password_length_not_met
//error inside the errors array
$validate->rule('password',array(
    'filled',
    array('min_length',6,'password_length_not_met')
));

Such identifiers are very useful for things like translations etc. You can find the full set of allowed rules and their parameters as static methods of the Validate Class and you are free to add your own rules using the validate.php config file like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
// /modules/validate/config/validate.php
<?php
return array(
    'rules' => array(

        //This would check if the value consists of uppercase
        //letters only
        'uppercase' => function($val) {
            return (bool)preg_match('#[A-Z]#',$val);
        }

    )
);

If you just need to use a function a single time and don’t feel like it’s important enough to be added to the config file, you can always use the func rule like this:

1
2
3
4
5
6
$validate->rule('access_token',array(
    'filled',
    array('func',function($val){
        //Returns either true or false
    },'token_invalid')
));
on 23 January 2013

I already posted some benchmarks of PHPixie comparing it to ohter popular frameworks. This time I want to show you why are some of these frameworks faster than others.

To compare the amount of boilerplate code I took the same simple application I used for benchmarking, and inserted an addition 0.01 second delay into them. As the delay always takes the same amount of time we can use it as a time reference.

The diagrams below are nested time diagrams of function execution, nested blocks represent fnctions calling one another, the size of each block represents the time the function was running. A brown block labled usleep is our hardcoded delay, so the bigger the brown block is the less time the framework took to prepare and run. You can click the images to enlarge them.

PHPixie

PHPixie was created to be very unobtrusive so our hardcoded delay occupies half of the whole execution time.

PHPixie framework benchmark

PHPixie framework benchmark

Yii

Yii framework benchmark

Yii framework benchmark

Yii took 50% longer to initialize for this basic application to run. We can see that the most of the time is wasted on autoloding classes, a lot of frameworks that make heavy use of extending classes and having a multitude of them suffer from this.

Kohana

Kohana Framework Benchmark

Kohana Framework Benchmark

Kohana wastes a lot of time searching files over the cascading file system. A lot of speed is wasted on Kohanas way of handling overriding core classes. For this very reason each class has a Kohana_Classname class and Classname class, which means twice as much files to load.

FuelPHP

FuelPHP Framework Benchmark

FuelPHP Framework Benchmark

Fuel seems to be just a bit slower than Kohana, but it seems that FuelPHPs’ cascading file system is slightly better.

Laravel

Laravel Framework Benchmark

Laravel Framework Benchmark

Laravel is going head to head with FuelPHP, but it would be interesting to compare the differences in their execution. While most delay in FuelPHP comes from autoloading, which could be overcome in the same way as it might be done for any cascading file system: by having a script that would place all class in the application folder before deployment. Laravel seems to have completely different problems. For one you might have noticed that usleep gets not just one but a few blocks in Laravel, this is because of how the controller is called (via call_user_func_array and XDebug has problems profiling such calls), this is not a problem though. You can notice some strange classes from Symfony components being instanced, you also see a glimple of mcrypt_decrypt being called etc. Basically the kind of boilerplate I was talking about in the first place.

CakePHP

CakePHP framework Benchmark

CakePHP framework Benchmark

CakePHP took 95% of the time to initialize the framework, it is almost 90% slower than PHPixie, mostly because of its rather complex architecture, there is an Event manager etc. But there are calls to Controller->__isset() occupying a lot of processing time which probably should be optimized.

As it is getting late I did not generate grind for other frameworks, I think these should suffice. Of course the tradeoff when choosing a framework is speed vs features usually, but you have to ask yourself how many times in your next project, that will likely just store and display data from the database, you will need an advanced HTTP protocol handler class or some complex class inheritance. You don’t need to go for features that you will not use just because they are there.

on 21 January 2013

ORM has just received a new update. To better explain what is it for consider the following scenario: You have fairies living in trees and you wish to show the name of each fairy and the tree she lives in. You would do it like this:

1
2
3
$fairies=ORM::factory('fairy')->find_all();
foreach($fairies as $fairy)
    echo $fairy->name." ".$fairy->tree->name."<br/>";

The problem with is that for each of these fairies a separate request would be made to the database to get the tree. This is really inefficient, so there is an option to preload them all at once. Like this:

1
2
3
$fairies=ORM::factory('fairy')->with('tree')->find_all();
foreach($fairies as $fairy)
    echo $fairy->name." ".$fairy->tree->name."<br/>";

You can specify multiple relationships to preload and can use the dot notation to preload relationships of those relationships:

1
2
3
4
//This will preload the 'tree' relationship,
//the 'forest' relationship of the tree relationship
//and a 'home' relationship
$fairies=ORM::factory('fairy')->with('tree.forest','home')->find_all();

The only limitation is that only belongs_to and has_one relationships can be preloaded.

1
2
3
//You cannot do this
ORM::factory('tree')->with('fairies')->find_all();
on 18 January 2013

Here is a callgrind for a simple application in PHPixie that accepts a url parameter, uses ORM to access the object from the database and renders a view. What it displays is the time that was used on each function call, the bigger the block the longer it was executing. Nested blocks depict functions being called inside other functions.

PHPixie PHP framework call map

PHPixie PHP framework call map

It would seem that autoloading and getting configuration parameters take up most of the time, which is true because both require searching the filesystem. Let’s now compare this to something more tangible, e.g. a 0.01s delay.

PHPixie PHP framework callgrind compared to 0.01s delay

PHPixie PHP framework callgrind compared to 0.01s delay

The picture is much clearer now, that small delay took 57% of the call time compared to PHPixie, so even if you are really concerned about the speed of your application you don’t need to worry at all about PHPixie being any kind of overhead.

on 17 January 2013

If there are few developers working on a single project they often face a problem of keeping their databases up to date with the latest changes. If they are adding tables and modifying columns on a day to day basis, keeping track of those changes may be really troublesome since the database cannot be placed under SVN or Git. The workaround here is to use special files that when executed apply a series of changes to the system. In this way you can easily notify other developers that you changed something by adding that file to your source code. That’s how database migrations work and PHPixie just got one of its own.

To enable migrations you need to download the migration module from Github put it inside your modules folder and add ‘migrate’ to the modules array in /application/config/core.php. After this let’s configure the module to use our database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// /modules/migrate/config/migrate.php
&amp;lt;?php
return array (

    //As with the datatabasethe migration module can handle multiple
    //configurations. 'Default' is the default one
    'default' =&amp;gt; 
        array (

            //Specify a database connection to use
            'connection' =&amp;gt; 'default',

            //Path to a folder where migration files for this 
            //configuration are stored
            'path' =&amp;gt; '/modules/migrate/migrations/',

            //Name of the last migration applied to the database,
            //it will be automatically updated when you migrate
            'current_version' =&amp;gt; null
          ),
    );

Now let’s look at the migration files themselves. There are some supplied with the module by default so we’ll use them as reference. First thing you should take note of id the naming of the files, the migrations are incremental and are applied based on file name in an ascending order. So that 1_adding_fairies_table.php will be first, then 2_adding_pixies_table.php and so on. Most of the other systems have you use a command line tool to add migrations or force you to write them as classes with up() and down() methods used to upgrade to and revert from a migration, but that is very cumbersome when the changes are small and frequent. PHPixie let’s you specify changes using simple arrays like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// /modules/migrate/migrations/1_adding_fairies_table.php
&amp;lt;?php
return array(

    //Each element of this array will be treated as table,
    //with array key treated as table name and its value as
    //an array of column definitions. If the table was not
    //referenced in a migration before this one it will be created,
    //otherwise it will be altered.
    'fairies' =&amp;gt; array(
        'id'=&amp;gt;array(

            //'id' type is a shorthand for
            // INT AUTO_INCREMENT PRIMARY_KEY
            'type' =&amp;gt; 'id'
        ),
        'name'=&amp;gt;array(

            //'Name' will be a column of type VARCHAR(255)
            'type'=&amp;gt;'varchar',
            'size'=&amp;gt;255
        )
    )
);

Now our second migration will alter the newly created fairies table and add a new pixies one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// /modules/migrate/migrations/2_adding_pixies_table.php
&amp;lt;?php
return array(

    //Because 'fairies' already exists, this will alter it.
    'fairies' =&amp;gt; array(
        'name'=&amp;gt;array(

            //Altering the type of an existing column to VARCHAR(30)
            'type'=&amp;gt;'varchar',
            'size' =&amp;gt; 230,

            //To rename the column we just specify a new 'name' for it
            'name'=&amp;gt;'fairy_name'
        )
    ),

    //Creating another table
    'pixies' =&amp;gt; array(
        'id'=&amp;gt;array(
            'type'=&amp;gt;'id',
        ),
        'tree'=&amp;gt;array(
            'type'=&amp;gt;'text'
        ),
        'count'=&amp;gt;array(
            'type'=&amp;gt;'int'
        )
    )

);

And now let’s drop the fairies table and rename pixies into fairies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// /modules/migrate/migrations/3_some_altering.php
&amp;lt;?php
return array(

    //Dropping a table
    'fairies' =&amp;gt; 'drop',

    'pixies' =&amp;gt; array(

        //Renaming a table is similar to renaming a column
        //but because 'name' is quite a popular name for columns
        //you should use 'rename' to specify table renaming
        'rename' =&amp;gt; 'fairies',

        //Dropping a column is just the same as dropping a table
        'tree' =&amp;gt; 'drop'
    )

);

The important part of this third file is to remember that the alterations are made in the same succession as they appear in the file. So that if you want to drop a table and then rename the other into the same name you need to do this in this order. Otherwise it will try renaming the pixies table before the fairies one is dropped and you will receive an error. Note that though migrations let you recover your table structure by reverting back it will not recover the data inside it.

Now the whole beaty of this modules comes from that you dont need to write anything for reverting back to previous migration. the module will deduce how to undo the changes automatically!

Alright, now that we know how to use the system, let’s try actually applying the migrations. For that just navigate to http://localhost/migrate/ and see this handy interface:

Migration module screenshot

Migration module screenshot

Using it you can update or revert your database to any revision just by clicking a button.

Note that this system is designed for developer use and not intended for your website users, that’s why for security reasons you should disable the module by removing it from modules array in core.php after your migration is complete.

on 16 January 2013

The simplistic configuartion structure with having a single config.php while easy to maintain is not wel suited for modularity, so it has received some changes. Now instead of putting your configuration options in /application/config.php you create files inside the /application/config/ folder.   Because of the cascading file system you may also keep those files inside modules. For example you can move the file from /application/config/database.php to /modules/database/config/database.php with no changes to the code. to better describe the configuration files let’s assume that we want to describe a magical forest with a config. It will look like this:

1
2
3
4
5
6
7
8
9
// /application/config/forest.php
<?php
return array(
    'trees' => 8,
    'dwellers' => array(
            'fairies' => 8,
            'pixies' => 10
        )
    );

and you can access these options like this (notice that the first part of the option name is the name of the file):

1
2
3
4
5
6
7
8
9
//Getting an option
$num_fairies=Config::get('forest.dwellers.fairies');

//Setting or updating an option
$num_fairies=Config::set('forest.dwellers.fairies',15);

//Writing options back to config file
$num_fairies=Config::write('forest');

Using it in this way can help better organize your configuration files.

Also a new Email module has been added which allows you to send emails using Swift Mailer library.

on 10 January 2013

As I wanted to set up a system to benchmark PHPixie I decided I might as well benchmark other frameworks too. Performance comparison done by Yii developers is laughable at best, because they benchmarked the “Hello World” scenario which tells nothing about database access speed, ORM performance or view rendering. This is really biased towards frameworks that lazy load classes and modules on first request to them. If the framework initializes slower it doesn’t mean it works slower too. Thats why:

We will benchmark a complete scenario that includes parsing URL parameters, getting data from the database and rendering a view.

Also I will not be testing this on a dedicated machine but on a VPS with limited resources. Why? Because that’s where a lot of website end up. So here is the setup:

  • 1  GHZ CPU
  • 256 MB RAM
  • XCache Enabled
  • PHP-FPM
  • 100 concurrent connections
  • 30s test time

Framework versions benchmarked:

  • PHPixie 1.45
  • Yii 1.1.13
  • Kohana 3.3.0
  • FuelPHP 1.4
  • CodeIgniter 2.1.3
  • Laravel 3.2.1 and 4 Beta (very slight performance difference so I included only 3.2.1 in graphs)
  • CakePHP 2.2.4
  • Symfony 2.1.6
  • Zend 2.0.6

We will run a test application that will have to take a parameter from the URL and output the record from the database. We will have a Fairy table with two columns: id and name. The URL will be http://test/fairies/get/1 and we expect to get the name of the first fairy from the database. This way we can test routing speed and database access. Here we go:

PHP Framework Benchmark

PHP Framework Performance with XCache

Well it seems that Yiis’ claims are a bit overhyped, it is indeed faster then most frameworks, but the difference is not as drastic now. I’ve been hearing a lot about Laravel 4 lately, but the results that I came up with Laravel 3 were mostly the same.

So now let’s try without the XCache:

PHP Framework Benchmark without opcache

PHP Framework Benchmark without opcache

As you can see the difference is quite larger this time. PHPixie is approximately twice as fast as Zend. Why so? Mostly because we update the code all the time to tweek little things that hog miliseconds of performance, for example trying to use str_replace instead of preg_replace where possible, etc.

Let me say a few words about my personal thoughts.

CakePHP  has very good documentation, I’ve created few sites with it some time in the past, and it seems a decent system, but it does kick you in soft places a few times, mostly because you can find a lot of tutorials on the internet that are in fact for its older version and don’t work with the new release. Their database abstraction feels a bit dated and doesn’t really provide a convenient way of querying the database, especially when passing params to find() as array. You don’t get any hints when doing that (like code completion when using query builders in other frameworks) and have to remember those parameters which means consulting the API a lot, which doesn’t seem developer friendly.

Yii  was annoying for me to code in. Mostly because i hate code generation. Even today when i tried to do this simple application to benchmark I got this pregenerated website with contact form and about page etc, and had to spend time to actually not use it, it felt like I was modding a CMS rather than coding my own code. On the other hand generated models do seem to be a workable idea so I can’t hold this against Yii. Another thing that bugs me about it is naming things like Gii etc. The name doesn’t describe at all what it does. Also it is really hard to find a tutorial that actually tells you which code to write rather they tell you which buttons to press to generate the code, and leave you wondering how to actually do the customization part.

Codeigniter was super awesome back in the day, it was simple, elegant, everything. It’s still pretty good now but some developers complain about it moving slowly with PHP focusing on backwards compatibility. IMHO apart from the namespaces there’s little reason for a framework to force PHP 5.3 on you and there is nothing really groundbreaking in PHP 5.4, except for maybe traits. But Codeigniter still feels dated though, especially its ActiveRecord implementation. PHPixie follows a lot of Kohana practices which follows CodeIgniter, so you might say that CI is PHPixies’ grandad.

Kohana is something that I like and have used a lot. The tutorials are for the most part non-existent, but it’s  rather intuitive to write in. What I really liked is the lack of master page layout by default, like those that CakePHP and Yii have, which is good because you usually define it yourself by extending a Controller, so you have more control over it.

Laravel  I didn’t like, there’s just no edge to it apart from branding. They seem so consumed by branding and naming everything those strange names, e.g. Eloquent and Blade. They keep on telling you that their bundle system is the best and their ActiveRecord implementation is the best when it’s more or less same thing as you would expect from any framework, e.g. eager loading is a cool idea but it has been in Kohana since a long time and Yii too. I can’t smile enough when I see the “A Framework For Web Artisans” and “All the cool kids are doing it” punchlines. I assume the idea is to use coolness as a factor e.g. like Apple does. What is really good about Laravel is detailed configuration files which other frameworks lack in comparison.

Zend is still being Zend. It is slow but has extensive libraries, large community and a lot of good documentation. I don’t think anyone uses it for small to medium projects though.

Symfony is still slow, though it targets the same enterprise niche as Zend does. I never used Twig, as PHP is a very good templating language on its own, the idea of declaring templates is rather useful though, and looks much better then using includes inside PHP. Using Doctrine was also a choice of sacrificing speed for stability. If I had to choose between it and Zend though I would pick Symfony because it seems a bit more straightforward for the developer (e.g. me).

Now where does  PHPixie fit in? If you know that your application will have no use for the complex stacks of frameworks like Zend, that all you actually will use is mostly database access and showing pages and making AJAX calls you need something that does just that, something that let’s you built upon what you decide is best and let’s you deploy applications fast. If further down the line you come across that you actually need an additional feature you can easily add a library to PHPixie with no hustle at all. On the other hand large projects usually tend to have their own implementation of virtually everything and PHPixie can provide a very strong foundation for that.

on 3 January 2013

PHpixies’ home just got a new design as you might have noticed. I know a lot of you guys like the old style, but we wanted to give it a more appropriately themed look. But thats not all, we are also moving the source code to GitHub, so feel free to fork us so we can all work to make PHPixie the fastest framework ever. I’ll be managing all the pull requests myself and I’ll be sure to include as much as possible. Of course it would be nice if you obided same formatting standarts as PHPixie currently uses, though if I pull your changes into the main code I’ll reformat them myself.

on 28 December 2012