symfony: An Open-Source Framework for Professionals (PHP Day 2008)

Preview:

DESCRIPTION

 

Citation preview

www.sensiolabs.com

Fabien Potencier

symfony An Open-Source Framework

for Professionals

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

– Web Agency – Founded in 1998 – 45 people dedicated to Web dev.

• Open-Source Specialists

• Big corporate customers

Webmarketing Internet Technologies

Sensio Web Agency

symfony framework creator

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

Maintainability & Evolutivity

www.sensiolabs.com

Structure & Standardisation

www.sensiolabs.com

MVC

www.sensiolabs.com

Model

www.sensiolabs.com

View

www.sensiolabs.com

Controller

www.sensiolabs.com

Internet

Controleur

Vue

2

Modèle

BDD

3

4

5

6

1

www.sensiolabs.com

Develop Faster & Better

www.sensiolabs.com

Write less code

More time for edge cases, business rules, …

less code

less complexity

less bugs

more productivity

more time

www.sensiolabs.com

Each line of code has an initial cost

… and there is a cost to maintain the line

Kent Beck (based on Yourdon and Constantine)

Costinitial = Costdeveloppement + Costtests

Costmaintenance >> Costinitial

Costmaintenance = Costunderstanding + Costchange + Costtests + Costdeployment

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)

– Deutsch – Español – Français –  Italiano –  日本語 (Japanese)

–  Polski –  Português –  Russian –  Ukrainian –  Čeština –  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

Categories Post information

Excerpt

www.sensiolabs.com

Sidebar customization

Add a comment

List of comments

www.sensiolabs.com

Famfamfam icons

YUI stylesheets

homepage

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

Project, Application, Module, Action

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 </Directory>

</VirtualHost>

Web root directory is web/

www.sensiolabs.com

symfony Assets Used by the default pages and the Web Debug Toolbar

Configure the Web Server to serve symfony assets

Or, create a symlink

<VirtualHost *:80> … Alias /sf /$sf_symfony_data_dir/web/sf <Directory "/$sf_symfony_data_dir/web/sf"> AllowOverride All Allow from All </Directory> </VirtualHost>

$ cd web/

$ ln -sf ../lib/vendor/symfony/data/web/sf sf

www.sensiolabs.com

Environments

www.sensiolabs.com

developers customers end users

development environment

staging environment

production environment

www.sensiolabs.com

cache cache cache

debug debug debug

logs logs

stats stats stats

logs

development environment

staging environment

production environment

www.sensiolabs.com

Try a 404 dev environment

prod environment

www.sensiolabs.com

Front Controllers dev environment

prod environment

environment

environment

www.sensiolabs.com

Environment Configuration apps/frontend/config/settings.yml

Web debug toolbar

environment

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

Project, Application, Module, Action

www.sensiolabs.com

Action and Template Naming /frontend_dev.php/blog/index

// 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 -->

module action

www.sensiolabs.com

Browse

/frontend_dev.php/post/index

www.sensiolabs.com

Create the Blog Homepage

• 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

apps/frontend/modules/post/templates/indexSuccess.php

/frontend_dev.php/post/index

www.sensiolabs.com

Create an Action to show a Post apps/frontend/modules/post/actions/actions.class.php

/frontend_dev.php/post/show

• Create an empy executeShow() action • Copy post.html into showSuccess.php • Fix images and css paths

www.sensiolabs.com

Project, Application, Module, Action

www.sensiolabs.com

Extract common Code

Homepage specific content

Post page specific content

www.sensiolabs.com

The Layout

header.php

page content

footer.php

page content

layout.php

include

include

decoration

A layout wraps the template content

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"

Main content

Main content

+ =

Layout Template with slots

Rendered Page

Slot1

Slot

2

Slot 1

Slot 2

A slot content depends on the template context

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

table row, record field, column

class object proterty

Object-Oriented Relational

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

Database Schema config/schema.yml

www.sensiolabs.com

Build the Model Classes ./symfony propel:build-model

www.sensiolabs.com

From Schema to Object Model

$ ./symfony propel:build-model

lib/ model/ om/ BasePost.php BasePostPeer.php Post.php PostPeer.php

propel: post: id: ~ name: varchar(255)

1 table > 4 classes?

www.sensiolabs.com

Base and Custom Classes Base classes

Under model/om/, prefixed by Base Generated by Propel Overwritten each time the schema

changes and the model is generated Never edit these files!

lib/ model/ om/ BasePost.php BasePostPeer.php Post.php PostPeer.php

lib/ model/ om/ BasePost.php BasePostPeer.php Post.php PostPeer.php

Custom classes Under model/, no prefix Inherit from Base classes Never overwritten Put custom methods here Override base methods here

www.sensiolabs.com

Peer and Object Classes Peer classes

Suffixed by Peer Useful to retrieve a collection of objects Methods return objects Only static methods (::, self)

lib/ model/ om/ BasePost.php BasePostPeer.php Post.php PostPeer.php

Object classes No suffix Useful to create / inspect / update records Methods return column values Only object methods (->, $this)

lib/ model/ om/ BasePost.php BasePostPeer.php Post.php PostPeer.php

www.sensiolabs.com

Database Initialization

mysqladmin create phpday

./symfony configure:database mysql://localhost/phpday

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

schema.yml

Object model Base, Custom, Peer and object classes

Relational database Tables, columns, keys, indexes

propel:build-model

propel:build-sql propel:insert-sql

1

2

3

www.sensiolabs.com

If the Database preexists the Project

schema.yml

Object model Base, Custom, Peer and object classes

Relational database Tables, columns, keys, indexes

propel:build-model

propel:build-schema

2

3

1

www.sensiolabs.com

Generated Methods of Object Classes

Getter for columns $title = $post->getTitle(); $content = $post->getContent(); $createdAt = $post->getCreatedAt();

Some getters have special options $date = $post->getCreatedAt($dateFormat);

Getter by name $title = $post->getByName('title');

CamelCase version of the column name

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())

SELECT * FROM post

Criteria to SQL translation

resultset Query execution

Array of Post objects Object hydrating

www.sensiolabs.com

What the Model Layer does Template Model Database

$post->getTitle()

String Looking up internal attribute

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= ?

resultset Query execution

Array of Comment objects Object hydrating

www.sensiolabs.com

Comment Form

$ ./symfony propel:build-forms

www.sensiolabs.com

Base and Custom Classes Base classes

Under form/base/, prefixed by Base Generated by symfony Overwritten when the schema

changes and the forms are generated

Never edit these files!

lib/ form/ base/ BasePostForm.class.php PostForm.class.php

lib/ form/ base/ BasePost.Form.class.php PostForm.class.php

Custom classes Under form/, no prefix Inherit from Base classes Never overwritten Put custom methods here Override base methods here

www.sensiolabs.com

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/templates/layout.php

apps/frontend/modules/post/actions/components.class.php

apps/frontend/modules/post/templates/_categories.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

Sensio S.A. 26, rue Salomon de Rothschild

92 286 Suresnes Cedex FRANCE

Tél. : +33 1 40 99 80 80 Fax : +33 1 40 99 83 34

Contact Fabien Potencier

fabien.potencier@sensio.com

http://www.sensiolabs.com/ http://www.symfony-project.com/

Recommended