72
1 Dustin Whittle Social Search Group Diving into symfony

Diving Into Symfony 2007

Embed Size (px)

DESCRIPTION

phpworks 2007 talk - diving into symfony

Citation preview

1

Dustin WhittleSocial Search Group

Diving into symfony

2

Introduction

This session will cover rapid applicationdevelopment using the symfony platform.

Learn what symfony is, how symfonyworks, and why it will simultaneously

speed up your development and producesecure maintainable code.The focus willbe on how to build, test, and deploy yourweb 2.0 applications using symfony and

an assortment of integrated tools.

3

What is the symfony project?

• Full stack web application framework built forrapid application development

• Written in PHP5• A growing community since 2005• Open source and free• Licensed under the MIT license

symfony is a web application framework,which automates most of the tedious tasks

of an AJAX developer

4

Why a framework?

• Another software layer (symfony, php, apache, linux/bsd)• Factors out common patterns

– Code Structure/Layout -> (action + view)– Configuration– Clean Routing– User Security / Authentication / Credentials / Attribute– Server Side Form Validation / Automated Repopulation– Internationalization / Localization– ORM– Unit & Functional Testing

• Encourages good design• Abstraction > Consistency > Long Term Maintainability

5

Why symfony?

• Agile Development– Built on best practices– Built to factor out common patterns and allow

developers to focus on application logic

• Performance– Proven to scale on very active web sites - Y!

• Stable– Tested code base (4000+ unit and functional tests)

• Support– Great documentation and very active community

6

How is symfony different?

• By default, comes with most tools needed fordevelopment– Routing, I18n/l10n, ORM, Caching,– Debug Environment– Code Generation

• CRUD, Admin Generators, Database Objects (propel)

– Helpers for Forms, AJAX, Visual Effects– Plugin System– Unit and functional testing– Project administration

• Project/Module Creation, Deployment Tools

7

Built to adapt = Flexibility

• Minimal Dependencies• Directory structure can be adapted to fit

your current environment• All major components are factories

– Built to be extended and customized for yourapplication (user, i18n, routing, controller,request, response, storage)

8

Clean Design

• Built using proven MVC design pattern– Model-View-Controller

• Router/Dispatcher• Separation / Encapsulation

– Model Logic (data access/manipulation)– Presentation logic (view/template)– Business logic (action/executor)

• Built to embrace agile development principles– Allows developers to easily practice

• Extreme Programming Philosophy• DRY (Don’t Repeat Yourself)• KISS (Keep it simple)

9

Requirements

• A web server that is capable of serving PHP5• Database server supported by Creole/PDO

– MySQL, PostgreSQL, SQLite, Oracle, MSSQL,

• Recommended Configuration– Apache

• mod_rewrite

– PHP 5.2.x• APC (xCache or eAccellerator are also supported)• Syck• xDebug

10

Installation

• PEARpear channel-discover pear.symfony-project.compear install symfony/symfony

• symfony sandboxhttp://www.symfony-project.com/get/sf_sandbox.tgz

• Subversionsvn export http://svn.symfony-project.com/branches/1.0/

11

Integrated PHP Libraries

• Creole– Database Abstraction– Support for MySQL, PostgreSQL, SQLite, MSSQL

• Propel– Object Relationship Mapping– Code generation for db objects/base objects

• PAKE– Command Line Tasks

• LIME– Unit and Functional Testing

12

Integrated Javascript Libraries

• Symfony makes it easy to build rich internetapplications– Prototype

• Javascript Framework

– script.aculo.us• AJAX Interactions• Visual Effects

– TinyMCE• Rich Text Editor (WYSIWYG)

– DynArch.com Rich Calendar• Rich Date Control

13

`symfony` command

• Creating projects/applications/modules• Managing your model• Code Generation

– CRUD, Admin– Propel Database Objects– Creation of Project / Applications / Modules with tests

• Executing Unit/Functional Tests• Deploying your project with rsync• Rotating and Purging logs• Installing/Removing Plugins• Upgrading symfony• Create your own tasks

14

Creating a project

1. mkdir -p ~/projects/sfproject2. cd ~/projects/sfproject3. symfony init-project sfproject4. symfony init-app frontend5. symfony init-module frontend content

15

Configuration System

• Convention over configuration– Establish conventions to eliminate the need to

configure• Allows a developer to only configure the unconventional

• YAML– Readable– Short syntax– Hierarchy Support

• Three levels of cascading configuration– project, application, module

• framework provides defaults

16

Environments

• Three default environments– Production

• caching enabled, logging disabled, clean URLs

– Development• Caching disabled, logging enabled, debug toolbar enabled

– Testing• Similar to production without caching

• Environment determined by front controller (entry)• Add as many environments as you require

– staging

17

Debug Environment

• Debug Toolbar– Browser access to relevant information

• Request Parameters / Sessions / Cookies• Configuration / Environment

– Logs & Debug Messages• xDebug Integration

– SQL Query Monitor• SQL Queries + Time

– Performance Monitor• Memory Consumption• Timers

– Cache Monitor

18

Configure your project

• Setup your database– databases.yml, propel.ini

• Configure your symfony settings– settings.yml

• Configure your default view– view.yml

• Configure your application settings– app.yml

19

Configure your databases

all: propel: class: sfPropelDatabase param: phptype: mysql hostspec: localhost username: symfonyworks password: password database: symfonyworks persistent: true encoding: utf8 compat_assoc_lower: true

20

Configure your symfony settings

use_database: on use_security: on use_flash: on i18n: on check_symfony_version: off use_process_cache: on compressed: off suffix: .html no_script_name: on

21

Configure your default view

default: http_metas: content-type: text/html; charset=utf-8 content-language: en metas: robots: noindex, nofollow description: symfony showcase project. keywords: symfony, showcase, project stylesheets: - common javascripts: - common

22

Configure your app settings

dev: ui:

title: symfony playground [dev]all: ui: theme: v1

title: symfony playground

delicious:username: dustin.whittlemax_per_page: 10

flickr: api_key: 4bb8629b535921fa13abd7cbd32ad8fb max: 10

23

The Model Layer

• By default based on Propel– Built in tools for pagination, sorting, and filters– Can be replaced with Doctrine or ezPDO– Support for behaviors

• Object model built via schema.yml– Can be reverse engineered from existing db– Support for indexes, references, constraints, and db

specific properties

• schema -> model generation -> sql -> insert

24

Create an object model/database

propel: _attributes: { noXsd: false, defaultIdMethod: native }

contents: _attributes: { phpName: Content } id: { type: integer, primaryKey: true, autoIncrement: true } title: { type: varchar, size: 255 } permalink: { type: varchar, size: 255, index: true } content: { type: longvarchar } created_at: { type: timestamp }

25

Build your object model

symfony propel-build-all

26

Add stub data (fixtures)

Content: Homepage: title: home content: <h1>Welcome to the site!</h1> About: title: about content: <h1>About</h1><p>about the site...</p> Contact: title: contact content: <h1>Contact</h1><p>contact the owner of the site...</p>

27

Rebuild the object model w/ data

symfony propel-build-all-load frontend

28

Customizing the object model

class Content extends BaseContent{ public function __toString() { return $this->getTitle(); } public function setTitle($title) { $this->setPermalink(TextTools::normalize($title)); return parent::setTitle($title); }}

29

Customize the object model peer

class ContentPeer extends BaseContentPeer{ public static function retrieveByPermalink($permalink) { $c = new Criteria(); $c->add(self::PERMALINK, $permalink);

return self::doSelectOne($c); }}

30

The Controller Layer

• Contains all business logic• Based on modules and actions

– Determined by route /:module/:action– A module is a group of related actions (user)

• Represented by a class containing actions

– An action is the business logic of any view• Represented by methods of the module class

• Actions can have multiple views– Actions return view types

• Success/Error/Custom

31

Create a content action

public function executeRender() { $permalink = $this->getRequestParameter('permalink',

false);

$this->forward404If(empty($permalink));

$this->content =ContentPeer::retrieveByPermalink($permalink);

$this->forward404Unless($this->content instanceof Content);

return sfView::SUCCESS; }

32

The View Layer

• PHP as a template language with helpers• View configuration managed via view.yml

– meta tags, title, javascript, css

• Layout– Common elements like header/footer

• Partials– Template fragment without business logic (footer)

• Components– Template fragment with business logic

• Slots -> a placeholder in layout

33

Create a view

<?php echo $content->getContent(); ?>

34

The Routing System

• Front controller• Converts url into appropriate module/action

– Support for requirements via regex matching

• Clean URL generation– link_to(‘click me’, ‘module/action’) / url_for helpers

content_render_permalink: url: /:permalink param: { module: content, action: render }

35

Easy rich interactions in PHP

• Template Helpers inspired from Rails– Based on prototype/script.aculo.us

• Easy implementations in one line of php– AJAX Interactions -> link_to_remote– Visual Effects -> visual_effect– Auto Complete -> input_autocomplete_tag– Inline Editing -> input_inline_editor_tag– Drag and Drop -> draggable_element– Rich Text Editing -> textarea_tag w/ rich=tinymce|fck– Rich Calendar -> input_date_tag

36

Easy AJAX

<?php use_helper(’Javascript') ?>

<?php echo link_to_remote(’about (ajax)', array('update'=> ’content', 'url' => ’content/render?permalink=about'));?>

<div id=“content”></div>

37

AJAX Toolkit Integration

• Prototype/scriptaculous built-in• Plugins available:

– sfUJSPlugin -> helpers for UJS via jQuery– sfYUIPlugin -> helpers for YUI– sfDojoPlugin -> helpers for Dojo– sfExtPlugin -> helpers for Ext

• Build your own helpers

38

A better AJAX (unobtrusive)

• Uses sfUJSPlugin to add unobtrusivelyadd behaviors to a page

<?php echo link_to('about', 'content/render?permalink=about','id=about'); ?>

<?php UJS_ajaxify_link('#about', array('update' => '#content', 'url' =>'content/render?permalink=about')); ?>

39

Integrate your own PHP libraries

• Autoloading hooks for easy integration of– Zend Framework– EZ Components– PEAR– Custom

40

Integrating the Zend framework

• Download Zend and install in lib/vendor/zf• Modify your settings.yml

autoloading_functions: [[sfZendFrameworkBridge, autoload]]zend_lib_dir: <?php echo sfConfig::get('sf_lib_dir'); ?>/vendor/zf

• Clear the symfony cache (symfony cc)

41

Create a homepage

• Create a homepage action– actions/actions.class.php public function executeHomepage() {

$this->content = ContentPeer::retrieveByPermalink('home');return sfView::SUCCESS;

}

• Create a homepage view– templates/homepageSuccess.php

42

Create a del.icio.us component

• Create actions/components.class.php public function executeDelicious()

{ $delicious = new

Zend_Service_Delicious(sfConfig::get('app_delicious_username'),sfConfig::get('app_delicious_password'));

$this->posts = $delicious->getRecentPosts(sfConfig::get('app_delicious_tag'),sfConfig::get('app_delicious_max', 10));

}

43

Create a del.icio.us partial

• frontend/content/templates/_delicious.php

<ul> <?php foreach($posts as $post): ?> <li><?php echo link_to($post->getTitle(), $post->getUrl()); ?></li> <?php endforeach; ?></ul>

44

Customize the homepage view

• templates/homepageSuccess.php

<?php echo $content->getContent(); ?>

<?php include_component('content', 'delicious'); ?>

45

Change the default homepage

• Modify the route (routing.yml)# default ruleshomepage: url: / param: { module: content, action: homepage }

• Modify the default settingsall: .actions: default_module: content

default_action: homepage

46

The Caching System

• Caching– Actions with or without the layout– Components– Template fragments

• cache/cache_save helpers

• Cache + ETag header handling• Configurable per action/component• File based or SQLite• sfSuperCachePlugin

47

Cache our homepage + delicious

• Enable in settings.ymlConfigure cache.yml

_delicious: enabled: true lifetime: 96000

homepage: enabled: true with_layout: true lifetime: 12000

48

Create a content administration

• symfony init-app backend• symfony propel-init-admin backend

content Content• Customize generator.yml

49

Generator.yml

fields: title: { name: Title, help: This is the title of the content. } content: { name: Body, help: This is the body of this content. } list: display: [=title, created_at] filters: [title, created_at] sort: title, desc fields: created_at: { params: disabled=true, type: plain } title: { type: plain } content: { type: textarea_tag, params: rich=true size=60x60}

50

Input Filtering & Output Escaping

• Input filtering– Transformations applied via converters in

form handling– Configurable via validate/:action.yml

• Output escaping– XSS prevention

• Automatically escapes all variables accessible tothe template

• Configurable via settings.yml

51

The Plugin System

• Plugins are packages– Configuration, Object Model, Libraries,

Helpers, Modules, Tasks, Tests, Assets

• Easy to install via PEAR– symfony plugin-install or pear install

• Plugins can be overridden/extended– Configuration, Object Model, Actions,

Templates

52

Available Plugins

• sfGuard– Basic auth/user/group/permission system

• sfFeed2 / sfWebBrowserPlugin– RSS/Atom Feed Generation/Aggregation

• sfSimpleCMS/sfSimpleBlog/sfSimpleForum– Basic content management/blog/forum

• sfSuperCache– Extremely fast full page caching

• sfErrorLogger– Error logging for 404 and 500 errors

53

Install sfGuardPlugin

• Install sfGuardPlugin from pear– symfony plugin-install

http://plugins.symfony-project.com/sfGuardPlugin

• Rebuild object model + load data– symfony propel-build-all-load frontend

54

Install sfGuardPlugin

• Enable in frontend (settings.yml) .settings: enabled_modules: [sfGuardAuth]

• Enable in backend (settings.yml) .settings: enabled_modules: [sfGuardGroup, sfGuardUser,

sfGuardPermission]

55

Install sfGuardPlugin

• Add remember me filter (filters.yml) security_filter: class: sfGuardBasicSecurityFilter

• Change default security actions(settings.yml)

login_module: sfGuardAuth login_action: signin secure_module: sfGuardAuth secure_action: secure

56

Secure your administration area

• Confirm frontend application is unsecure(apps/frontend/config/security.yml)

default: is_secure: off

• Modify backend application to be secure(apps/backend/config/security.yml)

default: is_secure: on

credentials: [admin | author]

57

I18n & L10n

• Inspired by PRADO• Flexible Configuration

– Dictionaries can be XLIFF, gettext, or database

• Caching• Template Helpers

– Dealing with text = __()• Works with complex strings

– Date, time, currency formatting

• Support for internationalization in database tables

58

LIME - Unit and Functional Testing

• Based on Test::More Perl library• Supports

– Unit Testing• Given specific input validate specific output

– Functional Testing• Does this work in context, a complete feature

• TAP compliant output• Zero Dependencies

59

Writing a basic Unit Test

$t = new lime_test(16, new lime_output_color());

$t->diag('hello world');$t->ok(1 == '1', 'the equal operator ignores type');$t->is(1, '1', 'a string is converted to a number for comparison');$t->isnt(0, 1, 'zero and one are not equal');$t->like('test01', '/test\d+/', 'test01 follows the test numbering pattern');$t->unlike('tests01', '/test\d+/', 'tests01 does not follow the pattern');$t->cmp_ok(1, '<', 2, 'one is inferior to two');$t->cmp_ok(1, '!==', true, 'one and true are not identical');$t->isa_ok('foobar', 'string', '\'foobar\' is a string');$t->isa_ok(new myObject(), 'myObject', 'new creates object of the right class');$t->can_ok(new myObject(), 'myMethod', 'objects of class myObject do have amyMethod method');$array1 = array(1, 2, array(1 => 'foo', 'a' => '4'));$t->is_deeply($array1, array(1, 2, array(1 => 'foo', 'a' => '4')), 'the first and the second array are the same');$t->include_ok('./fooBar.php', 'the fooBar.php file was properly included');

60

Execute Unit Tests

• ./symfony test-unit helloworld# hello worldok 1 - the equal operator ignores typeok 2 - a string is converted to a number for comparisonok 3 - zero and one are not equalok 4 - test01 follows the test numbering patternok 5 - tests01 does not follow the patternok 6 - one is inferior to twook 7 - one and true are not identicalok 8 - 'foobar' is a stringok 9 - new creates object of the right classok 10 - objects of class myObject do have a myMethod methodok 11 - the first and the second array are the samenot ok 12 - the fooBar.php file was properly included# Failed test (.\test\unit\testTest.php at line 27)# Tried to include './fooBar.php'

61

Write functional test for our app

$browser = new sfTestBrowser();$browser->initialize();

$browser-> get('/')-> isStatusCode(200)-> isRequestParameter('module', 'content')-> isRequestParameter('action', 'homepage')-> checkResponseElement('body', '/Welcome/')-> checkResponseElement('ul#list li a[href]', 'click me');

62

Execute Functional Test

• ./symfony test-functional frontend

# get /ok 1 - status code is 200ok 2 - request parameter module is contentok 3 - request parameter action is homepageok 4 - response selector body matches regex /Welcome/

63

Real World Performance

• Hello World in 15ms @ 220qps (pointless)– APC / Syck

• symfony provides many features by default– disable the ones you will not use

• Build intelligently, cache effectively• sfOptimizerPlugin / sfSuperCache• Yahoo! Bookmarks

– Full dynamic page in < 100ms

• symfony-project.com

64

Where to go from here?

• Read Documentation• Work through the Askeet advent• Step by step tutorials• Finding example code• Finding help

65

Documentation

• The Definitive Guide to symfony– http://symfony-project.com/book/trunk– Released open source 1/29/2007– Licensed under GFDL

• API Documentation– Good coverage

• Wiki– Many useful guides and how to knowledge– Many user contributed tips

66

Askeet Advent

• Askeet.com– http://symfony-project.com/askeet

• 24 day tutorial on how to build a real web2.0 application– In-depth coverage of all aspects of symfony

67

Tutorials

• Askeet• My first project• Building an ajaxified drag and drop

shopping cart• Sortable lists using ajax• Degradable ajax pagination

68

Example Code

• Askeet– http://trac.askeet.com

• Snippets– http://symfony-project.com/snippets/

• Snipeet– http://trac.snipeet.com

69

Finding Help

• Forums– http://www.symfony-project.com/forum

• IRC– irc.freenode.net/#symfony

• Mailing List (Google Groups)– [email protected]– archived & searchable

70

Questions?

71

YAHOO IS HIRING

Are you good with AJAX, PHP,DHTML/XHTML, Javascript, CSS,

Actionscript / Flash?

Then we have a job for you!

72

Enjoy the rest of the conference!