SlideShare a Scribd company logo
Symfony 4
Workshop
Victoria Quirante - @vicqr
Nacho Martin - @nacmartin
Notes: http://symfony4.limenius.com/
Nacho Martín
@nacmartin
nacho@limenius.com
Victoria Quirante
@vicqr
victoria@limenius.com
We build tailor-made projects with Symfony and React
We have been working with Symfony since 2008
We provide development, consulting and training
Symfony 4
We are here
Symfony Evolution
Symfony 12005 A monolith (very different)
Symfony 22011 Components appear
Components used in popular projects
Doctrine
Silex
Laravel
Symfony Evolution
Symfony 12005 A monolith (very different)
Symfony 22011 Components appear
Symfony 32015 Brief intermediate step
Symfony 42017 Compose your apps
Symfony 2/3
SF 2
Web app
SF 2
API
SF 2
Microservice
SF 4
Web app
SF4
API
SF4
Microservice
Symfony 4
Symfony 4
SF4 SF 4
Web app
SF4
API
SF4
Microservice
We need something to smooth
out these transformations
Symfony Flex
Symfony Flex is a tool to implement
Symfony 4 philosophy
It is a composer plugin that comes with
Symfony 4
The idea is automation to the max
when installing and configuring packages
Modifies the behaviour of the
require and update commands
Allows Symfony to perform tasks before
or after the composer commands
Symfony 4
Your application
with Symfony Flex
composer req mailer
Symfony Flex
Server
Recipe?
No
Regular install
With composer
Symfony 4
Your application
with Symfony Flex
composer req mailer
Symfony Flex
Server
Recipe?
Yes
Install them
With composer
Follow recipe instructions
Decide which packages to install
Run any task to configure them
http://symfony.sh
Directory Structure
my-project/
├── config/
│   ├── bundles.php
│   ├── packages/
│   ├── routes.yaml
│   └── services.yaml
├── public/
│   └── index.php
├── src/
│   ├── ...
│   └── Kernel.php
├── templates/
└── vendor/
Doctrine
Entity
Entity
namespace AppEntity;
class Movie
{
private $id;
private $name;
private $director;
private $year;
private $picture;
}
Entity /**
* @ORMEntity()
* @ORMTable(name="movie")
*/
class Movie
{
/**
* @ORMColumn(type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORMColumn(type="string")
*/
private $name;
/**
* @ORMColumn(type="string", length=100)
*/
private $director;
/**
* @ORMColumn(type="smallint")
*/
private $year;
/**
* @ORMColumn(type="string")
*/
private $picture;
}
Entity
Code that has to do with the model itself.
Doesn’t depend on services, or query the DB.
Accessors
In this workshop we are going to use setters and getters:
•getDirector()
•setDirector()
This is not the only way. See for instance:
http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/
Entity Manager
Entity Manager
$em = $this->getDoctrine()->getManager();
$em->getRepository(Movie::class)->find($movieId);
$em = $this->getDoctrine()->getManager();
$em->persist($sale);
$em->flush();
Doctrine Query Language (DQL)
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT m, a FROM App:Movie m LEFT JOIN m.actors a WHERE
m.id = :id'
)->setParameter('id', $movieId);
$movie = $query->getOneOrNullResult();
Query Builder
$em = $this->getDoctrine()->getManager();
$query = $em->getRepository(Movie::class)
->createQueryBuilder('m')
->select('m, a')
->leftJoin('m.actors', 'a')
->where('m.id = :id')
->setParameter('id', $movieId)
->getQuery();
$movie = $query->getOneOrNullResult();
Entity Manager
Code that deals with retrieving or persisting
entities.
Fixtures

With Alice
We could do this
for ($i = 0; $i < 10; $i ++) {
$movie = new Movie();
$movie->setYear(1994);
$movie->setName('Pulp Fiction'.$i);
//...
$em->persist($movie);
}
$em->flush();
With Alice
AppEntityMovie:
movie{1..10}:
name: '<sentence(4, true)>'
director: '<name()>'
year: '<numberBetween(1970, 2017)>'
picture: '<image("./public/images", 500, 500, "cats", false)>'
See all the generators in
https://github.com/fzaninotto/Faker
Relationships
appentitymovie:
actor{1..10}:
#…
movie{1..10}:
#...
actors: ["@actor<numberBetween(1, 3)>", "@actor<numberBetween(4, 6)>"]
Twig
Twig
{{ }}
{% %}
Display Data
Define Structures
Access variables
{{ foo }}
{{ foo.bar }}
{{ foo['bar'] }}
- Checks if foo is an array and bar an element
- If not, checks if foo is an object and bar a property
- If not, checks if foo is an object and bar a method
- If not, checks if foo is an object and getBar a method
- If not, checks if foo is an object and isBar a method
{{ foo.bar }}
Access variables
{% for user in users %}
{{ user.username }}
{% endfor %}
For each
{% for i in 0..10 %}
{{ i }}
{% endfor %}
For
For … else
{% for item in items %}
{{ item }}
{% else %}
No items.
{% endfor %}
<html><head>...</head>
<body>
<h1>
{% block title %}{% endblock %}
</h1>
{% block body %}{% endblock %}
</body></html>
Template inheritance
templates/layout.html.twig
{% extends "layout.twig" %}
{% block title %}
Home
{% endblock %}
{% block body %}
Lorem ipsum...
{% endblock %}
Template inheritance
templates/home.html.twig
{% extends "layout.twig" %}
{% block title %}
Movie list
{% endblock %}
{% block body %}
Duis aute irure dolor in..
{% endblock %}
Template inheritance
templates/movies.html.twig
Webpack

Encore
Webpack
Webpack
The standard nowadays.
Very powerful.
Steep learning curve.
Cons
Pros
Webpack Encore
A wrapper around Webpack that makes it
easier to set up.
It solves a big % of cases.
If you require something specific, you can still
use Webpack without Encore.
Forms
Create a form
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, ['label' => 'Create Post'])
->getForm();
return $this->render('default/new.html.twig', [
'form' => $form->createView(),
]);
Forms in Twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
You can customise a lot the rendering of every widget,
If you need to.
Handle submission
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, ['label' => 'Create Task'])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($task);
$em->flush();
return $this->redirectToRoute('task_success');
}
return $this->render('default/new.html.twig', [
'form' => $form->createView(),
]);
Forms in their own classes
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Task::class,
));
}
}
Events
Event and EventListener
Event EventListener
dispatch
Event
class SaleEvent extends Event
{
const NAME = 'sale.created';
protected $sale;
protected $movie;
protected $numTickets;
public function __construct(Sale $sale, Movie $movie, int $numTickets)
{
$this->sale = $sale;
$this->movie = $movie;
$this->numTickets = $numTickets;
}
public function getSale()
{
return $this->sale;
}
public function getMovie()
{
return $this->movie;
}
public function getNumTickets()
{
return $this->numTickets;
}
}
A bag of parameters
that describe the event
Dispatch Events
$this->get('event_dispatcher')
->dispatch(
SaleEvent::NAME,
new SaleEvent($sale, $movie, $numTickets)
);
EventListener
Processes the event
class SaleListener
{
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function onSaleCreated(SaleEvent $event)
{
for ($i = 0; $i < $event->getNumTickets(); $i++) {
$ticket = new Ticket();
$ticket->setMovie($event->getMovie());
$ticket->setSale($event->getSale());
$ticket->setRow(1);
$ticket->setSeat(1);
$this->em->persist($ticket);
}
}
}
Services
Services
A service is an object that does something:
• Generate a thumbnail.
• Generate a PDF.
• A query to ElasticSearch.
• Log something.
• Send an email.
Example
class SaleLogger
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function log(Sale $sale)
{
$this->logger->info('Sold ' . count($sale->getTickets()) . ' tickets to ' . $sale->getFullName());
}
}
Where does this come from?
Using services
public function listAction(SaleLogger $saleLogger)
{
//…
$saleLogger->log($sale);
}
Is injected with dependencies
Explicit configuration
# app/config/services.yml
services:
# explicitly configure the service
AppLoggerSaleLogger:
arguments:
$logger: '@monolog.logger.request'
Tagged services
$taggedServices = $container->findTaggedServiceIds(‘app.my_tag’);
foreach ($taggedServices as $id => $tags) {
$definition->addMethodCall('callAMethod', array(new Reference($id)));
}
AppMyServices:
resource: '../src/MyServices'
tags: ['app.my_tag']
Validation
Built in assertions
/**
* @ORMColumn(type="string")
* @AssertLength(min=2)
*/
private $fullName;
/**
* @ORMColumn(type="string")
* @AssertEmail()
*/
private $email;
/**
* @ORMColumn(type="text")
* @AssertLength(max=100)
*/
private $question;
Built in assertions
There are 47 assertions
From NotNull to Isbn
And we can write our
own assertions
Use validators
if ($form->isValid()) {}
$author = new Author();
$validator = $this->get('validator');
$errors = $validator->validate($author);
Dependency container
Standalone use
$email = ‘obama@usa.gov’;
$emailConstraint = new AssertEmail();
$emailConstraint->message = 'Invalid email address';
$errorList = $this->get('validator')->validate(
$email,
$emailConstraint
);
Creating new constraints
Constraint Validator
Validate
Constraint
class HasAvailableSeats extends Constraint
{
public $message = 'No {{ number }} available seats’;
protected $movie;
public function __construct($options)
{
$this->movie = $options['movie'];
}
public function getMovie()
{
return $this->movie;
}
public function validatedBy()
{
return get_class($this).'Validator';
}
}
No logic,
data that describes
the constraint
Who validates this?
class HasAvailableSeatsValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
$available = $constraint->getMovie()->getAvailableSeats();
if ($value > $available) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ number }}', $value)
->addViolation();
}
}
}
Validator
Validation logic
APIs
Up to level 2
Good use of HTTP verbs (GET, POST, PUT, DELETE, PATCH…)
Structure based on resources (/movies, /movies/31).
Use of HTTP Status codes (200, 201, 406, …).
Use of representations (JSON, XML, …).
Serializer: the idea
$recipe = new Recipe();
$recipe->setName($content['name']);
$recipe->setEnergy($content['energy']);
$recipe->setServings($content['servings']);
Request->Our object (manual deserialization)
$responseData = [
   'id' => $recipe->getId(),
   'name' => $recipe->getName(),
   'energy' => $recipe->getEnergy(),
   'servings' => $recipe->getServings(),
   ];
$response = new JsonResponse($responseData, 201);
Our object->Request (manual serialization)
Tedious!
$response = new Response($serializer->serialize($recipe, 'json'), 201);
$responseData = [
   'id' => $recipe->getId(),
   'name' => $recipe->getName(),
   'energy' => $recipe->getEnergy(),
   'servings' => $recipe->getServings(),
   ];
$response = new JsonResponse($responseData, 201);
Our object->Request (manual serialization)
Serialize
$recipe = $serializer->deserialize($content, Recipe::class, 'json');
$recipe = new Recipe();
$recipe->setName($content['name']);
$recipe->setEnergy($content['energy']);
$recipe->setServings($content['servings']);
Request->Our object (manual deserialization)
Deserialize
Serializer
Representation in API != DB
{
id: 9,
name: "victoriaq",
password: "encryptedPassword",
email: "victoria@limenius.com",
avatar: "avatar.jpg",
twitter_handler: "vicqr",
profile: {
id: 19,
bio: "My bio."
}
}
I want this to be “username”
I don’t want to expose it!
Only in profile, not in list
We want to prepend “thumb_”
Only in version 2 of the API
I’d like this to be bio:”My bio”
We do this in the normalizer
Annotations
MaxDepth
• Detect and limit the serialization depth
• Especially useful when serializing large trees
Groups
• Sometimes, you want to serialize different sets of attributes from your entities
• Groups are a handy way to achieve this need
API Platform makes it very easy
Admin Panel
Admin on REST with API Platform
Sonata Admin
Easy Admin
Thanks! @nacmartin
nacho@limenius.com
@vicqr
victoria@limenius.com

More Related Content

What's hot

Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Stephan Hochdörfer
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
James Titcumb
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
Marcin Czarnecki
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with Twig
Ryan Weaver
 
Actions filters
Actions filtersActions filters
Actions filters
John Dillick
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD tests
Stefan Adolf
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
James Titcumb
 
Getting big without getting fat, in perl
Getting big without getting fat, in perlGetting big without getting fat, in perl
Getting big without getting fat, in perl
Dean Hamstead
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
James Titcumb
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoComplete
IsaacSchlueter
 
TWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHPTWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHP
Cesare D'Amico
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
Jeremy Kendall
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceJesse Vincent
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
Dave Cross
 
CSS in React - Will Change Transform
CSS in React - Will Change TransformCSS in React - Will Change Transform
CSS in React - Will Change Transform
Joe Seifi
 

What's hot (19)

Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with Twig
 
Actions filters
Actions filtersActions filters
Actions filters
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD tests
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
 
Getting big without getting fat, in perl
Getting big without getting fat, in perlGetting big without getting fat, in perl
Getting big without getting fat, in perl
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoComplete
 
TWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHPTWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHP
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
CSS in React - Will Change Transform
CSS in React - Will Change TransformCSS in React - Will Change Transform
CSS in React - Will Change Transform
 

Similar to Symfony 4 Workshop - Limenius

The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
Lars Jankowfsky
 
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with MagentoMeet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Kristof Ringleff
 
Things to consider for testable Code
Things to consider for testable CodeThings to consider for testable Code
Things to consider for testable Code
Frank Kleine
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
Jakub Zalas
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Exampleliufabin 66688
 
Growing up with Magento
Growing up with MagentoGrowing up with Magento
Growing up with Magento
Kristof Ringleff
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
Fwdays
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
Yonni Mendes
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
Ross Bruniges
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Javier Eguiluz
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
Sébastien Houzé
 
Javascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularJavascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & Angular
Erik Guzman
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
Javier Eguiluz
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)Oleg Zinchenko
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
Ryunosuke SATO
 

Similar to Symfony 4 Workshop - Limenius (20)

The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with MagentoMeet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
 
Things to consider for testable Code
Things to consider for testable CodeThings to consider for testable Code
Things to consider for testable Code
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Example
 
Growing up with Magento
Growing up with MagentoGrowing up with Magento
Growing up with Magento
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Javascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularJavascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & Angular
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 

More from Ignacio Martín

Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
Ignacio Martín
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
Ignacio Martín
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHP
Ignacio Martín
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
Ignacio Martín
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
Ignacio Martín
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
Ignacio Martín
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWT
Ignacio Martín
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
Ignacio Martín
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
Ignacio Martín
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
Ignacio Martín
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Ignacio Martín
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your Projects
Ignacio Martín
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
Symfony 2 CMF
Symfony 2 CMFSymfony 2 CMF
Symfony 2 CMF
Ignacio Martín
 
Doctrine2 sf2Vigo
Doctrine2 sf2VigoDoctrine2 sf2Vigo
Doctrine2 sf2Vigo
Ignacio Martín
 
Presentacion git
Presentacion gitPresentacion git
Presentacion git
Ignacio Martín
 

More from Ignacio Martín (17)

Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHP
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWT
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your Projects
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Symfony 2 CMF
Symfony 2 CMFSymfony 2 CMF
Symfony 2 CMF
 
Doctrine2 sf2Vigo
Doctrine2 sf2VigoDoctrine2 sf2Vigo
Doctrine2 sf2Vigo
 
Presentacion git
Presentacion gitPresentacion git
Presentacion git
 

Recently uploaded

Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 

Recently uploaded (20)

Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 

Symfony 4 Workshop - Limenius

  • 1. Symfony 4 Workshop Victoria Quirante - @vicqr Nacho Martin - @nacmartin Notes: http://symfony4.limenius.com/
  • 2. Nacho Martín @nacmartin nacho@limenius.com Victoria Quirante @vicqr victoria@limenius.com We build tailor-made projects with Symfony and React We have been working with Symfony since 2008 We provide development, consulting and training
  • 5. Symfony Evolution Symfony 12005 A monolith (very different) Symfony 22011 Components appear
  • 6. Components used in popular projects
  • 10. Symfony Evolution Symfony 12005 A monolith (very different) Symfony 22011 Components appear Symfony 32015 Brief intermediate step Symfony 42017 Compose your apps
  • 11. Symfony 2/3 SF 2 Web app SF 2 API SF 2 Microservice SF 4 Web app SF4 API SF4 Microservice Symfony 4
  • 12. Symfony 4 SF4 SF 4 Web app SF4 API SF4 Microservice We need something to smooth out these transformations
  • 14. Symfony Flex is a tool to implement Symfony 4 philosophy
  • 15. It is a composer plugin that comes with Symfony 4 The idea is automation to the max when installing and configuring packages
  • 16. Modifies the behaviour of the require and update commands Allows Symfony to perform tasks before or after the composer commands
  • 17. Symfony 4 Your application with Symfony Flex composer req mailer Symfony Flex Server Recipe? No Regular install With composer
  • 18. Symfony 4 Your application with Symfony Flex composer req mailer Symfony Flex Server Recipe? Yes Install them With composer Follow recipe instructions Decide which packages to install Run any task to configure them
  • 20. Directory Structure my-project/ ├── config/ │   ├── bundles.php │   ├── packages/ │   ├── routes.yaml │   └── services.yaml ├── public/ │   └── index.php ├── src/ │   ├── ... │   └── Kernel.php ├── templates/ └── vendor/
  • 23. Entity namespace AppEntity; class Movie { private $id; private $name; private $director; private $year; private $picture; }
  • 24. Entity /** * @ORMEntity() * @ORMTable(name="movie") */ class Movie { /** * @ORMColumn(type="integer") * @ORMId * @ORMGeneratedValue(strategy="AUTO") */ private $id; /** * @ORMColumn(type="string") */ private $name; /** * @ORMColumn(type="string", length=100) */ private $director; /** * @ORMColumn(type="smallint") */ private $year; /** * @ORMColumn(type="string") */ private $picture; }
  • 25. Entity Code that has to do with the model itself. Doesn’t depend on services, or query the DB.
  • 26. Accessors In this workshop we are going to use setters and getters: •getDirector() •setDirector() This is not the only way. See for instance: http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/
  • 28. Entity Manager $em = $this->getDoctrine()->getManager(); $em->getRepository(Movie::class)->find($movieId); $em = $this->getDoctrine()->getManager(); $em->persist($sale); $em->flush();
  • 29. Doctrine Query Language (DQL) $em = $this->getDoctrine()->getManager(); $query = $em->createQuery( 'SELECT m, a FROM App:Movie m LEFT JOIN m.actors a WHERE m.id = :id' )->setParameter('id', $movieId); $movie = $query->getOneOrNullResult();
  • 30. Query Builder $em = $this->getDoctrine()->getManager(); $query = $em->getRepository(Movie::class) ->createQueryBuilder('m') ->select('m, a') ->leftJoin('m.actors', 'a') ->where('m.id = :id') ->setParameter('id', $movieId) ->getQuery(); $movie = $query->getOneOrNullResult();
  • 31. Entity Manager Code that deals with retrieving or persisting entities.
  • 33. We could do this for ($i = 0; $i < 10; $i ++) { $movie = new Movie(); $movie->setYear(1994); $movie->setName('Pulp Fiction'.$i); //... $em->persist($movie); } $em->flush();
  • 34. With Alice AppEntityMovie: movie{1..10}: name: '<sentence(4, true)>' director: '<name()>' year: '<numberBetween(1970, 2017)>' picture: '<image("./public/images", 500, 500, "cats", false)>' See all the generators in https://github.com/fzaninotto/Faker
  • 36. Twig
  • 37. Twig {{ }} {% %} Display Data Define Structures
  • 38. Access variables {{ foo }} {{ foo.bar }} {{ foo['bar'] }}
  • 39. - Checks if foo is an array and bar an element - If not, checks if foo is an object and bar a property - If not, checks if foo is an object and bar a method - If not, checks if foo is an object and getBar a method - If not, checks if foo is an object and isBar a method {{ foo.bar }} Access variables
  • 40. {% for user in users %} {{ user.username }} {% endfor %} For each
  • 41. {% for i in 0..10 %} {{ i }} {% endfor %} For
  • 42. For … else {% for item in items %} {{ item }} {% else %} No items. {% endfor %}
  • 43. <html><head>...</head> <body> <h1> {% block title %}{% endblock %} </h1> {% block body %}{% endblock %} </body></html> Template inheritance templates/layout.html.twig
  • 44. {% extends "layout.twig" %} {% block title %} Home {% endblock %} {% block body %} Lorem ipsum... {% endblock %} Template inheritance templates/home.html.twig
  • 45. {% extends "layout.twig" %} {% block title %} Movie list {% endblock %} {% block body %} Duis aute irure dolor in.. {% endblock %} Template inheritance templates/movies.html.twig
  • 48. Webpack The standard nowadays. Very powerful. Steep learning curve. Cons Pros
  • 49. Webpack Encore A wrapper around Webpack that makes it easier to set up. It solves a big % of cases. If you require something specific, you can still use Webpack without Encore.
  • 50. Forms
  • 51. Create a form $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, ['label' => 'Create Post']) ->getForm(); return $this->render('default/new.html.twig', [ 'form' => $form->createView(), ]);
  • 52. Forms in Twig {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} You can customise a lot the rendering of every widget, If you need to.
  • 53. Handle submission $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, ['label' => 'Create Task']) ->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); $em->flush(); return $this->redirectToRoute('task_success'); } return $this->render('default/new.html.twig', [ 'form' => $form->createView(), ]);
  • 54. Forms in their own classes class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->add('save', SubmitType::class); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => Task::class, )); } }
  • 56. Event and EventListener Event EventListener dispatch
  • 57. Event class SaleEvent extends Event { const NAME = 'sale.created'; protected $sale; protected $movie; protected $numTickets; public function __construct(Sale $sale, Movie $movie, int $numTickets) { $this->sale = $sale; $this->movie = $movie; $this->numTickets = $numTickets; } public function getSale() { return $this->sale; } public function getMovie() { return $this->movie; } public function getNumTickets() { return $this->numTickets; } } A bag of parameters that describe the event
  • 59. EventListener Processes the event class SaleListener { public function __construct(EntityManager $em) { $this->em = $em; } public function onSaleCreated(SaleEvent $event) { for ($i = 0; $i < $event->getNumTickets(); $i++) { $ticket = new Ticket(); $ticket->setMovie($event->getMovie()); $ticket->setSale($event->getSale()); $ticket->setRow(1); $ticket->setSeat(1); $this->em->persist($ticket); } } }
  • 61. Services A service is an object that does something: • Generate a thumbnail. • Generate a PDF. • A query to ElasticSearch. • Log something. • Send an email.
  • 62. Example class SaleLogger { private $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function log(Sale $sale) { $this->logger->info('Sold ' . count($sale->getTickets()) . ' tickets to ' . $sale->getFullName()); } } Where does this come from?
  • 63. Using services public function listAction(SaleLogger $saleLogger) { //… $saleLogger->log($sale); } Is injected with dependencies
  • 64. Explicit configuration # app/config/services.yml services: # explicitly configure the service AppLoggerSaleLogger: arguments: $logger: '@monolog.logger.request'
  • 65. Tagged services $taggedServices = $container->findTaggedServiceIds(‘app.my_tag’); foreach ($taggedServices as $id => $tags) { $definition->addMethodCall('callAMethod', array(new Reference($id))); } AppMyServices: resource: '../src/MyServices' tags: ['app.my_tag']
  • 67. Built in assertions /** * @ORMColumn(type="string") * @AssertLength(min=2) */ private $fullName; /** * @ORMColumn(type="string") * @AssertEmail() */ private $email; /** * @ORMColumn(type="text") * @AssertLength(max=100) */ private $question;
  • 68. Built in assertions There are 47 assertions From NotNull to Isbn And we can write our own assertions
  • 69. Use validators if ($form->isValid()) {} $author = new Author(); $validator = $this->get('validator'); $errors = $validator->validate($author); Dependency container
  • 70. Standalone use $email = ‘obama@usa.gov’; $emailConstraint = new AssertEmail(); $emailConstraint->message = 'Invalid email address'; $errorList = $this->get('validator')->validate( $email, $emailConstraint );
  • 72. Constraint class HasAvailableSeats extends Constraint { public $message = 'No {{ number }} available seats’; protected $movie; public function __construct($options) { $this->movie = $options['movie']; } public function getMovie() { return $this->movie; } public function validatedBy() { return get_class($this).'Validator'; } } No logic, data that describes the constraint Who validates this?
  • 73. class HasAvailableSeatsValidator extends ConstraintValidator { public function validate($value, Constraint $constraint) { $available = $constraint->getMovie()->getAvailableSeats(); if ($value > $available) { $this->context->buildViolation($constraint->message) ->setParameter('{{ number }}', $value) ->addViolation(); } } } Validator Validation logic
  • 74. APIs
  • 75.
  • 76. Up to level 2 Good use of HTTP verbs (GET, POST, PUT, DELETE, PATCH…) Structure based on resources (/movies, /movies/31). Use of HTTP Status codes (200, 201, 406, …). Use of representations (JSON, XML, …).
  • 77. Serializer: the idea $recipe = new Recipe(); $recipe->setName($content['name']); $recipe->setEnergy($content['energy']); $recipe->setServings($content['servings']); Request->Our object (manual deserialization) $responseData = [    'id' => $recipe->getId(),    'name' => $recipe->getName(),    'energy' => $recipe->getEnergy(),    'servings' => $recipe->getServings(),    ]; $response = new JsonResponse($responseData, 201); Our object->Request (manual serialization) Tedious!
  • 78. $response = new Response($serializer->serialize($recipe, 'json'), 201); $responseData = [    'id' => $recipe->getId(),    'name' => $recipe->getName(),    'energy' => $recipe->getEnergy(),    'servings' => $recipe->getServings(),    ]; $response = new JsonResponse($responseData, 201); Our object->Request (manual serialization) Serialize
  • 79. $recipe = $serializer->deserialize($content, Recipe::class, 'json'); $recipe = new Recipe(); $recipe->setName($content['name']); $recipe->setEnergy($content['energy']); $recipe->setServings($content['servings']); Request->Our object (manual deserialization) Deserialize
  • 81. Representation in API != DB { id: 9, name: "victoriaq", password: "encryptedPassword", email: "victoria@limenius.com", avatar: "avatar.jpg", twitter_handler: "vicqr", profile: { id: 19, bio: "My bio." } } I want this to be “username” I don’t want to expose it! Only in profile, not in list We want to prepend “thumb_” Only in version 2 of the API I’d like this to be bio:”My bio” We do this in the normalizer
  • 82. Annotations MaxDepth • Detect and limit the serialization depth • Especially useful when serializing large trees Groups • Sometimes, you want to serialize different sets of attributes from your entities • Groups are a handy way to achieve this need
  • 83. API Platform makes it very easy
  • 85. Admin on REST with API Platform