diving into symfony 2007
DESCRIPTION
phpworks 2007 talk - diving into symfonyTRANSCRIPT
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 }
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>
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
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
71
YAHOO IS HIRING
Are you good with AJAX, PHP,DHTML/XHTML, Javascript, CSS,
Actionscript / Flash?
Then we have a job for you!