symfony: An Open-Source Framework for Professionals (PHP Day 2008) - Presentation Transcript
symfony
An Open-Source Framework
for Professionals
Fabien Potencier
www.sensiolabs.com
Before we begin
How many have already
used symfony for a project,
even a very small personal project?
www.sensiolabs.com
Before we begin
Do you want to do
the exercices on your laptop?
www.sensiolabs.com
Sensio
• Sensio Sensio
Web Agency
– Web Agency
Internet
Webmarketing
– Founded in 1998 Technologies
– 45 people dedicated to Web dev.
• Open-Source Specialists symfony framework
creator
• Big corporate customers
www.sensiolabs.com
symfony
• PHP Web framework
• Based on
– 10 years of Sensio experience
– Existing Open-Source projects
• Built for :
– Professional websites
– Complex needs
– Demanding environments
www.sensiolabs.com
Framework
www.sensiolabs.com
Whatever the application, a
framework is build to ease
development by providing tools
for recurrent and boring tasks.
www.sensiolabs.com
Write less code
less code
less complexity
less bugs
more productivity
more time
More time for edge cases, business rules, …
www.sensiolabs.com
Each line of code has an initial cost
Costinitial = Costdeveloppement + Costtests
… and there is a cost to maintain the line
Costmaintenance >> Costinitial
Costmaintenance = Costunderstanding + Costchange + Costtests + Costdeployment
Kent Beck (based on Yourdon and Constantine)
www.sensiolabs.com
symfony
www.sensiolabs.com
An Open-Source Framework
www.sensiolabs.com
MIT Licence
« It is a permissive license, meaning that it permits
reuse within proprietary software on the condition
that the license is distributed with that software. »
www.sensiolabs.com
An Open-Source Documentation
www.sensiolabs.com
• Open-Source documentation
– The book (450 pages - GFDL)
– Askeet Tutorial (250 pages)
• Translation in 12 langages
– (Chinese) – Polski
– Deutsch – Português
– Español – Russian
– Français – Ukrainian
– Italiano – Čeština
– (Japanese)
– Nederlands
www.sensiolabs.com
www.sensiolabs.com
A great Community
www.sensiolabs.com
Mailing-list support / forums / IRC
240 available plugins
300k unique visitors per month on the official
website www.symfony-project.org
www.sensiolabs.com
« Entreprise » Version
www.sensiolabs.com
Version 1.0 released early 2007
Maintained for 3 ans (early 2010)
~1 release a month (1.0.16 now)
Bugs and security fixes, compatibility with upcoming
PHP versions
No new features
Upgrading is simple and safe
www.sensiolabs.com
Let’s start a Project
www.sensiolabs.com
The Project
• A simple blog system
– Posts
– Categories
– Authors
– Comments
• Requirements
– Maintainable
– Customizable
– Secure
• Use symfony 1.1
www.sensiolabs.com
List of recent posts
Excerpt
Categories
Post information
www.sensiolabs.com
Sidebar customization
List of comments
www.sensiolabs.com Add a comment
YUI stylesheets
homepage
Famfamfam icons
post
http://www.symfony-project.org/get/design.tgz
www.sensiolabs.com
Project Initialization
www.sensiolabs.com
Bootstrap a symfony Project
1. Install symfony
2. Initialize a new project
3. Configure the Web Server
4. Start coding
www.sensiolabs.com
Installing symfony
Sandbox: Ready-to-run symfony application
PEAR: Install symfony globally on your machine
Subversion: Be free to have several versions around
www.sensiolabs.com
symfony CLI
$ symfony
www.sensiolabs.com
Create a new Project
$ mkdir blog
$ cd blog
$ symfony generate:project blog
www.sensiolabs.com
Create a new Application
./symfony help generate:app
www.sensiolabs.com
Create a new secure Application
./symfony generate:app frontend
--escaping-strategy=on
--csrf-secret=A$ecret
www.sensiolabs.com
Which symfony Version?
./symfony -V
config/ProjectConfiguration.class.php
www.sensiolabs.com
Configure the Web Server
<VirtualHost *:80>
ServerName myapp.example.com
DocumentRoot "/path/to/blog/web"
DirectoryIndex index.php
<Directory "/path/to/blog/web">
AllowOverride All
Allow from All Web root directory is web/
</Directory>
</VirtualHost>
www.sensiolabs.com
symfony Assets
Used by the default pages and the Web Debug Toolbar
Configure the Web Server to serve symfony assets
<VirtualHost *:80>
…
Alias /sf /$sf_symfony_data_dir/web/sf
<Directory "/$sf_symfony_data_dir/web/sf">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
Or, create a symlink
$ cd web/
$ ln -sf ../lib/vendor/symfony/data/web/sf sf
www.sensiolabs.com
Environments
www.sensiolabs.com
developers customers end users
development staging production
environment environment environment
www.sensiolabs.com
cache cache cache
debug debug debug
logs logs logs
stats stats stats
development staging production
environment environment environment
www.sensiolabs.com
Try a 404
dev environment
prod environment
www.sensiolabs.com
Front Controllers
dev environment
environment
prod environment
environment
www.sensiolabs.com
Environment Configuration
apps/frontend/config/settings.yml
environment
Web debug toolbar
www.sensiolabs.com
Web Debug Toolbar
Web debug toolbar
www.sensiolabs.com
Create a Module for Posts
Create a new ‘post’ module in the ‘frontend’
application
$ php symfony generate:module frontend post
www.sensiolabs.com
Action and Template Naming
/frontend_dev.php/blog/index
module action
// in apps/frontend/modules/blog/actions/actions.class.php
<?php
class blogActions extends sfActions
{
public function executeIndex()
{
// do things
}
}
// in apps/frontend/modules/blog/templates/indexSuccess.php
<!–- do things -->
www.sensiolabs.com
Create the Blog Homepage
apps/frontend/modules/post/templates/indexSuccess.php
• Copy homepage.html into indexSuccess.php
• Copy the images/ and css/ under web/
• Add the base.css CSS in view.yml
• Fix images and css paths
/frontend_dev.php/post/index
www.sensiolabs.com
Create an Action to show a Post
apps/frontend/modules/post/actions/actions.class.php
• Create an empy executeShow() action
• Copy post.html into showSuccess.php
• Fix images and css paths
/frontend_dev.php/post/show
www.sensiolabs.com
Extract common Code
Post page specific content
Homepage specific content
www.sensiolabs.com
The Layout
A layout wraps the template content
header.php
page content
include
decoration
page content
include
footer.php
layout.php
www.sensiolabs.com
The Layout
Move the common code from homepage and post to
the layout
apps/frontend/templates/layout.php
www.sensiolabs.com
Customize the Sidebar and the Title
The title depends on the page
The sidebar depends on the page
www.sensiolabs.com
Layout with Several "holes"
A slot content depends on the template context
Slot1
Main
content
Slot 2
Main + =
content
Slot 1
Slot 2
Layout Template Rendered
with slots Page
www.sensiolabs.com
Create Slots for Title and Sidebar
apps/frontend/templates/layout.php
www.sensiolabs.com
Fill the Slots
apps/frontend/modules/blog/templates/showSuccess.php
www.sensiolabs.com
Passing Data from Action to Template
apps/frontend/modules/blog/actions/actions.class.php
apps/frontend/modules/blog/templates/indexSuccess.php
www.sensiolabs.com
Make the Counter dynamic
www.sensiolabs.com
Database Schema
A post has an author
A post can be in a category
A post can have comments
www.sensiolabs.com
Propel : The symfony ORM
ORM = Object-Relational Mapping
Mapping a relational database to an object-oriented
model
Database Abstraction
Relational Object-Oriented
table class
row, record object
field, column proterty
www.sensiolabs.com
Schema Conventions
post:
id: # primary key, autoincrement integer
author_id: # foreign key to Author
created_at: # timestamp, set to current time on creation
updated_at: # timestamp, set to current time on update
# column types
published_at: timestamp
title: varchar(255)
content: longvarchar
is_spam: boolean
# complex column definitions
last_name: { type: varchar(100), index: true, required: true }
category_id: { type: integer, foreignTable: category,
foreignReference: id, required: false, onDelete: setnull }
www.sensiolabs.com
Build the Model Classes
./symfony propel:build-model
www.sensiolabs.com
From Schema to Object Model
$ ./symfony propel:build-model
propel: lib/
post: model/
id: ~ om/
name: varchar(255) BasePost.php
BasePostPeer.php
Post.php
PostPeer.php
1 table > 4 classes?
www.sensiolabs.com
Base and Custom Classes
lib/ Base classes
model/
om/ Under model/om/, prefixed by Base
BasePost.php
BasePostPeer.php
Generated by Propel
Post.php Overwritten each time the schema
PostPeer.php
changes and the model is generated
Never edit these files!
lib/ Custom classes
model/
om/ Under model/, no prefix
BasePost.php
BasePostPeer.php
Inherit from Base classes
Post.php Never overwritten
PostPeer.php
Put custom methods here
www.sensiolabs.com
Override base methods here
Peer and Object Classes
lib/ Peer classes
model/
om/ Suffixed by Peer
BasePost.php Useful to retrieve a collection of objects
BasePostPeer.php
Post.php Methods return objects
PostPeer.php
Only static methods (::, self)
lib/ Object classes
model/
No suffix
om/
BasePost.php
Useful to create / inspect / update
BasePostPeer.php records
Post.php Methods return column values
PostPeer.php Only object methods (->, $this)
www.sensiolabs.com
Build the SQL queries
./symfony propel:build-sql
./symfony propel:insert-sql
www.sensiolabs.com
Shortcut for all the previous Tasks
./symfony propel:build-all
www.sensiolabs.com
Initial Data
data/fixtures/01-data.yml
Define PKs with names
Use names instead of Pks
Dynamic values
www.sensiolabs.com
Load Data
$ ./symfony propel:data-load frontend
www.sensiolabs.com
Summary of Code Generation
2 Object model
propel:build-model Base, Custom,
Peer and object classes
1
schema.yml
3 propel:build-sql
propel:insert-sql
Relational database
Tables, columns, keys, indexes
www.sensiolabs.com
If the Database preexists the Project
3 Object model
propel:build-model Base, Custom,
Peer and object classes
2
schema.yml
1
propel:build-schema
Relational database
Tables, columns, keys, indexes
www.sensiolabs.com
Generated Methods of Object Classes
Getter for columns CamelCase version
$title = $post->getTitle();
$content = $post->getContent(); of the column name
$createdAt = $post->getCreatedAt();
Some getters have special options
$date = $post->getCreatedAt($dateFormat);
Getter by name
$title = $post->getByName('title');
www.sensiolabs.com
Generated Methods of Object Classes
Manipulate primary keys
$commentId = $comment->getId();
// for composite keys, prefer
$commentId = $comment->getPrimaryKey();
Manipulate foreign keys
$postId = $comment->getPostId();
// in practice, these methods are not used much
// use getter for foreign objects instead
$post = $comment->getPost(); // Post object
// as the result is an object, you can chain method calls
$content = $comment->getPost()->getContent();
One-to-Many smart getters
$comments = $post->getCommments(); // Array of Comments
$nb = $post->countCommments(); // Integer
www.sensiolabs.com
Get the Posts from the Database
www.sensiolabs.com
What the Model Layer does
Action Model Database
PostPeer::doSelect(new Criteria())
Criteria to SQL translation
SELECT * FROM post
Query execution
resultset
Object hydrating
Array of Post objects
www.sensiolabs.com
What the Model Layer does
Template Model Database
$post->getTitle()
Looking up internal attribute
String
www.sensiolabs.com
Make the Post show Page dynamic
/frontend_dev.php/post/show?id=1
www.sensiolabs.com
Make the Post show Page dynamic
Display a 404 error if the post does not exist
www.sensiolabs.com
Change the Date Format
getPublishedAt() first argument accepts the date()
format or the strftime() format
symfony format_date() helper is i18n aware
www.sensiolabs.com
Helper Groups
• Tag
• URLs
• Assets (images, JavaScript, CSS, …)
• Subtemplate inclusion (slot, partial, component)
• Links
• Form
• Javascript and Ajax
• Text, number, date manipulation
• I18N
• …
www.sensiolabs.com
Permalinks
• Many applications provide an alternative to
functional URLs
• Permalinks look like links to permanent content
while the resource they reference is dynamically
generated
• Primarily focused at search engines, permalink
often carry more readable data for end users
http://www.symfony-project.org/blog/2008/05/21/new-symfony-security-policy
www.sensiolabs.com
Links to the Post Page
apps/frontend/config/routing.yml
lib/model/Post.php
www.sensiolabs.com
Links to the Post Page
apps/frontend/modules/post/templates/indexSuccess.php
apps/frontend/modules/post/actions/actions.class.php
www.sensiolabs.com
Link to the Homepage
www.sensiolabs.com
Add the Comments
apps/frontend/modules/post/templates/showSuccess.php
www.sensiolabs.com
What the Model Layer does
Template Model Database
$post->getComments()
SELECT * FROM comment
WHERE comment.post_id= ?
Query execution
resultset
Array of Comment objects
Object hydrating
www.sensiolabs.com
Comment Form
$ ./symfony propel:build-forms
www.sensiolabs.com
Base and Custom Classes
lib/ Base classes
form/
Under form/base/, prefixed by Base
base/
BasePostForm.class.php Generated by symfony
PostForm.class.php
Overwritten when the schema
changes and the forms are
generated
Never edit these files!
lib/ Custom classes
form/
base/ Under form/, no prefix
BasePost.Form.class.php Inherit from Base classes
PostForm.class.php
Never overwritten
Put custom methods here
www.sensiolabs.com
Override base methods here
Create a Comment Form
apps/frontend/modules/post/actions/actions.class.php
apps/frontend/modules/post/templates/showSuccess.php
www.sensiolabs.com
Create a Comment Form
www.sensiolabs.com
Propel Forms
• Generated by propel:build-forms
• 1 table = 1 form
• Model introspection to determine
– The widget
– The validation rules
• Automatically converts a form to a Propel object
and save it to the database
• Extensible
www.sensiolabs.com
Bind The Form to the Post
www.sensiolabs.com
Customize the Form
lib/form/CommentForm.class.php
www.sensiolabs.com
Form Life Cycle
www.sensiolabs.com
Comments
www.sensiolabs.com
Security: XSS
www.sensiolabs.com
Security: CSRF
www.sensiolabs.com
Create the Category Page
lib/model/PostPeer.class.php
apps/frontend/modules/blog/actions/actions.class.php
www.sensiolabs.com
Create the Category Page
apps/frontend/config/routing.yml
apps/frontend/templates/layout.php
www.sensiolabs.com
Create a Partial for the List
apps/frontend/modules/blog/templates/_list.php
apps/frontend/modules/blog/templates/listByCategorySuccess.php
www.sensiolabs.com
Create a Component
apps/frontend/modules/post/actions/components.class.php
apps/frontend/modules/post/templates/_categories.php
apps/frontend/templates/layout.php
www.sensiolabs.com
Create a Web Service for Posts
apps/frontend/config/routing.yml
apps/frontend/modules/post/templates/indexSuccess.xml.php
www.sensiolabs.com
If we have time…
• Functional Tests
• Cache
• CRUD to manage posts
www.sensiolabs.com
0 comments
Post a comment