SlideShare a Scribd company logo
WORKING WITH SYMFONY2
MODELS IN THE FRONT-END
(USING JAVASCRIPT)
By / RedNose LeidenSven Hagemann
ABOUT ME
SVEN CHRISTIAAN HAGEMANN (1986)
2009 until > 9000;
2004 until 2009;
2001 until 2004;
WHEN TO USE MODELS IN
THE FRONT-END?
AVARAGE GOVERNMENT COMPUTER BROWSER:
WHEN TO USE MODELS IN
THE FRONT-END?
When developing for a modern browser (>
IE8, FF 3.5)
When building a single page application
(SPA) for desktop
When building a single page application for
mobile devices
WHEN TO USE MODELS IN
THE FRONT-END?
HYBRID SITUATION
Endusers
(website front-end)
Administrators
(website back-end)
HTML / CSS - Twig Symfony2 Entities Fancy Javascript / HTML5
WHEN TO USE MODELS IN
THE FRONT-END?
FROM PROGRESSIVE ENHANCEMENT TO BUILDING
ACTUAL APPLICATIONS IN JAVASCRIPT
SunSpider 2001 until Q1-2009 Google Trends 2007 until 2014
SO WHY USE MODELS IN THE
FRONT-END?
MODERN WEBDEVELOPMENT PARADIGM
90's early 2000's Today
SO WHY USE MODELS IN THE
FRONT-END?
Code structure
Maintainability
Working in a team of front-end developers
Clear seperation between front and back-end (developers)
The front-end and back-end share a common data model
Stateful
Ability to synchronise state from and to the back-end
Less data usage. (Important for mobile devices)
Less server resources required
Ability to keep data client-side (HTML5 data storage for example)
Bonus: Free API!
RESTFul API supporting both XML and JSON
Import / Export entities to XML and JSON
Easy to migrate to newer versions of the data model
HOW DO STATEFUL
JAVASCRIPT MODELS WORK?
PSEUDO-CODE EXAMPLE: CREATING MODELS
//Model()isanobjectprovidedbysomeawesomejavascriptframework
varmodelProject =newModel({name:'Exampleproject'}),
modelTaskPrimary =newModel({name:'Makemeasandwich',ready:false}),
modelTaskSecondary=newModel({name:'Createworldpeace',ready:false});
//ChangetodoListproperty(calls.set()onModel())
modelProject.set('todoList',[modelTaskPrimary,modelTaskSecondary]);
//Registeracallbackurlforthismodel
modelProject.set('routes',{create:Routing.generate('project_create')});
//Persist(SendsaserializedJSONstringtoaRESTFulapiusingAJAX)
modelProject.save();
HOW DO STATEFUL
JAVASCRIPT MODELS WORK?
PSEUDO-CODE EXAMPLE: UPDATE MODEL
varmodelProject=newModel({
routes:{get:Routing.generate('project_get',{id:1337})}
});
//Model.load(callback)sendsahttpcalltothe'project_get'route.
//Ifallgoestoplan,werecieveaserializedJSONstring
modelProject.load(function(){
if(modelProject.get('todoList').length>0){
//Getthefirsttask
varmodelTodoTask=modelProject.get('todoList')[0];
//Changethenameofthetask(objectsareByRef).
//BecausetheIDofthistaskissetbytheload()itwillbe
//updatedwhensave()iscalled,otherwiseanewtaskwillbecreated.
modelTodoTask.set('name','SUDOMAKEMEASANDWICH!');
}
});
//...Dosomeotherstuff...
//Atsomeotherpointintime.
modelProject.save();
HOW DO STATEFUL
JAVASCRIPT MODELS WORK?
PSEUDO-CODE EXAMPLE: CLASS INHERITANCE
//Createprototypemodelobjectusinginheritance
varProjectModel=function(){
}
ProjectModel.prototype=newModel();
//Createareferencetotheobjectparentprototypeforsuperclasscalls.
ProjectModel.prototype.parent=Model.prototype;
//Overwriteget()
ProjectModel.prototype.get=function(name){
if(name==='routes'){
return{
create:Routing.generate('project_get'),
get:Routing.generate('project_get',{
id:this.parent.get.call(this,'id');
})
};
}
//Callget()onsuperclass
returnthis.parent.get.call(this,name);
}
HOW DO STATEFUL
JAVASCRIPT MODELS WORK?
PSEUDO-CODE EXAMPLE: BUSINESS LOGIC
//Createprototypemodelobjectusinginheritance
varProjectModel=function(){
}
ProjectModel.prototype=newModel();
/**
*Addsatask
*
*@param{string}name
*@return{void}
*/
ProjectModel.prototype.addTask=function(name){
vartodoModel =newModel({name:name,ready:false}),
todoModelList=this.get('todoList');
if(todoModelList===null){
todoModelList=[];
}
todoModelList.push(todoModel)
this.set('todoList',todoModelList);
}
REAL WORLD EXAMPLE
LIVE DEMO!
(NOTE TO SELF: PRAY TO DEMO-GODS)
CAN WE PLEASE TALK SOME
PHP NOW?
SYMFONY2 ENTITY
SERIALIZATION
THERE IS A BUNDLE FOR THAT!
Exposing your routes to JavaScript
FOSJsRoutingBundle
Make your entities automatically serialize
JMSSerializerBundle
Create a RESTFul API, the lazy .. ahum .. easy way
FOSRestBundle
EXPOSING YOUR ROUTES TO
JAVASCRIPT
/APP/CONFIG/ROUTING.YML
#IfyoucouldgoaheadandaddthecovertotheTPSreportsthatwouldbeterrific
add_cover_to_tps_report:
pattern:/tps_report/add_cover/{reportId}
defaults:{_controller:OfficeSpaceTpsBundle:Reports:addCover}
#Theimportantpart
options:
expose:true
FOSRoutingBundle provides Routing.generate();
Generate a JSON object based on exposed routes
EXPOSING YOUR ROUTES TO
JAVASCRIPT
INCLUDING FOSJSROUTINGBUNDLE DEPENDENCIES IN
<HEADER />
<script
type="text/javascript"
src="{{asset('bundles/fosjsrouting/js/router.js')}}"
>
<script
type="text/javascript"
src="{{path('fos_js_routing_js',{"callback":"fos.Router.setData"})}}"
>
* Ignore the weird indenting
EXPOSING YOUR ROUTES TO
JAVASCRIPT
USAGE
varroute=Routing.generate(
'add_cover_to_tps_report',
{reportId:143}
);
alert(route);
Adding annotations to your existing entities
http://jmsyst.com/libs/serializer/master/reference/annotations
MAKE YOUR ENTITIES
SERIALIZABLE
JMSSERIALIZERBUNDLE ANNOTATIONS
useRednoseTodoBundleModelTaskasBaseTask;
//AnnotationclassprovidedbytheJMSSerializerBundle
useJMSSerializerAnnotationasSerializer;
classTaskextendsBaseTask{
/**
*...
*...
*@SerializerType("boolean")
*@SerializerGroups({"details","file"})
*/
protected$ready=false;
}
MAKE YOUR ENTITIES
SERIALIZABLE
BASIC ENTITY ANNOTATING
useRednoseTodoBundleModelProjectasBaseProject;
useJMSSerializerAnnotationasSerializer;
/**
*@ORMEntity
*@ORMTable(name="todo_project")
*
*@SerializerXmlRoot("project")
*/
classProjectextendsBaseProject
{
/**
*@ORMId
*@ORMColumn(type="integer")
*@ORMGeneratedValue(strategy="AUTO")
*
*@SerializerXmlAttribute
*@SerializerGroups({"details"})
*/
protected$id;
/**
*@ORMColumn(type="string",length=255)
*
*@SerializerXmlAttribute
*@SerializerType("string")
*@SerializerGroups({"details","file"})
*/
protected$name;
//...................
MAKE YOUR ENTITIES
SERIALIZABLE
RELATIONAL ENTITIES
classProjectextendsBaseProject
{
/**
*@ORMOneToMany(
* targetEntity="Task",
* orphanRemoval=true,
* mappedBy="project",
* cascade={"persist","remove"})
*@ORMOrderBy({"id"="ASC"})
*
*@SerializerGroups({"details","file"})
*@SerializerSerializedName("tasks")
*@SerializerXmlList(inline=false,entry="task")
*/
protected$tasks;
/**
*Theserializerusesreflectiontocreateobjectsinsteadofsetters.Somakesureyourepair
*bi-directionalrelations,otherwisedoctrinewillremovethemwhenyoupersisttheparententity.
*
*@SerializerPostDeserialize
*/
publicfunctionpostDeserialize()
{
foreach($this->tasksas$task){
$task->setProject($this);
}
}
}
MAKE YOUR ENTITIES
SERIALIZABLE
DESERIALIZE AND PERSIST
useJMSSerializerDeserializationContext;
classProjectController{
functionupdateProjectActions(){
$em=$this->getDoctrine()->getManager();
$serializer=$this->get('jms_serializer');
$context=newDeserializationContext();
$context->setGroups(array('details'));
$project=$serializer->deserialize(
$this->getRequest()->getContent(), //TheJSONsendbyJavascript.
'RednoseTodoBundleEntityProject',//Baseentitynamespace.
'json',$context //Format=JSON,Context=details
);
$em->persist($project);
$em->flush();
}
}
MAKE YOUR ENTITIES
SERIALIZABLE
GOOD TO KNOW: EVENTLISTENERS
useJMSSerializerEventDispatcherEventSubscriberInterface;
useJMSSerializerEventDispatcherObjectEvent;
classEntityListenerimplementsEventSubscriberInterface
{
protected$user;
publicfunction__construct(ContainerInterface$container)
{
$this->user=$container->get('security.context')->getToken()->getUser();
}
staticpublicfunctiongetSubscribedEvents()
{
returnarray(
array(
'event'=>'serializer.post_deserialize',
'class'=>'RednoseTodoBundleEntityTask','method'=>'onPostDeserialize'
),
);
}
publicfunctiononPreSerialize(PreSerializeEvent$event)
{
$task=$event->getobject();
$task->setOwner($this->user);//Javascriptisnotawareofthesessionuser
}
}
Replacing the default ObjectConstructor
MAKE YOUR ENTITIES
SERIALIZABLE
GOOD TO KNOW: DOCTRINE OBJECTCONSTRUCTOR
If entities are not created using Doctrine they will not be referenced to the
existing entity in the database and therefore when persisted new entities will be
created.
But . . . . JMSSerializerBundle provides us a special ObjectConstructor to solve
this issue.
<containerxmlns="...">
<services>
<service
id="jms_serializer.object_constructor"
alias="jms_serializer.doctrine_object_constructor"public="false"
/>
</services>
</container>
The Symfony2 way: Convention over configuration is ,
there should at least be 19 ways to do the same thing.
Routing.yml
ProjectController.php
RESTFUL API THE EASY WAY
BASIC ROUTING ANNOTATIONS
stupid
todo_app:
resource:"@RednoseTodoBundle/Controller/"
type: annotation
prefix: /
useSensioBundleFrameworkExtraBundleConfigurationRoute;
/**
*@Route("/project/{projectId}",requirements={"id"="d+"},defaults={"id"=1})
*/
publicfunctiongetProjectAction($projectId)
{
returnnewResponse("Thesearenottheprojectsyou'relookingfor");
}
Configuration equals extendability:
RestBundle provides us with CRUD annotations
RESTFUL API THE EASY WAY
CRUD ROUTING ANNOTATIONS
convenient
useFOSRestBundleControllerAnnotationsGet;
useFOSRestBundleControllerAnnotationsPut;
/**
*Getallproject
*
*@Get("/projects",name="todo_app_projects_read",options={"expose"=true})
*
*@returnJsonResponse
*/
publicfunctionreadProjectsActions(){/*...*/}
/**
*Updateaproject
*
*@Put("/project",name="todo_app_project_update",options={"expose"=true})
*
*@returnResponse
*/
publicfunctionupdateProjectActions(){/*...*/}
Using @GET and @POST routes in your docblocks will create a self-documenting API !
RESTFUL API THE EASY WAY
RESTBUNDLE VIEW AND VIEWHANDLER
RESTFUL API THE EASY WAY
RESTBUNDLE AND SERIALIZERBUNDLE ARE FRIENDS
namespaceRednoseTodoBundleCommon;
useJMSSerializerSerializationContext;
useFOSRestBundleViewView;
useSymfonyBundleFrameworkBundleControllerControllerasBaseController;
classControllerextendsBaseController
{
/**
*Createaxmlorjsonviewbasedonthegivenentity
*
*@paramstring $format Validoptionsare:json|xml
*@paramarray $groups Theserializercontextgroup(s)
*@parammixed $entity
*@returnResponse
*/
functiongetView($format,$groups,$entity)
{
$handler=$this->get('fos_rest.view_handler');
$view =newView();
$context=newSerializationContext();
$context->setGroups($groups);
$view->setSerializationContext($context);
$view->setData($entity);
$view->setFormat($format);
return$handler->handle($view);
}
}
RedNose
sven@rednose.nl
https://github.com/SavageTiger/Todo-App-Demo
QUESTIONS ?

More Related Content

Similar to Working with symfony2 models in the front end

Javaland 2014 / GWT architectures and lessons learned
Javaland 2014 / GWT architectures and lessons learnedJavaland 2014 / GWT architectures and lessons learned
Javaland 2014 / GWT architectures and lessons learned
pgt technology scouting GmbH
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
SharePoint Conference North America - Converting your JavaScript to SPFX
SharePoint Conference North America - Converting your JavaScript to SPFXSharePoint Conference North America - Converting your JavaScript to SPFX
SharePoint Conference North America - Converting your JavaScript to SPFX
Mark Rackley
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
Fwdays
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
Jady Yang
 
Java - A broad introduction
Java - A broad introductionJava - A broad introduction
Java - A broad introduction
Birol Efe
 
Asynchronous Module Definition (AMD)
Asynchronous Module Definition (AMD)Asynchronous Module Definition (AMD)
Asynchronous Module Definition (AMD)
xMartin12
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
intelliyole
 
Building a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one weekBuilding a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one week
Dr. Felix Raab
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
Haehnchen
 
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
Codemotion
 
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
NodeJS for Novices - 28/Oct/13 - Winnipeg, MBNodeJS for Novices - 28/Oct/13 - Winnipeg, MB
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
David Wesst
 
TPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and FluxTPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and Flux
Jirat Kijlerdpornpailoj
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
Jose Manuel Pereira Garcia
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson
GWTcon
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Ondřej Machulda
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
Anis Ahmad
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
Christian Heilmann
 
[2015/2016] JavaScript
[2015/2016] JavaScript[2015/2016] JavaScript
[2015/2016] JavaScript
Ivano Malavolta
 

Similar to Working with symfony2 models in the front end (20)

Javaland 2014 / GWT architectures and lessons learned
Javaland 2014 / GWT architectures and lessons learnedJavaland 2014 / GWT architectures and lessons learned
Javaland 2014 / GWT architectures and lessons learned
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
SharePoint Conference North America - Converting your JavaScript to SPFX
SharePoint Conference North America - Converting your JavaScript to SPFXSharePoint Conference North America - Converting your JavaScript to SPFX
SharePoint Conference North America - Converting your JavaScript to SPFX
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
 
Java - A broad introduction
Java - A broad introductionJava - A broad introduction
Java - A broad introduction
 
Asynchronous Module Definition (AMD)
Asynchronous Module Definition (AMD)Asynchronous Module Definition (AMD)
Asynchronous Module Definition (AMD)
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Building a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one weekBuilding a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one week
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
 
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
NodeJS for Novices - 28/Oct/13 - Winnipeg, MBNodeJS for Novices - 28/Oct/13 - Winnipeg, MB
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
 
TPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and FluxTPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and Flux
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
[2015/2016] JavaScript
[2015/2016] JavaScript[2015/2016] JavaScript
[2015/2016] JavaScript
 

Recently uploaded

Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
Neo4j
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
LizaNolte
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
Javier Junquera
 
ScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking ReplicationScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking Replication
ScyllaDB
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
Safe Software
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
Fwdays
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
Principle of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptxPrinciple of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptx
BibashShahi
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
Ivo Velitchkov
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
christinelarrosa
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Neo4j
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
ScyllaDB
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
Antonios Katsarakis
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
UiPathCommunity
 

Recently uploaded (20)

Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
 
ScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking ReplicationScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking Replication
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
Principle of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptxPrinciple of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptx
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
 

Working with symfony2 models in the front end

  • 1. WORKING WITH SYMFONY2 MODELS IN THE FRONT-END (USING JAVASCRIPT) By / RedNose LeidenSven Hagemann
  • 2. ABOUT ME SVEN CHRISTIAAN HAGEMANN (1986) 2009 until > 9000; 2004 until 2009; 2001 until 2004;
  • 3. WHEN TO USE MODELS IN THE FRONT-END? AVARAGE GOVERNMENT COMPUTER BROWSER:
  • 4. WHEN TO USE MODELS IN THE FRONT-END? When developing for a modern browser (> IE8, FF 3.5) When building a single page application (SPA) for desktop When building a single page application for mobile devices
  • 5. WHEN TO USE MODELS IN THE FRONT-END? HYBRID SITUATION Endusers (website front-end) Administrators (website back-end) HTML / CSS - Twig Symfony2 Entities Fancy Javascript / HTML5
  • 6. WHEN TO USE MODELS IN THE FRONT-END? FROM PROGRESSIVE ENHANCEMENT TO BUILDING ACTUAL APPLICATIONS IN JAVASCRIPT SunSpider 2001 until Q1-2009 Google Trends 2007 until 2014
  • 7. SO WHY USE MODELS IN THE FRONT-END? MODERN WEBDEVELOPMENT PARADIGM 90's early 2000's Today
  • 8. SO WHY USE MODELS IN THE FRONT-END? Code structure Maintainability Working in a team of front-end developers Clear seperation between front and back-end (developers) The front-end and back-end share a common data model Stateful Ability to synchronise state from and to the back-end Less data usage. (Important for mobile devices) Less server resources required Ability to keep data client-side (HTML5 data storage for example) Bonus: Free API! RESTFul API supporting both XML and JSON Import / Export entities to XML and JSON Easy to migrate to newer versions of the data model
  • 9. HOW DO STATEFUL JAVASCRIPT MODELS WORK? PSEUDO-CODE EXAMPLE: CREATING MODELS //Model()isanobjectprovidedbysomeawesomejavascriptframework varmodelProject =newModel({name:'Exampleproject'}), modelTaskPrimary =newModel({name:'Makemeasandwich',ready:false}), modelTaskSecondary=newModel({name:'Createworldpeace',ready:false}); //ChangetodoListproperty(calls.set()onModel()) modelProject.set('todoList',[modelTaskPrimary,modelTaskSecondary]); //Registeracallbackurlforthismodel modelProject.set('routes',{create:Routing.generate('project_create')}); //Persist(SendsaserializedJSONstringtoaRESTFulapiusingAJAX) modelProject.save();
  • 10. HOW DO STATEFUL JAVASCRIPT MODELS WORK? PSEUDO-CODE EXAMPLE: UPDATE MODEL varmodelProject=newModel({ routes:{get:Routing.generate('project_get',{id:1337})} }); //Model.load(callback)sendsahttpcalltothe'project_get'route. //Ifallgoestoplan,werecieveaserializedJSONstring modelProject.load(function(){ if(modelProject.get('todoList').length>0){ //Getthefirsttask varmodelTodoTask=modelProject.get('todoList')[0]; //Changethenameofthetask(objectsareByRef). //BecausetheIDofthistaskissetbytheload()itwillbe //updatedwhensave()iscalled,otherwiseanewtaskwillbecreated. modelTodoTask.set('name','SUDOMAKEMEASANDWICH!'); } }); //...Dosomeotherstuff... //Atsomeotherpointintime. modelProject.save();
  • 11. HOW DO STATEFUL JAVASCRIPT MODELS WORK? PSEUDO-CODE EXAMPLE: CLASS INHERITANCE //Createprototypemodelobjectusinginheritance varProjectModel=function(){ } ProjectModel.prototype=newModel(); //Createareferencetotheobjectparentprototypeforsuperclasscalls. ProjectModel.prototype.parent=Model.prototype; //Overwriteget() ProjectModel.prototype.get=function(name){ if(name==='routes'){ return{ create:Routing.generate('project_get'), get:Routing.generate('project_get',{ id:this.parent.get.call(this,'id'); }) }; } //Callget()onsuperclass returnthis.parent.get.call(this,name); }
  • 12. HOW DO STATEFUL JAVASCRIPT MODELS WORK? PSEUDO-CODE EXAMPLE: BUSINESS LOGIC //Createprototypemodelobjectusinginheritance varProjectModel=function(){ } ProjectModel.prototype=newModel(); /** *Addsatask * *@param{string}name *@return{void} */ ProjectModel.prototype.addTask=function(name){ vartodoModel =newModel({name:name,ready:false}), todoModelList=this.get('todoList'); if(todoModelList===null){ todoModelList=[]; } todoModelList.push(todoModel) this.set('todoList',todoModelList); }
  • 14. LIVE DEMO! (NOTE TO SELF: PRAY TO DEMO-GODS)
  • 15. CAN WE PLEASE TALK SOME PHP NOW?
  • 16. SYMFONY2 ENTITY SERIALIZATION THERE IS A BUNDLE FOR THAT! Exposing your routes to JavaScript FOSJsRoutingBundle Make your entities automatically serialize JMSSerializerBundle Create a RESTFul API, the lazy .. ahum .. easy way FOSRestBundle
  • 17. EXPOSING YOUR ROUTES TO JAVASCRIPT /APP/CONFIG/ROUTING.YML #IfyoucouldgoaheadandaddthecovertotheTPSreportsthatwouldbeterrific add_cover_to_tps_report: pattern:/tps_report/add_cover/{reportId} defaults:{_controller:OfficeSpaceTpsBundle:Reports:addCover} #Theimportantpart options: expose:true
  • 18. FOSRoutingBundle provides Routing.generate(); Generate a JSON object based on exposed routes EXPOSING YOUR ROUTES TO JAVASCRIPT INCLUDING FOSJSROUTINGBUNDLE DEPENDENCIES IN <HEADER /> <script type="text/javascript" src="{{asset('bundles/fosjsrouting/js/router.js')}}" > <script type="text/javascript" src="{{path('fos_js_routing_js',{"callback":"fos.Router.setData"})}}" > * Ignore the weird indenting
  • 19. EXPOSING YOUR ROUTES TO JAVASCRIPT USAGE varroute=Routing.generate( 'add_cover_to_tps_report', {reportId:143} ); alert(route);
  • 20. Adding annotations to your existing entities http://jmsyst.com/libs/serializer/master/reference/annotations MAKE YOUR ENTITIES SERIALIZABLE JMSSERIALIZERBUNDLE ANNOTATIONS useRednoseTodoBundleModelTaskasBaseTask; //AnnotationclassprovidedbytheJMSSerializerBundle useJMSSerializerAnnotationasSerializer; classTaskextendsBaseTask{ /** *... *... *@SerializerType("boolean") *@SerializerGroups({"details","file"}) */ protected$ready=false; }
  • 21. MAKE YOUR ENTITIES SERIALIZABLE BASIC ENTITY ANNOTATING useRednoseTodoBundleModelProjectasBaseProject; useJMSSerializerAnnotationasSerializer; /** *@ORMEntity *@ORMTable(name="todo_project") * *@SerializerXmlRoot("project") */ classProjectextendsBaseProject { /** *@ORMId *@ORMColumn(type="integer") *@ORMGeneratedValue(strategy="AUTO") * *@SerializerXmlAttribute *@SerializerGroups({"details"}) */ protected$id; /** *@ORMColumn(type="string",length=255) * *@SerializerXmlAttribute *@SerializerType("string") *@SerializerGroups({"details","file"}) */ protected$name; //...................
  • 22. MAKE YOUR ENTITIES SERIALIZABLE RELATIONAL ENTITIES classProjectextendsBaseProject { /** *@ORMOneToMany( * targetEntity="Task", * orphanRemoval=true, * mappedBy="project", * cascade={"persist","remove"}) *@ORMOrderBy({"id"="ASC"}) * *@SerializerGroups({"details","file"}) *@SerializerSerializedName("tasks") *@SerializerXmlList(inline=false,entry="task") */ protected$tasks; /** *Theserializerusesreflectiontocreateobjectsinsteadofsetters.Somakesureyourepair *bi-directionalrelations,otherwisedoctrinewillremovethemwhenyoupersisttheparententity. * *@SerializerPostDeserialize */ publicfunctionpostDeserialize() { foreach($this->tasksas$task){ $task->setProject($this); } } }
  • 23. MAKE YOUR ENTITIES SERIALIZABLE DESERIALIZE AND PERSIST useJMSSerializerDeserializationContext; classProjectController{ functionupdateProjectActions(){ $em=$this->getDoctrine()->getManager(); $serializer=$this->get('jms_serializer'); $context=newDeserializationContext(); $context->setGroups(array('details')); $project=$serializer->deserialize( $this->getRequest()->getContent(), //TheJSONsendbyJavascript. 'RednoseTodoBundleEntityProject',//Baseentitynamespace. 'json',$context //Format=JSON,Context=details ); $em->persist($project); $em->flush(); } }
  • 24. MAKE YOUR ENTITIES SERIALIZABLE GOOD TO KNOW: EVENTLISTENERS useJMSSerializerEventDispatcherEventSubscriberInterface; useJMSSerializerEventDispatcherObjectEvent; classEntityListenerimplementsEventSubscriberInterface { protected$user; publicfunction__construct(ContainerInterface$container) { $this->user=$container->get('security.context')->getToken()->getUser(); } staticpublicfunctiongetSubscribedEvents() { returnarray( array( 'event'=>'serializer.post_deserialize', 'class'=>'RednoseTodoBundleEntityTask','method'=>'onPostDeserialize' ), ); } publicfunctiononPreSerialize(PreSerializeEvent$event) { $task=$event->getobject(); $task->setOwner($this->user);//Javascriptisnotawareofthesessionuser } }
  • 25. Replacing the default ObjectConstructor MAKE YOUR ENTITIES SERIALIZABLE GOOD TO KNOW: DOCTRINE OBJECTCONSTRUCTOR If entities are not created using Doctrine they will not be referenced to the existing entity in the database and therefore when persisted new entities will be created. But . . . . JMSSerializerBundle provides us a special ObjectConstructor to solve this issue. <containerxmlns="..."> <services> <service id="jms_serializer.object_constructor" alias="jms_serializer.doctrine_object_constructor"public="false" /> </services> </container>
  • 26. The Symfony2 way: Convention over configuration is , there should at least be 19 ways to do the same thing. Routing.yml ProjectController.php RESTFUL API THE EASY WAY BASIC ROUTING ANNOTATIONS stupid todo_app: resource:"@RednoseTodoBundle/Controller/" type: annotation prefix: / useSensioBundleFrameworkExtraBundleConfigurationRoute; /** *@Route("/project/{projectId}",requirements={"id"="d+"},defaults={"id"=1}) */ publicfunctiongetProjectAction($projectId) { returnnewResponse("Thesearenottheprojectsyou'relookingfor"); }
  • 27. Configuration equals extendability: RestBundle provides us with CRUD annotations RESTFUL API THE EASY WAY CRUD ROUTING ANNOTATIONS convenient useFOSRestBundleControllerAnnotationsGet; useFOSRestBundleControllerAnnotationsPut; /** *Getallproject * *@Get("/projects",name="todo_app_projects_read",options={"expose"=true}) * *@returnJsonResponse */ publicfunctionreadProjectsActions(){/*...*/} /** *Updateaproject * *@Put("/project",name="todo_app_project_update",options={"expose"=true}) * *@returnResponse */ publicfunctionupdateProjectActions(){/*...*/} Using @GET and @POST routes in your docblocks will create a self-documenting API !
  • 28. RESTFUL API THE EASY WAY RESTBUNDLE VIEW AND VIEWHANDLER
  • 29. RESTFUL API THE EASY WAY RESTBUNDLE AND SERIALIZERBUNDLE ARE FRIENDS namespaceRednoseTodoBundleCommon; useJMSSerializerSerializationContext; useFOSRestBundleViewView; useSymfonyBundleFrameworkBundleControllerControllerasBaseController; classControllerextendsBaseController { /** *Createaxmlorjsonviewbasedonthegivenentity * *@paramstring $format Validoptionsare:json|xml *@paramarray $groups Theserializercontextgroup(s) *@parammixed $entity *@returnResponse */ functiongetView($format,$groups,$entity) { $handler=$this->get('fos_rest.view_handler'); $view =newView(); $context=newSerializationContext(); $context->setGroups($groups); $view->setSerializationContext($context); $view->setData($entity); $view->setFormat($format); return$handler->handle($view); } }