Web Development with
Symfony Friday May 9th 2014 – Osijek – Croatia
Slide 2
Slide 2 text
Hugo HAMON
Head of training at SensioLabs
Book author
Speaker at Conferences
Symfony contributor
@hhamon
Slide 3
Slide 3 text
No content
Slide 4
Slide 4 text
What is
Symfony2
Slide 5
Slide 5 text
Framework
Philosophy
Community
Slide 6
Slide 6 text
Symfony2 is a set of reusable,
standalone, decoupled, and
cohesive PHP components that
solve common web development
problems.
Slide 7
Slide 7 text
Dependency Injection
BrowserKit
ClassLoader
Config
Console CssSelector Debug
DomCrawler
EventDispatcher
ExpressionLanguage Filesystem
Finder Form
HttpFoundation
HttpKernel
Locale Intl Icu
OptionsResolver
Process
PropertyAccess
Routing Security
Serializer Stopwatch Templating Translation
Validator
Yaml
Slide 8
Slide 8 text
Symfony is also a full stack
web framework made of
bundles and third party
libraries.
Slide 9
Slide 9 text
No content
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
Community
Slide 12
Slide 12 text
+1,000 code contributors
Slide 13
Slide 13 text
+700 documentation contributors
Slide 14
Slide 14 text
+2,200 community bundles
Slide 15
Slide 15 text
And many open source projects!
Slide 16
Slide 16 text
IDE Integration
Slide 17
Slide 17 text
NETBEANS
Slide 18
Slide 18 text
PHP Storm
Slide 19
Slide 19 text
Installation
Slide 20
Slide 20 text
Easy installation
Slide 21
Slide 21 text
Easy installation with Composer
Slide 22
Slide 22 text
The First Page
Slide 23
Slide 23 text
Configuration
Slide 24
Slide 24 text
No content
Slide 25
Slide 25 text
Philosophy
Slide 26
Slide 26 text
# web/app.php
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Slide 27
Slide 27 text
No content
Slide 28
Slide 28 text
namespace Acme\DemoBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\[…]\Route;
use Symfony\Component\HttpFoundation\Response;
class DefaultController
{
/** @Route("/hello/{name}") */
public function indexAction($name)
{
return new Response('Hello '.$name);
}
}
Slide 29
Slide 29 text
class DefaultController extends Controller
{
/** @Route("/hello/{name}") */
public function indexAction($name)
{
return $this->render(
'AcmeDemoBundle:Default:index.html.twig',
[ 'name' => $name ]
);
}
}
Slide 30
Slide 30 text
class DefaultController
{
/**
* @Route("/schedule")
* @Template
*/
public function indexAction()
{
return [ 'title' => 'Schedule' ];
}
}
§ Database Abstraction Layer on top of PDO
§ Object Relational Mapper
§ Migrations support
§ Object Document Mapper (MongoDB)
§ Object XML Mapper (XML databases)
Doctrine2 Support
class appProdProjectContainer extends Container
{
protected function getUserManagerService()
{
$instance = new Acme\UserManager(
$this->get('debug.event_dispatcher'),
$this->get('security.encoder_factory'),
$this->get('doctrine.orm.default_entity_manager'),
$this->get('security.context')
);
$this->services['user_manager'] = $instance;
return $instance;
}
}
Service Factory Method
Slide 61
Slide 61 text
$manager = $this
->container
->get('user_manager')
;
Service Lazy Loading
Slide 62
Slide 62 text
Data
Validation
Slide 63
Slide 63 text
The validator component
validates objects againsts a
set of constraints.
Slide 64
Slide 64 text
/** @Assert\UniqueEntity("username") */
class User
{
/**
* @Assert\NotBlank
* @Assert\Email
*/
private $username;
/**
* @Assert\NotBlank
* @Assert\Length(min = 8, max = 32)
*/
private $password;
// ...
}
Slide 65
Slide 65 text
$user = new User();
$user->setUsername('[email protected]');
$user->setPassword('changeme');
$validator = $this->get('validator');
$errors = $validator->validate($user);
Validating an Object
Slide 66
Slide 66 text
Forms
management
Slide 67
Slide 67 text
h"p://www.flickr.com/photos/miahz/
Slide 68
Slide 68 text
namespace Sensio\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class UserType extends AbstractType
{
function buildForm(FormBuilderInterface $builder, …)
{
$builder
->add('username', 'email')
->add('password', 'password')
->add('submit', 'submit')
;
}
}
Slide 69
Slide 69 text
public function userAction(Request $request)
{
$user = new User();
$user->setUsername('[email protected]');
$form = $this->createForm(new UserType(), $user);
$form->handleRequest($request);
if ($form->isValid()) {
// ...
}
return ['form' => $form->createView() ];
}
Slide 70
Slide 70 text
{{ form(form) }}
Displaying the form
Slide 71
Slide 71 text
Automated
Tests
Slide 72
Slide 72 text
h"p://www.flickr.com/photos/kenstein/
Slide 73
Slide 73 text
No content
Slide 74
Slide 74 text
UNIT TESTING
Slide 75
Slide 75 text
FUNCTIONAL TESTING
Slide 76
Slide 76 text
No content
Slide 77
Slide 77 text
HTTP
Caching
Slide 78
Slide 78 text
RFC2616
Slide 79
Slide 79 text
Expiration
Validation
Slide 80
Slide 80 text
class DefaultController
{
/**
* @Template
* @Cache(expires="tomorrow")
*/
public function indexAction()
{
return [ 'title' => 'Schedule' ];
}
}
Slide 81
Slide 81 text
class DefaultController
{
/**
* @Template
* @Cache(maxage=120)
*/
public function indexAction()
{
return [ 'title' => 'Schedule' ];
}
}
Slide 82
Slide 82 text
HTTP Reverse
Proxy Caching
Slide 83
Slide 83 text
varnish-cache.org
Slide 84
Slide 84 text
Edge Side Includes
Slide 85
Slide 85 text
No ESI
Slide 86
Slide 86 text
With ESI
Slide 87
Slide 87 text
Internationalization
Localization
Slide 88
Slide 88 text
h"p://www.flickr.com/photos/bwop/
Slide 89
Slide 89 text
Symfony2 is great
J'aime Symfony2
Slide 90
Slide 90 text
{% set message = 'Symfony2 is great' %}
{{ message|trans }}
{% set message = 'My name is %name%!' %}
{{ message|trans({'%name%': 'Hugo'}, "hello") }}
Slide 91
Slide 91 text
Authentication
Authorizations
Slide 92
Slide 92 text
h"p://www.flickr.com/photos/cstein96/
Slide 93
Slide 93 text
/**
* @Security("has_role('ROLE_ADMIN')")
*/
public function editAction($id)
{
// granted to perform an action...
}
Using annotations to secure an action
Slide 94
Slide 94 text
Using expression to secure an action
/**
* @Security(
* expression="is_granted('EDIT', article)"
* )
*/
public function editAction(Article $article)
{
// granted to perform an action...
}