1. 30 Symfony Best Practices
30 Symfony Best
Practices
SymfonyDay ’09, Cologne, Germany
September 4th, 2009
Nicolas Perriault
2. 30 Symfony Best Practices
Best Practices?
A Best practice is a technique, method, process, activity, incentive or
reward that is believed to be more effective at delivering a particular
outcome than any other technique, method, process, etc.The idea is
that with proper processes, checks, and testing, a desired outcome
can be delivered with fewer problems and unforeseen
complications. Best practices can also be defined as the most
efficient (least amount of effort) and effective (best results) way of
accomplishing a task, based on repeatable procedures that have
proven themselves over time for large numbers of people.
-- Wikipedia, august 2009
Nicolas Perriault 2
3. 30 Symfony Best Practices
Best Practices?
Making. Stuff. Efficient.
Nicolas Perriault 3
4. 30 Symfony Best Practices
Best Practices?
• Moreover, best practices in software
development and symfony are all about:
• improving communication between
developers through standardization
• enhancing security, maintainability, portability
and interoperability by increasing code
quality
Nicolas Perriault 4
5. 30 Symfony Best Practices
Disclaimer
• These best practices are not sorted by
importance, nor criticality
• All best practices listed here are debatable, at
least because they’re based on my own
experience
• There are always exceptions
• Some best practices are not symfony-specific ;
“Zake Igniter” developers, you can take some notes
too.
Nicolas Perriault 5
7. 30 Symfony Best Practices
#0
• Always write “symfony” starting with a
small cap.
Nicolas Perriault 7
8. 30 Symfony Best Practices
#0
• Always write “symfony” starting with a
small cap.
• Or maybe not (mostly depends on the result of rand(0, 1))
Nicolas Perriault 7
9. 30 Symfony Best Practices
#1
• Manage the View within the View
• View is intended to be handled in templates
• Try to avoid the use of the view.yml file
• Try to avoid handling the view from the
controller (eeeek) or the model (you’re
fired)
• Slots can help (a lot)
Nicolas Perriault 8
10. 30 Symfony Best Practices
#1
For example, handling <title> tag and assets:
Note: here the value of $defaultTitle could (should) be handled
in an app.yml configuration file
Nicolas Perriault 9
11. 30 Symfony Best Practices
#1
• Remember this: if you’re a graphic designer/
integrator, you don’t want to deal with YAML or
complex PHP code to manage the presentation
Nicolas Perriault 10
12. 30 Symfony Best Practices
#2
• Always enable output escaping and CSRF
protection
• starting with symfony 1.3, they’re enabled
by default
Nicolas Perriault 11
14. 30 Symfony Best Practices
#3
• Always call a redirect after posting data
• for security purpose
• for ergonomy
• to avoid duplicates in database
• don’t forget to add a flash message to the
end user after every transaction made
Nicolas Perriault 13
17. 30 Symfony Best Practices
#4
• No Propel Criteria or Doctrine_Query
instances, SQL queries and any ORM/RDBMS
specific calls should ever be found neither in
the templates nor in the actions.
• The more you couple your model to your
controllers and views, the more it’ll be hard
to change your persistence backend or
strategy.
Nicolas Perriault 16
18. 30 Symfony Best Practices
BAD
Doctrine_Collection
Nicolas Perriault 17
20. 30 Symfony Best Practices
GOOD
Array (ideally)
Nicolas Perriault 19
21. 30 Symfony Best Practices
#5
• Symfony core files should never be
modified to add or change the features they
provide, but replaced through the
autoloading mechanism, or way better:
extended.
• Tweaking the factories.yml file and
catching native symfony events can help a lot
achieving this goal.
Nicolas Perriault 20
27. 30 Symfony Best Practices
#7
• Verify cache settings, especially that the
cache is actually enabled in prod
environment. Don’t laugh, it happened quite
a lot.
• If you use cache, create a staging
environment to test the caching strategy if it
doesn't exist.
• Better: avoid using cache. No kidding.
Nicolas Perriault 26
29. 30 Symfony Best Practices
#8
• Use routes instead of raw module/action
couple in url_for(), link_to() and
redirect() calls.
• Also, default routes should be deactivated
by default (at least in apps which don’t run
admin-generator 1.0 modules)
Nicolas Perriault 28
30. 30 Symfony Best Practices
#9
• All code comments, phpdoc, INSTALL,
CHANGELOG and README files, variables,
functions, classes and methods names and
more generally the developer
documentation, should be written in
English.
Nicolas Perriault 29
39. 30 Symfony Best Practices
#12
• Ideally:
• A typical controller method should never
exceed ~30 lines.
• A typical controller class should never
have more than ~15 action methods.
Nicolas Perriault 38
40. x
30 Symfony Best Practices
BAD
Nicolas Perriault ~2000 lines on this actions class (the slidescreen size was to short to list them all). Unmaintenable. 39
49. 30 Symfony Best Practices
GOOD
Note: of course, a setRecentlySeenProducts() method could have been implemented in the myUser class.
Nicolas Perriault 48
50. 30 Symfony Best Practices
#16
• Always create customized 404 error and
500 error pages
Nicolas Perriault 49
53. 30 Symfony Best Practices
#17
• There should never be any direct use of
sfContext inside the Model layer (eg.
sfContext::getInstance())
• Because the sfContext instance you get can
differ a lot regarding the used env (cli, test,
dev, prod...)
• It would make your code quite untestable
• Yes, it’s hard.
Nicolas Perriault 52
58. 30 Symfony Best Practices
#18
• Avoid creating a big generic utility class
with many static methods
• It's like reinventing procedural
programming or using functions
• Write specialized classes
Nicolas Perriault 57
59. 30 Symfony Best Practices
#19
• Use sfLogger for debugging instead of
echoing variable or debug messages
• FirePHP(1) or FireSymfony(2) custom loggers
can be more than helpful to debug your app
(webservices for example)
(1) http://firephp.org/
(2) http://firesymfony.org/
Nicolas Perriault 58
60. 30 Symfony Best Practices
GOOD
factories.yml
The FireSymfony Firebug extension for Firefox in action
Nicolas Perriault 59
61. 30 Symfony Best Practices
#20
• If source code is managed through a SCM
tool, versioned files should NEVER contain
passwords, local paths, etc.
• Files containing them should be added to the
ignore directive
• Typical example: the databases.yml file
• Distribute platform-dependent configuration
files
Nicolas Perriault 60
64. 30 Symfony Best Practices
#21
• Write unit and functional tests:
• Unit test symfony business logicit’s
don’t
test your
or Doctrine again,
(please
already done)
• Functionally test the user interface
when it’s important (eg.
404/403/401 HTTP codes, security and user
authentication, transactions and forms, etc.)
Nicolas Perriault 63
65. 30 Symfony Best Practices
#21
Hint: you can write your own functional browser/
tester to avoid duplicate test code
Nicolas Perriault 64
66. 30 Symfony Best Practices
#22
• Never use absolute paths in code, or at
least put them in YAML configuration files.
• Make your symfony project portable: use
dirname(__FILE__) to point at the symfony
libs in the project configuration class.
• You can put symfony lib in a lib/vendor dir.
Nicolas Perriault 65
69. 30 Symfony Best Practices
#23
• Data objects should always be represented
by a slug in urls, not a primary key
• For security: numeric PKs are easily
guessable, whereas slugs are not
• For URL usability and SEO:
/article/symfony-rulez.html is sexier
than /article/123.html
Nicolas Perriault 68
70. 30 Symfony Best Practices
#24
• Every application or project specific
configuration variable should be
stored in its app.yml file
• You can share project-wide (cross-
applications) settings by putting an app.yml
file within the root config/ folder of the
project
Nicolas Perriault 69
72. 30 Symfony Best Practices
GOOD
Default value
Nicolas Perriault 71
73. 30 Symfony Best Practices
#25
• Avoid versioning any generated Base* class
file, especially if you want to write
reusable plugins or redistribute your
work.
• Maybe people will want to extend or add
behaviors to your model classes.
Nicolas Perriault 72
74. 30 Symfony Best Practices
#26
• Use symfony tasks system for CLI batch
scripts
• Tasks have access to all the symfony
facilities
• Tasks are designed for the CLI
• Text output
• Pretty printing
Nicolas Perriault 73
76. 30 Symfony Best Practices
#27
• Alter request and response
programmatically by using filters.
• You can use the request.filter_parameters
and response.filter_content events too.
• Filters are easy to setup and to debug,
whereas events are more clean and
powerful. Matter of taste.
Nicolas Perriault 75
79. 30 Symfony Best Practices
#28
• Always write a README, an INSTALL and a
CHANGELOG file at the root of the project
(or the plugin). If open sourced, a LICENSE
file is appreciated too.
• And please don’t release plugins under the
terms of the GPL license.
Symfony Plugin != Operating System
Nicolas Perriault 78
80. 30 Symfony Best Practices
#29
• Share features and modules across
applications by writing plugins
• If it’s really cool, release it publicly
Nicolas Perriault 79
81. 30 Symfony Best Practices
#30
• Study other frameworks code!
• They might have good, even better ideas
to solve the problem you have
• Even frameworks written in other
languages than PHP (Django, Rails,
Spring...)
Nicolas Perriault 80
82. 30 Symfony Best Practices
Questions?
Nicolas Perriault
nperriault@gmail.com
+33 660 920 867
prendreuncafe.com | symfonians.net | symfony-project.org
Nicolas Perriault