Announcing the Phalcon Store!!

Further popular demand by our community, we have opened a modest store where we have Phalcon stickers ready for you to purchase!

In the near future we will add more swag for your collection so that you can show off Phalcon proudly!

The stickers are just 5 USD (for quantity of 5) and you will also pay the delivery charge of 2 USD worldwide. 

This allows us to get some funds toward our hosting bills and other immediate expenses. We hope you like them!

Don’t forget, you can always offer monetary contributions by clicking the Donate button locate at the top bar.

Thank you for flying with Phalcon!

Success Story - Guitarama.ru
image

Yet another success story from our community member Michael (Xpundel).

Greetings, Phalcon team!

As I wrote in comments to your post, I have a project, built on Phalcon framework.

It’s a Guitarama (http://guitarama.ru) - guitars tabs and chords catalog. The site is aimed towards Russian audience, and uses the Russian language, but I hope, there will be no problem to understand most of pages.

The site was re-launced using Phalcon at the beginning of January, 2013 and has since shown steady attendance growth. The Google stats can be found here.

The site use Twig as the template engine (historical reasons), but I recently realized that the speed of Twig does not suit the site, in the near future I plan to replace it with Volt. 

There are still a lot of optimizations to do, and work on the project is constantly in process.

Once again, thank you for a great framework and all what you are doing :)

Best regards,

Michael.

NOTE: The site is running on a server with a P4 processor @3GHz and 4Gb RAM

If you have success cases with Phalcon, let us know so we can review them and share them with the community on our blog. :)

Success story: Phalcon Main Site/Phosphorum
image

Our main website and the forum are powered by Phalcon Framework, both are open sourced and published on Github, you can use them as example to create your own applications or if you want to see how real websites perform with Phalcon.

Looking at our web analytics, so far this year  (1-Jan-2013/30-Abr-2013) we have served 67,566 visits, with 27,204 unique visitors (about 12,000 visits every month) having 232,819 pages served. In comparison, all the past year, despite just starting the project, we have served 100,136 visits (56,368 unique visitors).

Click here to see the full Google Analytics report of last year and here of this year

If you have success cases with Phalcon, let us know so we can review them and share them with the community on our blog.

:]

Spread the word about Phalcon // Get Involved

Amazing projects need amazing tools. We might not know you just yet, but we think you’d be a great fit for building a better web. Together, we’re ready to change the world!

Here at Phalcon, we’re building a new generation framework for PHP, we want to give you amazing performance, while help you develop with ease and fun.

We hope that you enjoy Phalcon as much as we do. Our doors are always open to receive your collaboration with the many things a project like this requires:

Documentation The repository of this website is available on github. Feel free to improve it, fix typos, add examples, add articles, etc. Also, if you can translate some of the content to another language, it will be very much appreciated!

Screencasts We all love screencasts, if you have some extra time and want to support the community with some nice videos teaching any framework’s feature, it’s very welcome. Check out our Vimeo Channel as a guide.

Testing No software is free of bugs, if you find out any, please do not hesitate to tell us. We have a testsuite with more than 8000 tests. However, unit-tests are never enough. Help us to improve our testsuite by adding more tests or improve the current ones. Every added test make the framework more stable and avoid introduce bugs by mistake or break something that is currently working. The overall stability of the frameworks highly depends on our tests.

Sample Applications Big examples help others to better understand how big things can be created with Phalcon, feel free to share repositories with sample applications helping others with their work, allow others to give you feedback about your work too!

Evangelism There are a lot of people that still don’t know that Phalcon exist or it really works. We are certain that many developers will benefit from hearing what Phalcon is all about and how it can help them. If you know of any PHP events/meetings and you wish to give a talk about the project, you have our full support. Who does not want to know about the tool that is going to revolutionize PHP development?

Share your experiences Don’t be shy, feel free to share with the community, the ways that Phalcon was useful to you. If Phalcon is a success case for you, let us share that with the community. Also, discuss what components needed extra work, what you could do easier, what benefits you got by using Phalcon. Although not everything can be implemented immediately, your input on new feature requests can greatly help us shape the future of the project. Your feedback helps us all.

Blog If you like writing, remember that our blog is open to tutorial submissions, created by you. If you have a blog of your own and have written something about Phalcon, we can publish also in our social network pages so as to achieve maximum visibility. If your blog post is in a language other than English, we want to share it and potentially translate it if possible. If you know about blogs related to PHP that are interested in present the project to their audience please let us know.

Social Networks Phalcon is evolving on a daily basis, through our desire to make it better. Social networks are part of our lives now, and we all interact with others through them. Sharing your Phalcon experience with your social circles will greatly increase the visibility of the project. More and more people will engage in our community, thus making it more powerful, even more feature rich and popular. Like, “+1”, share posts that we constantly post on every social network, engage in discussions regarding those posts. People that will discover Phalcon through your interactions will thank you!

We have a presence in most of the popular social networks. By following us, you are helping increase the project visibility:

Donations/Sponsoring We’re a tiny but effective core team of developers working our tails off, we try to spend as much time as possible to the project. All our passion for this project makes us want to be better every day. Phalcon is open-sourced software and volunteer efforts are needed for its constant evolution. You can help us keep the active development by donating to the project or sponsoring the development. More time and resources dedicated to the project means more activity, more improvement, better support, more amazing features, etc.

Contributing to Phalcon comes in all different shapes and sizes. Whether you’re a user helping us find bugs, providing feedback on our forum, or contributing code or design, we need you.

Thank you! 

We would like to thank all of our contributors and members of the community for pushing us to make Phalcon the best framework. Your kind words and engagement is what drives us to do better. We hope to meet and exceed the trust you put in Phalcon.

Thanks for flying with Phalcon! <3

Moving towards Phalcon 1.2: Help us to prioritize our roadmap

We are constantly trying to enhance Phalcon, to make it a better framework using a completely new approach towards PHP frameworks. We are continuously adding new features and keeping the core stable and increasing performance as much as possible.

Looking into future development, we would love to create a roadmap together and be clear as to what work is more important to the community so that we can all create awesome and fast applications.

For this reason, kindly visit our Github issues page and help us prioritize those issues marked with the label [NFR] or [New Feature Request]

Comment with a “+1” in those which you think are more important than others, or leave your comments and feedback if you think they need considerations to be taken into account. If you think that a feature is not listed and it would be also useful, you can add it to the list by following our NFR guide.

A big - thank you for your time and participation making Phalcon even better!

Phalcon 1.1 released!

After a series of beta releases, Phalcon 1.1 is finally released!

This release adds new functionality, fixes bugs, improves of the current components, improves performance and more! We’re constantly searching for the best balance between performance and functionality, building a robust framework that performs exceptionally well!

Main features in this release were highlighted in the beta article. Summary of key features below:

Thanks to all the community (enthusiasts/contributors/testers) for their amazing, continuous work, providing feedback about new features and improvements, reporting of bugs, improvements to documentation, etc!

You guys rock!

This time we also want to give thanks to our donors. Thank you for helping us maintain a very active development! Special thanks to NetBear Software for its continued support to the project.

1.1.0 includes other minor changes, bug fixes and stability improvements. You can see the complete CHANGELOG here.

If you have any questions about functionality, feel free to ask either in our Forum or Stack Overflow.

As always, a big thank you!

Sample Application: Vökuró // Authorization/Authentication/Security
Vokuro

Vökuró, is our new sample application to showcase the features of Phalcon. ​We implemented several features related to authorization​, authentication ​ and security. Some of the​se features have recently been introduced in the framework. This sample application ​provides a basic frontend and a backend where users/profiles/security can be managed.

The following features are implemented:

  • Sign Up of Users
  • Confirmation by email
  • Login of Users
  • Login throttling
  • Registering of invalid logins
  • Registering of successfull logins
  • Password hashing
  • “Remember me” option
  • Password recovery
  • Change password
  • Profile/Roles management
  • Permission management by profile
  • Templates for emails

Other features/examples:

  • Full namespaced application
  • Volt powered
  • Custom user components
  • Full use of the Forms builder and Validation components
  • Frontend/Backend without using a multi-module application

To run/test this sample application you will need Phalcon 1.1.0 beta 3 or ​higher. You can see an online version here.

You can clone the code from Github. We welcome all the improvements to this sample as pull requests. Hope this application serve as example and help to develop your own applications with Phalcon. Head on over to our forum if you have questions regarding the sample.

Enjoy!

Help the community to make Phalcon available on cPanel

In an effort to help developers with the installation of Phalcon, we have created a feature request with cPanel so that we can develop an installation script that would allow cPanel customers install the extension with literally one click.

http://features.cpanel.net/responses/add-support-for-phalconphp-extension-apache-php

Kindly visit the link above and upvote this feature. If we get enough votes the feature will be included in cPanel powered hosted sites.

Feel free to share the link with your peers and friends :)

Thank you!

Phalcon 1.1 beta released!

After ​our successful 1.0 release, we continue improving Phalcon ​with our latest release 1.1.0 (beta). In this article, we’re highlighting the most important features introduced:

QueryBuilder Paginator

In addition to the ModelResultset and NativeArray paginator, this version introduces the QueryBuilder paginator which uses a SQL LIMIT/OFFSET clause to obtain the requested results. This paginator is suitable to handle ​large datasets.

use Phalcon\Paginator\Adapter\QueryBuilder;

$builder = $this->modelsManager->createBuilder()
      	->columns('id, name')
  	->from('Robots')
  	->orderBy('name');

$paginator = new Paginator(array(
	"builder" => $builder,
	"limit"=> 10,
	"page" => 1
));

$page = $paginator->getPaginate();

Beanstalkd Queuing client

A simple client for the Beanstalkd queuing server is now available as part of Phalcon:

<?php

//Connect to the queue
$queue = new Phalcon\Queue\Beanstalk(array(
    'host' => '192.168.0.21'
));

//Insert the job in the queue (simple)
$queue->put(array('proccessVideo' => 4871));

//Insert the job in the queue with options
$queue->put(
    array('proccessVideo' => 4871),
    array('priority' => 250, 'delay' => 10, 'ttr' => 3600)
);

while (($job = $queue->peekReady()) !== false) {

    $message = $job->getBody();

    var_dump($message);

    $job->delete();
}

Encryption

This version includes a simple class to encrypt/decrypt data based on the PHP’s mcrypt library.

//Create an instance
$encryption = new Phalcon\Crypt();

$key = 'le password';
$text = 'This is a secret text';

$encrypted = $encryption->encrypt($text, $key);

echo $encryption->decrypt($encrypted, $key);

Assets Management

This component eases the task of adding static resources such as CSS scripts and Javascript libraries to then output them in the views:

//Add some local CSS resources
$this->assets
	->addCss('css/style.css')
	->addCss('css/index.css');

//and some local javascript resources
$this->assets
	->addJs('js/jquery.js')
	->addJs('js/bootstrap.min.js');

Then in the view:

<html>
    <head>
        <title>Some amazing website</title>
        <?php $this->assets->outputCss() ?>
    </head>
    <body>

        <!-- ... -->

        <?php $this->assets->outputJs() ?>
    </body>
</html>

Exception mode in ORM Validations

By default, when some of the validators in a creating/updating process fails, the methods save()/create()/update return ​ ​a boolean value​stating the success ​or failure ​of this operation. Now, you can change this behavior to use exceptions:

use Phalcon\Mvc\Model\ValidationFailed;

try {

	$robot = new Robots();
	$robot->name = 'Bender';
	$robot->save();

} catch (ValidationFailed $e) {
	echo 'Reason: ', $e->getMessage();
}

Hostname routing

Phalcon\Mvc\Router now accepts hostname restrictions on their routes

$router = new Phalcon\Mvc\Router();

$router->addGet('/api/robots', array(
	'module' => 'api',
	'controller' => 'robots',
	'action' => 'index'
))->setHostName('api.phalconphp.com');

Or use a group:

$group = new Phalcon\Mvc\Router();

$group->setHostName('api.phalconphp.com');

$groop->addGet('/api/robots', array(
	'module' => 'api',
	'controller' => 'robots',
	'action' => 'index'
));

$groop->addGet('/api/robots/{id}', array(
	'module' => 'api',
	'controller' => 'robots',
	'action' => 'show'
));

$router->mount($group);

Use Controllers in Mvc\Micro

To organize better micro applications, now you can set up classes as controllers

$collection = new Phalcon\Mvc\Micro\Collection();

//Use direct instantiation
$collection
	->setPrefix('/posts')
	->setHandler(new PostsController());

//Lazy instantiation
$collection
	->setPrefix('/posts')
	->setHandler('PostsController', true);

$collection->get('/', 'index');

$collection->get('/edit/{id}', 'edit');

$collection->delete('/delete/{id}', 'delete');

$app->mount($collection);

1.1.0 includes other minor changes, bug fixes, stability and performance improvements. You can see the complete CHANGELOG here. Check the documentation for this version

Help with Testing

This version can be installed from the 1.1.0 branch:

git clone http://github.com/phalcon/cphalcon
cd build
git checkout 1.1.0
sudo ./install

Windows users can download a DLL from the download page.

We welcome your comments regarding this new release in Phosphorum and Stack Overflow. If you discover any bugs, please (if possible) create a failing test and submit a pull request, alongside with an issue on Github.

Thanks!

Tutorial: Creating a Blameable behavior with Phalcon

In this tutorial, we’re going to explain how to create a behavior for the Phalcon’s ORM. Its goal is keep track of data changed by users on specific models. This behavior is often known as Blameable.

A model in Phalcon triggers specific events when operations like create/update/delete are performed. These events help us to insert hook points extending the functionality according to our business needs.

In our example, we’re especially interested in tracking what records a user creates and what fields he/she changes.

Checking the list of events triggered by a model, the most appropiate to insert this logic are ‘afterCreate’ and ‘afterUpdate’. These are executed after the creating and updating operations respectively.

Why behaviors?

The simpler way to add logic to these events is implement them as methods in the model:

<?php

class Products extends Phalcon\Mvc\Model
{

    public function afterCreate()
    {

    }

    public function afterUpdate()
    {

    }

}

However, if we want to reuse that logic across several models, we could use other better alternatives. We can create a base class that implements these methods then use it as base class in the required models:

<?php

class BlameableModel extends Phalcon\Mvc\Model
{

    public function afterCreate()
    {

    }

    public function afterUpdate()
    {

    }

}

Then in the model:

class Products extends BlameableModel
{

}

This approach is very simple too, but it has some disadvantages, a class only can inherit one class at the same time, so if we want to implement more behaviors this strategy could limit us.

Recently in PHP 5.4, Traits were introduced allowing us to reuse method across classes without explicitly set a class inheritance. In our case a trait that fits our purposes looks like this:

trait Blameable
{

    public function afterCreate()
    {

    }

    public function afterUpdate()
    {

    }

}

Then in then model:

class Products extends Phalcon\Mvc\Model
{
    use Blameable;
}

This way also has limitations; you can’t add more than one trait that has implemented the same methods because it produces collisions. Although such collisions can be resolved, we must choose which implementation to use.

Phalcon provides behavior management, allowing us to add several behaviors to the same model that implements the same events. A behavior can be easily added to a model in the following way:

class Products extends Phalcon\Mvc\Model
{
    public function initialize()
    {
        $this->addBehavior(new MyBehavior());
    }
}

A behavior can respond to events produced by a model, our behavior “Blameable” initially looks like:

<?php

use Phalcon\Mvc\ModelInterface,
    Phalcon\Mvc\Model\Behavior,
    Phalcon\Mvc\Model\BehaviorInterface;

class Blameable extends Behavior implements BehaviorInterface
{

    /**
     * Receives notifications from the Models Manager
     *
     * @param string $eventType
     * @param Phalcon\Mvc\ModelInterface $model
     */
    public function notify($eventType, $model)
    {
        // ...
    }
}

It simply implements a method called “notify”, this method receives two parameters: the event name triggered by the models manager and the model that produced the event. As mentioned before, we’re only interested in ‘afterCreate’ and ‘afterUpdate’:

/**
 * Receives notifications from the Models Manager
 *
 * @param string $eventType
 * @param Phalcon\Mvc\ModelInterface $model
 */
public function notify($eventType, $model)
{
    if ($eventType == 'afterCreate') {
        //...
    }
    if ($eventType == 'afterUpdate') {
        //...
    }
}

Now, returning to our idea, we’re going to store the information about creating/updating operations in the following additional tables:

CREATE TABLE audit (
    id integer primary key auto_increment,
    user_name varchar(32) not null,
    model_name varchar(32) not null,
    ipaddress char(15) not null,
    type char(1) not null, /* C=Create/U=Update */
    created_at datetime not null
);

CREATE TABLE audit_detail (
    id integer primary key auto_increment,
    audit_id integer not null,
    field_name varchar(32) not null,
    old_value varchar(32),
    new_value varchar(32) not null
)

The respective models are:

class Audit extends \Phalcon\Mvc\Model
{

    public function initialize()
    {
        $this->hasMany('id', 'AuditDetail', 'audit_id', array(
            'alias' => 'details'
        ));
    }

}

class AuditDetail extends \Phalcon\Mvc\Model
{

    public function initialize()
    {
        $this->belongsTo('audit_id', 'Audit', 'id');
    }

}

“Audit” stores general information about the operation, while “AuditDetail” stores every new value or every changed value. You can easily adapt this structure to other approaches.

Let’s focus on the event “after updating”, since it represents an interesting challenge. We’re interested in tracking only those fields that changed with respect to original data in the record.

To achieve this, we must set up our model to store a snapshot of the original record so that we can compare it with the new and know their changes.

<?php

class Products extends Phalcon\Mvc\Model
{

    public function initialize()
    {
        $this->keepSnapshots(true);
    }

}

Now we have everything we need to complete the behavior.

public function notify($eventType, $model)
{
    //Fires 'logAfterUpdate' if the event is 'afterUpdate'
    if ($eventType == 'afterUpdate') {
        return $this->auditAfterUpdate($model);
    }
}

The method ‘auditAfterUpdate’ receives the model, creates a new “Audit” together with its detail:

public function auditAfterUpdate(ModelInterface $model)
{

    //Get the name of the fields that have changed
    $changedFields = $model->getChangedFields();
    if (count($changedFields)) {

        //Create a new audit
        $audit = new Audit();

        //Get the session service
        $session = $model->getDI()->getSession();

        //Get the request service
        $request = $model->getDI()->getRequest();

        //Get the username from session
        $audit->user_name = $session->get('userName');

        //The model who performed the action
        $audit->model_name = get_class($model);

        //The client IP address
        $audit->ipaddress = $request->getClientAddress();

        //Action is an update
        $audit->type = $type;

        //Current datetime
        $audit->created_at = date('Y-m-d H:i:s');

        //Get the original data before modification
        $originalData = $model->getSnapshotData();

        $details = array();
        foreach ($changedFields as $field) {

            $auditDetail = new AuditDetail();

            $auditDetail->field_name = $field;
            $auditDetail->old_value = $originalData[$field];
            $auditDetail->new_value = $model->$field;

            $details[] = $auditDetail;
        }

        $audit->details = $details;

        return $audit->save();
    }

    return null;
}

Check out the complete source of the behavior on the Incubator.

Conclusion

This example will help you understand how the behaviors in the ORM, as information about the fields that have been changed with respect to the original data and code reuse accessing global services application.