Phalcon framework

The fastest PHP framework yet

Marcin Wawrzyniak

Roadmap

1/25

What's that ?



one framework = one .dll (.so) file

2/25

What features does it have?


3/25

CakePHP has it all. Zend has it all. Why should I care?

Speed is the most important feature. If your application is slow, people won’t use it.

4/25

Frameworks performance compared

5/25

FASTER

Benchmark of a few HelloWorld framework applications which tells us the minimum framework overhead.



Chart build on http://charts.hohli.com

6/25





7/25

How to use it ?

8/25

Example model

Most often maps to a database table

class Article extends Phalcon_Model_Base {
    function initialize(){
        //table name, optional
        $this->setSource("articles"); 
        //many-to-many relation, through ArticleTags
        $this->hasMany("id", "ArticleTags", "article_id"); 
    }
    function validation(){
        $this->validate("InclusionIn", array(
            "field" => "available_to",
            "domain" => array("anyone", "registered", "premium")
        ));
        $this->validate("Uniqueness", array(
            "field" => "title",
            "message" => "The title must be unique"
        ));
        return !$this->validationHasFailed();
    }
}

9/25

Example model, more meat

class Tag extends Phalcon_Model_Base {
    function initialize(){
        //again many-to-many relation, through ArticleTags
        $this->hasMany("id", "ArticleTags", "tag_id");
    }
}

Now let's put it all together.

class ArticleTags extends Phalcon_Model_Base {
    function initialize(){
        $this->belongsTo("article_id", "Article", "id");
        $this->belongsTo("tag_id", "Tag", "id");
    }
}

10/25

Using the model (basic)

//for_update sets exclusive lock on record 1694
$article = Article::findFirst(array('id=1694', 'for_update' => true));
$article->title = "True story about one cynical bastard";

$premiumArticles = Article::find(array(
    'available_to="premium', 
    'order' => 'title', 
    'limit' => 10
));
foreach($premiumArticles as $article){
    echo $article->title . "\n";
}
foreach($article->getArticleTags() as $articleTag){ //'get' . $connectingModel
    echo $articleTag->getTag()->name, "\n";
}

There's also a metadata which is used to retrieve model attribute names or types.

$article = new Article();
$metaData = $article->getManager()->getMetaData();
$attributes = $metaData->getAttributes($article);

11/25

Using the model (fun stuff)

try{
    $transaction = Phalcon_Transaction_Manager::get();
	
    $article = new Article;
    $article->setTransaction($transaction);
    $article->title = 'Seen new Big Bang Theory?';
	
    if (false == $article->save()){
      $transaction->rollback("Article is not saveable!");
    }
    
    $tags = array('funny','outstanding','interesting','new');
    foreach($tags as $name){
        $tag = new Tag;
        $tag->setTransaction($transaction);
        $tag->name = $name;
        if (false == $tag->save()){
            $transaction->rollback('Cannot save tag: ' . $name);
        }
    }

    $transaction->commit();
  
}catch(Phalcon_Transaction_Failed $e){ /* ... */ }

12/25

Tag helper

Phalcon_Tag allows you to deal with HTML markup complexities.

In the controller

use Phalcon_Tag as Tag;
//...
public function addAction(){
	//sets the default value of <input name="born" />
	Tag::setDefault('born', date('d-m-y', strtotime('20 years ago'));
}

In the view

echo Tag::form(array('users/register', 'method' => 'post'));
echo Tag::textField(array('born', 'size'=>30));
echo Tag::select(array(
    'category_id',
    Categories::find('disabled=0'),
    'using' => array('id', 'name')
));
echo Tag::image(array('img/logo.png'));
echo Tag::linkTo('users/register', 'Join us!');
echo Tag::stylesheetLink('css/style.css');

13/25

Pagination

In the controller

$news = News::find();
$paginator = Phalcon_Paginator::factory("Model", array(
  "data" => $news,
  "limit"=> 10,
  "page" => $numberPage
));

In the view

<?php
foreach($page->items as $item):
    //...
endforeach;
?>

<?= Phalcon_Tag::linkTo('news/index?page=' . $page->before, 'Previous') ?>
<?= Phalcon_Tag::linkTo('news/index?page=' . $page->next, 'Next') ?>

<?= 'You are in page ' . $page->current . ' of ' . $page->total_pages ?>

14/25

Translating your app with i18n/l10n

Phalcon uses intl extension (yes I can spell internationalization).

$locale = 'en_US';
$formatter = new NumberFormatter($locale, NumberFormatter::DECIMAL);

echo $formatter->format(4560.50);


$mf = new MessageFormatter($locale, 
	"{0,choice,0#No new messages|
	  1#One new message|
	  1<You've got {0,number} new messages}."
);
echo $mf->format(7); //You've got 7 new messages

15/25

Migrations

smart migration based on serialized database schema (phalcon-developer-tools)

phalcon gen-migration //generate new migration
phalcon gen-migration --version 101 //switch to 101
use Phalcon_Db_Column as Column;
class CompaniesMigration_100 extends Phalcon_Model_Migration {
    public function up(){
        $this->morphTable('companies', array(
        'columns' => array(
            new Column('id', array(
            'type' => Column::TYPE_INTEGER,
            'size' => 10,
            'unsigned' => true,
            'primary' => true,
            'notNull' => true,
            'autoIncrement' => true,
            'first' => true
        )),
        //...
    }
}

16/25

Fixtures

Fixtures are just test data, which can be inserted to DB after migration.

class CompaniesMigration_100 extends Phalcon_Model_Migration {
  public function up(){
	//...
	self::$_connection->insert(
	   "companies",
	   array("Microsoft", "Bill Gates, Paul Allen"),
	   array("Apple", "Steve Jobs, Steve Wozniak"),
	   array("name", "founders")
	);
  }

}

17/25

But I'm lazy!!

Since Phalcon 0.3.2 there's a new nifty feature called "developer tools".

phalcon create-project candy-shop
phalcon create-controller --name User
phalcon create-model --table-name users
phalcon create-model --table-name users --gen-getters-setters
phalcon scaffold --table-name users
phalcon create-all-models
phalcon gen-migration

create-model allows you to modify database table between code generations (next code generation will not remove your code, just modify needed parts).

CREATE TABLE users(
  id int,
  name varchar(255)
);
phalcon create-model --table-name users

18/25

But I'm really lazy!!

When we alter the table..

ALTER TABLE users ADD email varchar(255);

and rerun create-model..

phalcon create-model --table-name users --force 

Phalcon will modify previously created class without touching code you've modified.

19/25

Drawbacks

20/25

But you should really try it out, because:

21/25

And it get's better...

22/25

That's it.

Thanks for your attention!

Questions?


23/25

Useful links

24/25

Bonus: Q&A after speech

Q: What do you think about Phalcon future?
A: I believe that as far as Phalcon is a great project itself, it's mission is rather to spread a brand new technical tought than become a new ZF.

Q: Does Phalcon use PDO?
A: "From PDO to native drivers, Phalcon encapsulate the specific details of each database engine in dialects. Those provide common functions and SQL generator to adapters."
ATM of writing, there's only MySQL dialect availble, which doesn't mean you cannot use PDO or mongo while developing in Phalcon.

Q: Do you know ANY project that switched to Phalcon in order to improve performance?
A: Why don't you read the drawbacks slide?

Q: Can you use SQLite with Phalcon?
A: Yes you can, using PDO_SQLITE, as Phalcon does not provide yet Phalcon_Db_Dialect_Sqlite class.

Q: Does Phalcon use under the hood PDO ex. in Phalcon_Db_Dialect_Mysql?
A: As since PHP 5.4 there's mysqlnd under the hood, Phalcon uses mysql extension.

Q: What versions of PHP does Phalcon support?
A: >=5.3

25/25