Download as pdf or txt
Download as pdf or txt
You are on page 1of 82

30 Symfony Best Practices

30 Symfony Best
Practices
SymfonyDay ’09, Cologne, Germany
September 4th, 2009

Nicolas Perriault
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
30 Symfony Best Practices

Best Practices?

Making. Stuff. Efficient.

Nicolas Perriault 3
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
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
30 Symfony Best Practices

Let’s begin...

Nicolas Perriault
30 Symfony Best Practices

#0

• Always write “symfony” starting with a


small cap.

Nicolas Perriault 7
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
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
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
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
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
30 Symfony Best Practices

GOOD

Nicolas Perriault 12
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
30 Symfony Best Practices

BAD

Nicolas Perriault 14
30 Symfony Best Practices

GOOD

Nicolas Perriault 15
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
30 Symfony Best Practices

BAD

Doctrine_Collection
Nicolas Perriault 17
30 Symfony Best Practices

BETTER

Array
Nicolas Perriault 18
30 Symfony Best Practices

GOOD

Array (ideally)

Nicolas Perriault 19
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
30 Symfony Best Practices

BAD
Unused

Nicolas Perriault 21
30 Symfony Best Practices

GOOD

Nicolas Perriault 22
30 Symfony Best Practices

#6

• The templates must contain PHP


alternative templating syntax, for
readability and ease of use.

Nicolas Perriault 23
30 Symfony Best Practices

BAD

Nicolas Perriault 24
30 Symfony Best Practices

GOOD

Nicolas Perriault 25
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
30 Symfony Best Practices

GOOD

Nicolas Perriault 27
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 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
30 Symfony Best Practices

BAD

Nicolas Perriault 30
30 Symfony Best Practices

GOOD

Nicolas Perriault 31
30 Symfony Best Practices

#10

• Catch and log exception messages, display


human readable error messages to the end
user

Nicolas Perriault 32
30 Symfony Best Practices

BAD

Nicolas Perriault 33
30 Symfony Best Practices

GOOD

Nicolas Perriault 34
30 Symfony Best Practices

#11

• Only deploy production front controllers in


production

Nicolas Perriault 35
30 Symfony Best Practices

BAD

Nicolas Perriault 36
30 Symfony Best Practices

BAD

Nicolas Perriault 37
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
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
30 Symfony Best Practices

#13

• Always apply consistent coding


standards.
• Always apply Symfony’s coding standards.
http://trac.symfony-project.org/wiki/HowToContributeToSymfony#CodingStandards

Nicolas Perriault 40
30 Symfony Best Practices

BAD

Nicolas Perriault 41
30 Symfony Best Practices

GOOD

Nicolas Perriault 42
30 Symfony Best Practices

#14

• Session persistence logic should


reside in sfUser derived class methods, and
only them.

Nicolas Perriault 43
30 Symfony Best Practices

BAD

Nicolas Perriault 44
30 Symfony Best Practices

GOOD

Nicolas Perriault 45
30 Symfony Best Practices

#15

• Never serialize objects in the session

Nicolas Perriault 46
30 Symfony Best Practices

BAD

Nicolas Perriault 47
30 Symfony Best Practices

GOOD

Note: of course, a setRecentlySeenProducts() method could have been implemented in the myUser class.

Nicolas Perriault 48
30 Symfony Best Practices

#16

• Always create customized 404 error and


500 error pages

Nicolas Perriault 49
30 Symfony Best Practices

BAD

Nicolas Perriault 50
30 Symfony Best Practices

GOOD

Nicolas Perriault 51
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
30 Symfony Best Practices

BAD

Nicolas Perriault 53
30 Symfony Best Practices

BAD

Nicolas Perriault 54
30 Symfony Best Practices

GOOD

Nicolas Perriault 55
30 Symfony Best Practices

GOOD

Nicolas Perriault 56
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
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
30 Symfony Best Practices

GOOD
factories.yml

The FireSymfony Firebug extension for Firefox in action

Nicolas Perriault 59
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
30 Symfony Best Practices

BAD

Nicolas Perriault 61
30 Symfony Best Practices

GOOD

Nicolas Perriault 62
30 Symfony Best Practices

#21
• Write unit and functional tests:
• Unit test your business logic (please
don’t test symfony or Doctrine again, it’s
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
30 Symfony Best Practices

#21
Hint: you can write your own functional browser/
tester to avoid duplicate test code

Nicolas Perriault 64
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
30 Symfony Best Practices

BAD

Nicolas Perriault 66
30 Symfony Best Practices

GOOD

Nicolas Perriault 67
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
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
30 Symfony Best Practices

BAD

Nicolas Perriault 70
30 Symfony Best Practices

GOOD

Default value

Nicolas Perriault 71
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
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
30 Symfony Best Practices

#26

Nicolas Perriault 74
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
30 Symfony Best Practices

GOOD

Nicolas Perriault 76
30 Symfony Best Practices

GOOD

Nicolas Perriault 77
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
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
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
30 Symfony Best Practices

Questions?

Nicolas Perriault
nperriault@gmail.com
+33 660 920 867

prendreuncafe.com | symfonians.net | symfony-project.org

Nicolas Perriault

You might also like