symfony2 meets propel 1.5
TRANSCRIPT
![Page 1: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/1.jpg)
Symfony 2 meets Propel 1.5François Zaninotto
![Page 2: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/2.jpg)
François ZaninottoHead of the Web Development Team at
eTF1, editor the web properties of the leading TV network in France.
Former symfony 1 contributorAuthor of “The Definitive Guide to
Symfony” (APress)Lead Developer of Propel since October,
2009Interests: Web development, Usability,
Agility, ROINot a developerTwitter: @francoisz, Github: fzaninotto
![Page 3: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/3.jpg)
Propel 1.5
![Page 4: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/4.jpg)
No surpriseBackwards compatible with Propel 1.3 and
1.4Faster than Propel 1.4, which was faster
than Propel 1.3, which was...Very IDE friendlyBetter documentedMore robust (3 times as many unit tests as
Propel 1.3)Fully integrated into symfony 1.3/1.4
(sfPropel15Plugin)
![Page 5: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/5.jpg)
Surprise!Major new features
Model QueriesCollectionsMany-to-many relationships
Major new behaviorsNested SetsConcrete Table Inheritance
Better Oracle Support
![Page 6: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/6.jpg)
Surprise!Major new features
Model QueriesCollectionsMany-to-many relationships
Major new behaviorsNested SetsConcrete Table Inheritance
Better Oracle Support
Killer Feature
Killer Feature
![Page 7: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/7.jpg)
Model QueriesModel Queries are to the SQL query what
ActiveRecord is to the table rowShift from the relational Paradigm to the
Object paradigm in QueriesInspirations: SQL Alchemy, Doctrine,
DbFinder, ArelCode generation makes it fast and IDE
friendlyEasy to learn and useMUCH cleaner custom model codeBye bye, Criteria!
![Page 8: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/8.jpg)
Model Queries$books = BookQuery::create() ->filterByPublishedAt(array( ‘max’ => time() )) ->filterByPublisher($publisher) ->useAuthorQuery() ->stillAlive() ->endUse() ->orderByTitle() ->find();
![Page 9: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/9.jpg)
Concrete Table Inheritancecontentidtitle
articlebody
videourl
structure data
![Page 10: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/10.jpg)
Concrete Table Inheritance: An Example
$article = new Article();$article->setTitle(‘France loses World Cup’);$article->setBody(‘Lorem Ipsum’);$article->save();
$video = new Video();$video->setTitle(‘World Cup Goals’);$video->setUrl(‘http://www.youtube.com/xxx’);$video->save();
![Page 11: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/11.jpg)
> SELECT * FROM article;+----+------------------------+-------------+| id | title | body |+----+------------------------+-------------+| 1 | France loses World Cup | Lorem Ipsum |+----+------------------------+-------------+
> SELECT * FROM video;+----+-----------------+----------------------------+| id | title | url |+----+-----------------+----------------------------+| 2 | World Cup goals | http://www.youtube.com/xxx |+----+-----------------+----------------------------+
> SELECT * FROM content;+----+------------------------+| id | title |+----+------------------------+| 1 | France loses World Cup || 2 | World Cup goals |+----+------------------------+
![Page 12: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/12.jpg)
Design your model in a true object-oriented way
Let Propel do the mapping with the relational world
Denormalize with ease for optimal performance
Let PHP manipulate inheritance, not data replication.
… Let PHP manipulate objects, not records.
… Let PHP manipulate collections, not arrays.
… Let PHP manipulate relations, not foreign keys.
![Page 13: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/13.jpg)
Continuous improvements through minor versions
1.5.1PropelObjectCollection::toKeyValue()One-to-many joined hydration (no LIMIT
support)CLI enhancements
1.5.2Namespaces ! ModelQuery::findOneOrCreate()aggregate_column behaviorSQL Comments
![Page 14: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/14.jpg)
Continuous improvements through minor versions
1.5.1PropelObjectCollection::toKeyValue()One-to-many joined hydration (no LIMIT
support)CLI enhancements
1.5.2Namespaces ! ModelQuery::findOneOrCreate()aggregate_column behaviorSQL Comments
Killer Feature
Must Have
![Page 15: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/15.jpg)
Namespaces// in schema.xml<table name="book" namespace="Bookstore"> ...</table>
// in application codeuse Bookstore\BookQuery;
$book = BookQuery::create(); ->findOneByTitle(‘War And Peace’);echo get_class($book); // Bookstore\Book
$author = $book->getAuthor();echo get_class($author); // Bookstore\People\Author
![Page 16: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/16.jpg)
Aggregate Table Behaviorauthoridname
bookidtitleauthor_id
*
<table name="author"> <behavior name="aggregate_column"> <parameter name="name" value="nb_books" /> <parameter name="foreign_table" value="book" /> <parameter name="expression" value="COUNT(id)" /> </behavior> ...</table>
![Page 17: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/17.jpg)
Aggregate Table Behaviorauthoridnamenb_books
bookidtitleauthor_id
*
<table name="author"> <behavior name="aggregate_column"> <parameter name="name" value="nb_books" /> <parameter name="foreign_table" value="book" /> <parameter name="expression" value="COUNT(id)" /> </behavior> ...</table>
![Page 18: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/18.jpg)
Aggregate Table Behavior$author = new Author();$author->setName(‘Leo Tolstoi');$author->save();echo $author->getNbBooks(); // 0$book = new Book();$book->setTitle(‘War and Peace’);$book->setAuthor($author);$book->save();echo $author->getNbBooks(); // 1$book->delete();echo $author->getNbBooks(); // 0
![Page 19: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/19.jpg)
No, really, Propel is definitely NOT DEAD
![Page 20: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/20.jpg)
Propel 1.5 and Symfony
![Page 21: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/21.jpg)
Propel Integration with symfony 1: sfPropel15Plugin
Use sf configuration system (databases.yml, propel.ini)
Use sf autoloading rather than Propel’s Use sf task system (and hides Phing, thank
God) Adapt Propel to SF applications directory
structureYAML format for the schema (and plugin
override)Web Debug Toolbar panel Form integration (Widgets, Validators, Model
forms)Admin Generator Theme Routing integration (Model routes, Model route
collections) Symfony Behaviors
![Page 22: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/22.jpg)
Propel Integration with Symfony2: PropelBundle
Use sf configuration system (config.yml, Dependency Injection)
Use sf autoloading rather than Propel’s (thanks Namespaces)
Use sf command system (and hides Phing, thank God)
Adapt Propel to SF applications directory structure
YAML format for the schema (and bundle override)
Web Debug Toolbar Panel Form integration (Widgets, Validators, Model
forms) Admin Generator Theme Routing integration (Model routes, Model
route collections) Symfony Behaviors
![Page 23: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/23.jpg)
Many of the symfony add-ons to Propel are now part of Propel 1.5Model hooks, query hooksBehavior system (at buildtime, for better
performance and power)auto_add_pk behaviortimestampable behaviorisPrimaryString column attribute for automated __toString()
No need for custom symfony code for these
![Page 24: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/24.jpg)
Why you may want to use Propel rather than Doctrine 2
No need to upgrade your Model codeIt’s fast (without any cache system - that’s code
generation)It’s an ActiveRecord implementationIt has behaviorsIt’s IDE friendlyThe model code is easy to understand and
debugIt has unique features (ModelQueries, concrete
table inheritance, aggregate column behavior, etc.)
It’s robust (3000+ unit tests) and already used by many developers
It’s not alpha, it’s not beta, it’s already stable
![Page 25: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/25.jpg)
Installation
![Page 26: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/26.jpg)
The PropelBundle is bundled with the Symfony2 Framework
Register the bundle in the kernel// in hello/HelloKernel.phpclass HelloKernel extends Kernel{ public function registerBundles() { $bundles = array( ... new Symfony\Framework\PropelBundle\Bundle(), );
return $bundles; }}
![Page 27: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/27.jpg)
Add Propel and Phing libraries in src/vendor/
> cd src/vendor> svn co http://svn.propelorm.org/branches/1.5/ propel> svn co http://svn.phing.info/tags/2.3.3 phing
Add Propel and Phing paths to the project configuration
# in hello/config/config.ymlpropel.config: path: %kernel.root_dir%/../src/vendor/propel phing_path: %kernel.root_dir%/../src/vendor/phing
![Page 28: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/28.jpg)
Test the installation by calling the project console> hello/consoleSymfony version 2.0.0-DEV - hello
Usage: [options] command [arguments]
propel :build Hub for Propel build commands (model, sql) :build-model Build the Propel Object Model classes based on XML schemas :build-sql Build the SQL generation code for all tables based on Propel XML schemas
![Page 29: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/29.jpg)
Usage
![Page 30: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/30.jpg)
Create an XML schema using namespaces// in src/Application/HelloBundle/Resources/config/schema.xml<?xml version="1.0" encoding="UTF-8"?><database name="default" namespace="Application\HelloBundle\Model"
defaultIdMethod="native"> <table name="book"> <column name="id" type="integer" required="true" primaryKey="true"
autoIncrement="true" /> <column name="title" type="varchar" primaryString="1" size="100" /> <column name="ISBN" type="varchar" size="20" /> <column name="author_id" type="integer" /> <foreign-key foreignTable="author"> <reference local="author_id" foreign="id" /> </foreign-key> </table> <table name="author"> <column name="id" type="integer" required="true" primaryKey="true"
autoIncrement="true" /> <column name="first_name" type="varchar" size="100" /> <column name="last_name" type="varchar" size="100" /> </table></database>
![Page 31: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/31.jpg)
Create an XML schemas using namespaces// in src/Application/HelloBundle/Resources/config/schema.xml<?xml version="1.0" encoding="UTF-8"?><database name="default" namespace="Application\HelloBundle\Model"
defaultIdMethod="native"> <table name="book"> <column name="id" type="integer" required="true" primaryKey="true"
autoIncrement="true" /> <column name="title" type="varchar" primaryString="1" size="100" /> <column name="ISBN" type="varchar" size="20" /> <column name="author_id" type="integer" /> <foreign-key foreignTable="author"> <reference local="author_id" foreign="id" /> </foreign-key> </table> <table name="author"> <column name="id" type="integer" required="true" primaryKey="true"
autoIncrement="true" /> <column name="first_name" type="varchar" size="100" /> <column name="last_name" type="varchar" size="100" /> </table></database>
![Page 32: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/32.jpg)
Build the model and SQL code> cd sandbox> hello/console propel:build
src/Application/HelloBundle/ Model/ map/ om/ Author.php AuthorPeer.php AuthorQuery.php Book.php BookPeer.php BookQuery.php
hello/propel/sql/ HelloBundle-schema.sql
![Page 33: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/33.jpg)
// in sandbox/src/application/HelloBundle/Model/Book.php
namespace Application\HelloBundle\Model;use Application\HelloBundle\Model\Om\BaseBook;
/** * Skeleton subclass for representing a row from the * 'book' table. * * You should add additional methods to this class to meet * the application requirements. This class will only be * generated as long as it does not already exist in the * output directory. */class Book extends BaseBook {
} // Book
![Page 34: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/34.jpg)
Setup your connection in the project configuration
# in sandbox/hello/config/config.ymlpropel.dbal: driver: mysql user: root password: null dsn: mysql:host=localhost;dbname=test options: {}
![Page 35: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/35.jpg)
Use models in your actions as with Propel 1.5 alone
Symfony handles the autoloading// in sandbox/src/Application/HelloBundle/Controller/HelloController.phpnamespace Application\HelloBundle\Controller;
use Symfony\Framework\WebBundle\Controller;use Application\HelloBundle\Model\AuthorQuery;
class HelloController extends Controller{ public function indexAction($name) { $author = AuthorQuery::create() ->findOneByName($name);
return $this->render('HelloBundle:Hello:index', array('author' => $author)); }}
![Page 36: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/36.jpg)
That’s about itAll the Propel features are ready to use…
in the Propel way
![Page 37: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/37.jpg)
The Future of Propel 1.5 and Symfony2
![Page 38: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/38.jpg)
Ask Fabien
![Page 39: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/39.jpg)
A lot left to doYAML format for the schema (and bundle
override)Web Debug Toolbar PanelForm integration (Widgets, Validators,
Model forms)Admin Generator ThemeDocumentationUnit tests
![Page 40: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/40.jpg)
And even moreEmbedded Relation FormsAdmin generator on steroids
Easy Custom FilterCross-module linksPlain text fields
Advanced Object RoutingCollection routesNested routes
A thousand more ideas worth implementing
cf. sfPropel15Plugin
cf. DbFinderPlugin
![Page 41: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/41.jpg)
Not much time to do so
I’m already developing PropelI’m already developing sfPropel15PluginI also have a full-time job…and a family
Any help is welcome!
![Page 42: Symfony2 meets propel 1.5](https://reader038.vdocument.in/reader038/viewer/2022102317/554f78e8b4c905d25b8b4666/html5/thumbnails/42.jpg)
Questions?
Online Resourceshttp://github.com/fzaninotto/symfonyhttp://www.propelorm.org/http://www.symfony-project.org/plugins/
sfPropel15PluginNews about all that
http://propel.posterous.com/http://twitter.com/francoisz