Phalcon 0.7.0 beta released

The newest version of Phalcon has entered the beta stage. 0.7.0 Beta 1 is now available. This upcoming release introduces features requested by the community, to make the framework more extensible and more robust.

Some of the most important features introduced in this version are highlighted below:

Interfaces We have added over 40 interfaces to the framework. Most of the components/classes now have interfaces that allow the framework to be extended as much as possible. The developers can now simply implement the relevant interface and replace specific (or all) parts of the framework with custom classes. In addition to this, developers can create new adapters for existing components thus expanding the framework according to their needs.

For example:

<?php

class MySessionHandler implements Phalcon\Session\AdapterInterface 
{
    public function start()
    {
    }

    public function setOptions(array $options)
    {
    }

    public function getOptions()
    {
    }

    public function get($index)
    {
    }

    public function set($index, $value)
    {
    }

    public function has($index)
    {
    }

    public function remove($index)
    {
    }

    public function getId()
    {
    }

    public function isStarted()
    {
    }

    public function destroy()
    {
    }
}

Independent Column Map The ORM now supports a independent column map, which allows the developer to use different column names in the model to the ones in the table. Phalcon will recognize the new column names and will rename them accordingly to match the respective columns in the database. This is a great feature when one needs to rename fields in the database without having to worry about all the queries in the code. A change in the column map in the model will take care of the rest. For example:

<?php

class Robots extends Phalcon\Mvc\Model
{
    public function columnMap()
    {
        // Keys are the real names in the table and
        // the values their names in the application
        return [
            'id'       => 'code',
            'the_name' => 'theName',
            'the_type' => 'theType',
            'the_year' => 'theYear'.
        ];
    }
}

Then you can use the new names naturally in your code:

<?php

// Find a robot by its name
$robot = Robots::findFirst("theName = 'Voltron'");
echo $robot->theName, "\n";

// Get robots ordered by type
$robot = Robots::find(['order' => 'theType DESC']);
foreach ($robots as $robot) {
    echo 'Code: ', $robot->code, "\n";
}

$robot          = new Robots();
$robot->code    = '10101';
$robot->theName = 'Bender';
$robot->theType = 'Industrial';
$robot->theYear = 2999;
$robot->save();

ORM queries through PHQL From 0.7.0, all the queries made by the ORM are now made through PHQL.

In PHQL, we’ve implemented a set of features to make your access to databases more secure:

  • PHQL implements a high level abstraction allowing you handling models as tables and class attributes as fields
  • Bound parameters are part of the PHQL language helping you to secure your code
  • PHQL only allows one SQL statement to be executed per call preventing injections
  • PHQL ignores all SQL comments which are often used in SQL injections
  • PHQL only allows data manipulation statements, avoiding altering or dropping tables/databases by mistake or externally without authorization

Object/Oriented Builder for PHQL A new builder is available to create PHQL queries without the need to write PHQL statements:

<?php

$builder = new Phalcon\Mvc\Model\Query\Builder();

$result = $builder
    ->from('Robots')
    ->join('RobotsParts');
    ->limit(20);
    ->order('Robots.name')
    ->getQuery()
    ->execute();

The same as:

$phql = "
    SELECT   r.*, p.* 
    FROM     Robots r JOIN RobotsParts p 
    ORDER BY r.name LIMIT 20
";
$result = $manager->executeQuery($phql);

Full escaping system for generated SQL Sometimes some our preferred names are reserved key words of the database system, so if they aren’t correctly escaped using them as part of a SQL statement will cause a syntax error. To fix this Phalcon implements a full escaping system for every SQL generated by the ORM.

The following PHQL statement:

$phql = "
    SELECT   Store\Toys\Robots.type,
             SUM(Store\Toys\Robots.price+Store\Toys\Robots.taxes) AS totalPrice
    FROM     Store\Toys\Robots 
    WHERE    Store\Toys\Robots.theType != 'virtual'
    GROUP BY Store\Toys\Robots.theType, 2
    HAVING   SUM(Store\Toys\Robots.price+Store\Toys\Robots.taxes) > 1000
"

Produces the following escaped SQL in MySQL:

SELECT   `robots`.`type`,
         SUM(`robots`.`price` + `robots`.`taxes`) AS `totalPrice`
FROM     `robots`
WHERE    `robots`.`type` != 'virtual'
GROUP BY `robots`.`type`, 2
HAVING   SUM(`robots`.`price` + `robots`.`taxes`) > 1000

Escaping columns also avoids possible SQL injections making applications more secure.

Events Propagation/Cancelation The EventsManager now controls the event propagation allowing the developer to stop events preventing other listeners from being notified of an event in course. This is a great feature for those that need to control every step of the application logic.

<?php

$eventsManager->attach(
    'db',
    function ($event, $connection){
        // We stop the event if it is cancelable
        if ($event->isCancelable()) {
            // Stop the event, so other listeners will not be notified about this
            $event->stop();
        }
    
        //...
    }
);

Registering services as “always shared” Phalcon\Di has been refactored to register services always as shared. Following the Singleton pattern, no matter how the service is retrieved from the services container it will return always the first instance created:

<?php

// Passing true as third parameter make it act as "always shared"
$di->set(
    'session',
    function (){
        $session = new Phalcon\Session\Adapter\Files();
        $session->start();
        return $session;
    }
);

// Alternative way use "setShared"
$di->setShared(
    'session',
    function (){
        $session = new Phalcon\Session\Adapter\Files();
        $session->start();
        return $session;
    }
);

Returning the service in any way will return a shared instance of the service:

$session = $di->get('session'); // By name
$session = $di->getSession();   // Using the magic getter

0.7.0 includes other minor changes and bug fixes, see complete CHANGELOG here. Applications created with 0.5.x/0.6.x will compatible with this new version.

All the tests are passing on Travis, and our website is running with it some couple of weeks ago, please update your applications to this version and report any problems/bugs on github.

Linux/Unix/Mac users please compile the extension from the 0.7.0 branch:

git clone https://github.com/phalcon/cphalcon
cd cphalcon/build
git checkout 0.7.0
sudo ./install

Windows DLLs are available on the download page.

Thanks for using Phalcon!

<3 The Phalcon Team

[2012-11-21]