symfony
An Open-Source Framework
     for Professionals
         Fabien Potencier
      Stefan Koopmanschap
Before we begin



     How many have already
    used symfony for a project,
even a very small personal project?
Who are we?
•  Fabien Potencier
  –  Founder of Sensio
     •  Web Agency
     •  Since 1998
     •  45 people
     •  Ope...
symfony
•  PHP Web framework
•  Based on
   –  10 years of Sensio experience
   –  Existing Open-Source projects


•  Buil...
Framework
Whatever the application, a
  framework is build to ease
development by providing tools
for recurrent and boring tasks.
Maintainability & Evolutivity
Structure & Standardisation
MVC
Model
View
Controller
1



                 Internet

             2

           Controleur             6

      3                 5

  Modèle  ...
Develop Faster & Better
Write less code


                          less code
                              
                       less complexi...
Each line of code has an initial cost

                     Costinitial = Costdeveloppement + Costtests


… and there is a...
symfony
An Open-Source Framework
MIT Licence


  « It is a permissive license, meaning that it permits
   reuse within proprietary software on the conditio...
An Open-Source Documentation
•  Open-Source documentation
  –  The book (450 pages - GFDL)
  –  Askeet Tutorial (250 pages)


•  Translation in 12 lang...
A great Community
Mailing-list support / forums / IRC

240 available plugins

300k unique visitors per month on the official
  website www.s...
« Entreprise » Version
Version 1.0 released early 2007

  – Maintained for 3 years (early 2010)
  – ~1 release a month (1.0.16 now)
    • Bug and...
Version 1.1 to be released this month
  – Maintained for 1 year
  – Same release cycle as 1.0


Roadmap
  – Version 1.2 Q4...
symfony is a set of cohesive
  but decoupled classes
symfony platform
sfEventDispatcher
// sfUser!
$event = new sfEvent($this, ‘user.change_culture’,
   array(‘culture’ => $culture));!
$dispat...
the symfony MVC framework
         is based on
    the symfony platform
Let’s start a Project
The Project
•  A simple blog system
  –  Posts
  –  Categories
  –  Authors
  –  Comments
•  Requirements
  –  Maintainabl...
List of recent posts


             Excerpt



                                Categories
             Post information
Sidebar customization


List of comments




Add a comment
YUI stylesheets

                          homepage



Famfamfam icons



             post




  http://www.symfony-proje...
Project Initialization
Bootstrap a symfony Project

1.  Install symfony

2.  Initialize a new project

3.  Configure the Web Server

4.  Start co...
Installing symfony

Sandbox: Ready-to-run symfony application

PEAR: Install symfony globally on your machine

Subversion:...
symfony CLI
$ symfony!
Create a new Project

$ mkdir blog!
$ cd blog!
$ symfony generate:project blog!
Create a new Application
./symfony help generate:app!
Create a new secure Application
   ./symfony generate:app frontend !
             --escaping-strategy=on !
             --...
Project, Application, Module, Action
Which symfony Version?

./symfony -V!




config/ProjectConfiguration.class.php!
Configure the Web Server
<VirtualHost *:80>
  ServerName myapp.example.com
  DocumentRoot "/path/to/blog/web"
  DirectoryI...
symfony Assets
Used by the default pages and the Web Debug Toolbar

Configure the Web Server to serve symfony assets
     ...
Environments
developers   customers     end users




development     staging      production
environment   environment   environment
cache        cache         cache

   debug        debug         debug

    logs         logs          logs

              ...
Try a 404
dev environment!
                               prod environment!
Front Controllers
dev environment!




                                 environment


                                    ...
Environment Configuration
apps/frontend/config/settings.yml!

      environment




           Web debug toolbar
Web Debug Toolbar

      Web debug toolbar
Create a Module for Posts
Create a new ‘post’ module in the ‘frontend’
  application

      $ php symfony generate:module ...
Project, Application, Module, Action
Action and Template Naming
/frontend_dev.php/blog/index


                 module action

// in apps/frontend/modules/blog...
Browse
/frontend_dev.php/post/index!
Create the Blog Homepage
apps/frontend/modules/post/templates/indexSuccess.php!

•  Copy homepage.html into indexSuccess.p...
Create an Action to show a Post
apps/frontend/modules/post/actions/actions.class.php!

•  Create an empy executeShow() act...
Project, Application, Module, Action
Extract common Code

                            Post page specific content




Homepage specific content
The Layout
   A layout wraps the template content

          header.php
                                   page content
  ...
The Layout
Move the common code from homepage and post to
  the layout

         apps/frontend/templates/layout.php!
Customize the Sidebar and the Title
                            The title depends on the page




         The sidebar dep...
Layout with Several "holes"
A slot content depends on the template context


           Slot1
                          Ma...
Create Slots for Title and Sidebar
apps/frontend/templates/layout.php!
Fill the Slots
apps/frontend/modules/blog/templates/showSuccess.php!
Passing Data from Action to Template
apps/frontend/modules/blog/actions/actions.class.php!




    apps/frontend/modules/b...
Make the Counter dynamic
Database Schema


A post has an author

A post can be in a category

A post can have comments
Propel : The symfony ORM
ORM = Object-Relational Mapping
Mapping a relational database to an object-oriented
  model
Datab...
Schema Conventions
post:
  id:           #   primary key, autoincrement integer
  author_id:    #   foreign key to Author
...
Database Schema
config/schema.yml!
Build the Model Classes
./symfony propel:build-model!
From Schema to Object Model

             $ ./symfony propel:build-model!

propel:                               lib/
  po...
Base and Custom Classes
lib/
  model/
                          Base classes
     om/                     Under model/om/,...
Peer and Object Classes
lib/                      Peer classes
  model/
     om/                     Suffixed by Peer
    ...
Database Initialization



mysqladmin create dutchconference!
./symfony configure:database mysql://localhost/dutchconferenc...
Build the SQL queries
./symfony propel:build-sql!




./symfony propel:insert-sql!
Shortcut for all the previous Tasks



          ./symfony propel:build-all!
Initial Data
data/fixtures/01-data.yml!


             Define PKs with names




             Use names instead of Pks

   ...
Load Data
$ ./symfony propel:data-load frontend!
Summary of Code Generation

           2                     Object model
           propel:build-model!   Base, Custom,
 ...
If the Database preexists the Project

           3                      Object model
            propel:build-model!   Ba...
Generated Methods of Object Classes
Getter for columns
  $title     = $post->getTitle();           CamelCase version
  $co...
Generated Methods of Object Classes
Manipulate primary keys
   $commentId = $comment->getId();
   // for composite keys, p...
Get the Posts from the Database
What the Model Layer does
Action                Model                     Database


    PostPeer::doSelect(new Criteria()...
What the Model Layer does
Template                Model                   Database


   $post->getTitle()!

              ...
Make the Post show Page dynamic

/frontend_dev.php/post/show?id=1!
Make the Post show Page dynamic




           Display a 404 error if the post does not exist
Change the Date Format
getPublishedAt() first argument accepts the date()
  format or the strftime() format

symfony forma...
Helper Groups
•  Tag
•  URLs
•  Assets (images, JavaScript, CSS, …)
•  Subtemplate inclusion (slot, partial, component)
• ...
Permalinks
•  Many applications provide an alternative to
   functional URLs
•  Permalinks look like links to permanent co...
Links to the Post Page
apps/frontend/config/routing.yml!




                                   lib/modełPost.php!
Links to the Post Page

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




        apps/frontend/modules/post/acti...
Link to the Homepage
Add the Comments
apps/frontend/modules/post/templates/showSuccess.php!
What the Model Layer does
Template              Model                  Database


    $post->getComments()!


            ...
Comment Form
$ ./symfony propel:build-forms!
Base and Custom Classes
lib/                              Base classes
  form/
     base/
                                ...
Create a Comment Form
apps/frontend/modules/post/actions/actions.class.php!




apps/frontend/modules/post/templates/showS...
Create a Comment Form
Propel Forms
•  Generated by propel:build-forms
•  1 table = 1 form
•  Model introspection to determine
  –  The widget
  ...
Bind The Form to the Post
Customize the Form
lib/form/CommentForm.class.php!
Form Life Cycle
Comments
Security: XSS
Security: CSRF
Create the Category Page
lib/modełPostPeer.class.php!




         apps/frontend/modules/blog/actions/actions.class.php!
Create the Category Page
apps/frontend/config/routing.yml!




                           apps/frontend/templates/layout.ph...
Create a Partial for the List
apps/frontend/modules/blog/templates/_list.php!




apps/frontend/modules/blog/templates/lis...
Create a Component
apps/frontend/modules/post/actions/components.class.php!




apps/frontend/modules/post/templates/_cate...
Create a Web Service for Posts
apps/frontend/config/routing.yml!




  apps/frontend/modules/post/templates/indexSuccess.xm...
If we have time…
•  Functional Tests

•  Cache

•  CRUD to manage posts
Sensio S.A.
                     26, rue Salomon de Rothschild
                         92 286 Suresnes Cedex
            ...
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
Upcoming SlideShare
Loading in …5
×

symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)

10,534
-1

Published on

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,534
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
49
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)

  1. 1. symfony An Open-Source Framework for Professionals Fabien Potencier Stefan Koopmanschap
  2. 2. Before we begin How many have already used symfony for a project, even a very small personal project?
  3. 3. Who are we? •  Fabien Potencier –  Founder of Sensio •  Web Agency •  Since 1998 •  45 people •  Open-Source Specialists •  Big corporate customers –  Creator and lead developer of symfony •  Stefan Koopmanschap –  Consultant at Ibuildings –  Initiator of symfony-framework.nl and symfonyCamp –  symfony developer for 2 years
  4. 4. symfony •  PHP Web framework •  Based on –  10 years of Sensio experience –  Existing Open-Source projects •  Built for : –  Professional websites –  Complex needs –  Demanding environments
  5. 5. Framework
  6. 6. Whatever the application, a framework is build to ease development by providing tools for recurrent and boring tasks.
  7. 7. Maintainability & Evolutivity
  8. 8. Structure & Standardisation
  9. 9. MVC
  10. 10. Model
  11. 11. View
  12. 12. Controller
  13. 13. 1 Internet 2 Controleur 6 3 5 Modèle Vue 4 BDD
  14. 14. Develop Faster & Better
  15. 15. Write less code less code  less complexity  less bugs  more productivity  more time More time for edge cases, business rules, …
  16. 16. 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)
  17. 17. symfony
  18. 18. An Open-Source Framework
  19. 19. 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. »
  20. 20. An Open-Source Documentation
  21. 21. •  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
  22. 22. A great Community
  23. 23. Mailing-list support / forums / IRC 240 available plugins 300k unique visitors per month on the official website www.symfony-project.org
  24. 24. « Entreprise » Version
  25. 25. Version 1.0 released early 2007 – Maintained for 3 years (early 2010) – ~1 release a month (1.0.16 now) • Bug and security fixes, compatibility with new PHP versions fixes • No new features (even small ones) • Upgrading is simple and safe
  26. 26. Version 1.1 to be released this month – Maintained for 1 year – Same release cycle as 1.0 Roadmap – Version 1.2 Q4 2008 – Version 1.3 Q1 2009
  27. 27. symfony is a set of cohesive but decoupled classes
  28. 28. symfony platform
  29. 29. sfEventDispatcher // sfUser! $event = new sfEvent($this, ‘user.change_culture’, array(‘culture’ => $culture));! $dispatcher->notify($event);! // sfI18N! $callback = array($this, ‘listenToChangeCultureEvent’);! $dispatcher->connect(‘user.change_culture’, $callback);! •  sfI18N and sfUser are decoupled •  « Anybody » can listen to any event •  You can notify existing events or create new ones
  30. 30. the symfony MVC framework is based on the symfony platform
  31. 31. Let’s start a Project
  32. 32. The Project •  A simple blog system –  Posts –  Categories –  Authors –  Comments •  Requirements –  Maintainable –  Customizable –  Secure •  Use symfony 1.1
  33. 33. List of recent posts Excerpt Categories Post information
  34. 34. Sidebar customization List of comments Add a comment
  35. 35. YUI stylesheets homepage Famfamfam icons post http://www.symfony-project.org/get/design.tgz
  36. 36. Project Initialization
  37. 37. Bootstrap a symfony Project 1.  Install symfony 2.  Initialize a new project 3.  Configure the Web Server 4.  Start coding
  38. 38. Installing symfony Sandbox: Ready-to-run symfony application PEAR: Install symfony globally on your machine Subversion: Be free to have several versions around
  39. 39. symfony CLI $ symfony!
  40. 40. Create a new Project $ mkdir blog! $ cd blog! $ symfony generate:project blog!
  41. 41. Create a new Application ./symfony help generate:app!
  42. 42. Create a new secure Application ./symfony generate:app frontend ! --escaping-strategy=on ! --csrf-secret=A$ecret!
  43. 43. Project, Application, Module, Action
  44. 44. Which symfony Version? ./symfony -V! config/ProjectConfiguration.class.php!
  45. 45. 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>
  46. 46. 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
  47. 47. Environments
  48. 48. developers customers end users development staging production environment environment environment
  49. 49. cache cache cache debug debug debug logs logs logs stats stats stats development staging production environment environment environment
  50. 50. Try a 404 dev environment! prod environment!
  51. 51. Front Controllers dev environment! environment prod environment! environment
  52. 52. Environment Configuration apps/frontend/config/settings.yml! environment Web debug toolbar
  53. 53. Web Debug Toolbar Web debug toolbar
  54. 54. Create a Module for Posts Create a new ‘post’ module in the ‘frontend’ application $ php symfony generate:module frontend post!
  55. 55. Project, Application, Module, Action
  56. 56. 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 -->
  57. 57. Browse /frontend_dev.php/post/index!
  58. 58. 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!
  59. 59. 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!
  60. 60. Project, Application, Module, Action
  61. 61. Extract common Code Post page specific content Homepage specific content
  62. 62. The Layout A layout wraps the template content header.php page content include decoration page content include footer.php layout.php
  63. 63. The Layout Move the common code from homepage and post to the layout apps/frontend/templates/layout.php!
  64. 64. Customize the Sidebar and the Title The title depends on the page The sidebar depends on the page
  65. 65. 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
  66. 66. Create Slots for Title and Sidebar apps/frontend/templates/layout.php!
  67. 67. Fill the Slots apps/frontend/modules/blog/templates/showSuccess.php!
  68. 68. Passing Data from Action to Template apps/frontend/modules/blog/actions/actions.class.php! apps/frontend/modules/blog/templates/indexSuccess.php!
  69. 69. Make the Counter dynamic
  70. 70. Database Schema A post has an author A post can be in a category A post can have comments
  71. 71. 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
  72. 72. 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 }
  73. 73. Database Schema config/schema.yml!
  74. 74. Build the Model Classes ./symfony propel:build-model!
  75. 75. 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?
  76. 76. Base and Custom Classes lib/ model/ Base classes 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 Inherit from Base classes BasePostPeer.php Post.php Never overwritten PostPeer.php Put custom methods here Override base methods here
  77. 77. 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/ om/ No suffix BasePost.php Useful to create / inspect / update BasePostPeer.php records Post.php Methods return column values PostPeer.php Only object methods (->, $this)
  78. 78. Database Initialization mysqladmin create dutchconference! ./symfony configure:database mysql://localhost/dutchconference!
  79. 79. Build the SQL queries ./symfony propel:build-sql! ./symfony propel:insert-sql!
  80. 80. Shortcut for all the previous Tasks ./symfony propel:build-all!
  81. 81. Initial Data data/fixtures/01-data.yml! Define PKs with names Use names instead of Pks Dynamic values
  82. 82. Load Data $ ./symfony propel:data-load frontend!
  83. 83. 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
  84. 84. 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
  85. 85. Generated Methods of Object Classes Getter for columns $title = $post->getTitle(); CamelCase version $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');
  86. 86. 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
  87. 87. Get the Posts from the Database
  88. 88. 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!
  89. 89. What the Model Layer does Template Model Database $post->getTitle()! Looking up internal attribute String!
  90. 90. Make the Post show Page dynamic /frontend_dev.php/post/show?id=1!
  91. 91. Make the Post show Page dynamic Display a 404 error if the post does not exist
  92. 92. Change the Date Format getPublishedAt() first argument accepts the date() format or the strftime() format symfony format_date() helper is i18n aware
  93. 93. Helper Groups •  Tag •  URLs •  Assets (images, JavaScript, CSS, …) •  Subtemplate inclusion (slot, partial, component) •  Links •  Form •  Javascript and Ajax •  Text, number, date manipulation •  I18N •  …
  94. 94. 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
  95. 95. Links to the Post Page apps/frontend/config/routing.yml! lib/modełPost.php!
  96. 96. Links to the Post Page apps/frontend/modules/post/templates/indexSuccess.php! apps/frontend/modules/post/actions/actions.class.php!
  97. 97. Link to the Homepage
  98. 98. Add the Comments apps/frontend/modules/post/templates/showSuccess.php!
  99. 99. 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!
  100. 100. Comment Form $ ./symfony propel:build-forms!
  101. 101. Base and Custom Classes lib/ Base classes form/ base/ Under form/base/, prefixed by 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 Override base methods here
  102. 102. Create a Comment Form apps/frontend/modules/post/actions/actions.class.php! apps/frontend/modules/post/templates/showSuccess.php!
  103. 103. Create a Comment Form
  104. 104. 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
  105. 105. Bind The Form to the Post
  106. 106. Customize the Form lib/form/CommentForm.class.php!
  107. 107. Form Life Cycle
  108. 108. Comments
  109. 109. Security: XSS
  110. 110. Security: CSRF
  111. 111. Create the Category Page lib/modełPostPeer.class.php! apps/frontend/modules/blog/actions/actions.class.php!
  112. 112. Create the Category Page apps/frontend/config/routing.yml! apps/frontend/templates/layout.php!
  113. 113. Create a Partial for the List apps/frontend/modules/blog/templates/_list.php! apps/frontend/modules/blog/templates/listByCategorySuccess.php!
  114. 114. Create a Component apps/frontend/modules/post/actions/components.class.php! apps/frontend/modules/post/templates/_categories.php! apps/frontend/templates/layout.php!
  115. 115. Create a Web Service for Posts apps/frontend/config/routing.yml! apps/frontend/modules/post/templates/indexSuccess.xml.php!
  116. 116. If we have time… •  Functional Tests •  Cache •  CRUD to manage posts
  117. 117. Sensio S.A. 26, rue Salomon de Rothschild 92 286 Suresnes Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier@sensio.com http://www.sensiolabs.com/ http://www.symfony-project.com/

×