SlideShare une entreprise Scribd logo
1  sur  30
Télécharger pour lire hors ligne
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 ?

Contenu connexe

Similaire à 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 learnedpgt 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 SPFXMark 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 DukhinFwdays
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application FrameworkJady Yang
 
Java - A broad introduction
Java - A broad introductionJava - A broad introduction
Java - A broad introductionBirol 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 DSLsintelliyole
 
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 weekDr. Felix Raab
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.jsBert 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 laterHaehnchen
 
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, MBDavid 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 FluxJirat 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 NelsonGWTcon
 
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 RubyAnis Ahmad
 

Similaire à 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
 

Dernier

Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 

Dernier (20)

Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 

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); } }