Upload
sampetruda
View
3.750
Download
0
Embed Size (px)
Citation preview
Server-Side,PHP-Generated AJAX
Mike Ho, Quasidea Development
Zend/PHP ConferenceThursday, October 22, 2009
Soli Deo GloriaJohn 3:16 • Romans 12
Thursday, October 22, 2009
a bit about me...
• Quasidea Development
• 10+ years of IT consulting experience
• Lead Developer,Qcodo Development Framework
Thursday, October 22, 2009
a bit about you...
• Developers vs. Others
• AJAX
• Frameworks
Thursday, October 22, 2009
a bit of history...
• PHP 3 and PHP 4
Database
PHP
Thursday, October 22, 2009
a bit of history...
• PHP 3 and PHP 4
• PHP 5, ORM and frameworks
Database
PHP View / Controller
PHP Model / ORM
Thursday, October 22, 2009
a bit of history...
• PHP 3 and PHP 4
• PHP 5, ORM and frameworks
• PHP with client-side AJAX
Database
PHP View / Controller
JavaScript
PHP Model / ORM
Thursday, October 22, 2009
old school examples
• 3 Files Required
• HTML page
• Data provider (e.g. a PHP webservice that generates XML or JSON)
• Client JavaScript(webservice client anda response handler)
Thursday, October 22, 2009
something with a bit more data...
• Even though this is a more sophisticated page, the three-file minimum stays the same:HTML File, Data WebService and Client JavaScript
Thursday, October 22, 2009
java pseudo script!var summary = document.getElementById("summary").value;
var status = document.getElementById("status").value;
// etc...
XmlRpcCall("http://server/get_issues?sm=" + summary + "&st=" + status + etc...,
"filterIssuesListCallback");
function filterIssuesListCallback(issueArray) {
var issueTable = document.getElementById("table");
issueTable.removeAllRows();
foreach (issueArray as issueObject) {
var issueRow = new HtmlTableRow();
issueRow.addTableCell(issueObject.id);
issueRow.addTableCell(issueObject.summary);
issueRow.addTableCell(issueObject.assignedTo);
// etc...
issueTable.addRow(issueRow);
};
};
Thursday, October 22, 2009
issues?
• Structure of “three files” completely dependent on structure of the data feed (e.g. the fields of an Issue object); HTML File, Data WebService and Client JavaScript all need to understand what an “Issue” is
• Confusion as to where Business Logic or Security would go
Thursday, October 22, 2009
client-side ajax
• Code maintenance:3 languages, 4 tiers
• Ripple effect
• Security concerns;Business logic stored on the client
Thursday, October 22, 2009
server-side ajax
• PHP generatesclient JavaScript(via traditional MVC approach)
• Code generation is the key
• More secure; Significant ease of maintenance
Thursday, October 22, 2009
keep javascript “dum”• JavaScript should do
the absolute bare minimum
• The ECMA “Standard”
• Shout-out to Douglas CrockfordYahoo! Sr. JavaScript Architect
• Minimizes security holes and exposure of business logic
Thursday, October 22, 2009
the strategy• Implement a true MVC
approach
• componentize your HTML Controls on the server
• utilize event-driven methodologies
• Add some Ajaxifying “Secret Sauce”
<h3>Please select a country</h3>
<select id="country">
<option>China</option>
<option>Japan</option>
<option>Taiwan</option>
<option>UK</option>
<option>USA</option>
....
</select>
<p>Lorem ipsum dolorem est...</p>
Thursday, October 22, 2009
the strategy• Implement a true MVC
approach
• componentize your HTML Controls on the server
• utilize event-driven methodologies
• Add some Ajaxifying “Secret Sauce”
$countrySelect = new Select();
$countrySelect->addOption("China");
$countrySelect->addOption("Japan");
$countrySelect->addOption("Taiwan");
$countrySelect->addOption("UK");
$countrySelect->addOption("US");
<h3>Please select a country</h3>
<?php $countrySelect->render(); ?>
<p>Lorem ipsum dolorem est...</p>
Thursday, October 22, 2009
$countrySelect->addChangeAction("countryChanged");
function countryChanged() {
$stateArray = States::LoadArrayForCountry
($countrySelect->selectedValue);
$stateSelect->removeAllOptions();
foreach ($stateArray as $state) {
$stateSelect->addOption($state);
}
}
the strategy• Implement a true MVC
approach
• componentize your HTML Controls on the server
• utilize event-driven methodologies
• Add some Ajaxifying “Secret Sauce”
Thursday, October 22, 2009
<?php
/* Listing for address.php */
$form = new Form();
if ($form->isNew()) {
$countrySelect = new Select($form);
$countrySelect->
addChangeAction("countryChanged");
...
$stateSelect = new Select($form);
$stateSelect->enabled = false;
...
}
function countryChanged() {...}
include("address.tpl.php");
?>
event-driven in detail
• Use “Form State”
• Every HTML Control is stored in Form State
• Form State is serialized, and restored on submit
Thursday, October 22, 2009
<html><body>
<?php $form->render(); ?>
Country:<br/>
<?php $country->render(); ?>
State:<br/>
<?php $state->render(); ?>
</body></html>
event-driven in detail
• Use “Form State”
• Every HTML Control is stored in Form State
• Form State is serialized, and restored on submit
Thursday, October 22, 2009
<html><body>
<form action="address.php">
<input type="hidden" id="formState"
value="abcd1234..."/>
Country:<br/>
<select id="country"
onchange="form.submit();">
...
</select>
State:<br/>
<select id="state">...</select>
</body></html>
event-driven in detail
• Use “Form State”
• Every HTML Control is stored in Form State
• Form State is serialized, and restored on submit
Thursday, October 22, 2009
<html><body>
<form action="address.php">
<input type="hidden" id="formState"
value="abcd1234..."/>
Country:<br/>
<select id="country"
onchange="form.submit();">
...
</select>
State:<br/>
<select id="state">...</select>
</body></html>
event-driven in detail
• Use “Form State”
• Every HTML Control is stored in Form State
• Form State is serialized, and restored on submit
<html><body>
<?php $form->render(); ?>
Country:<br/>
<?php $country->render(); ?>
State:<br/>
<?php $state->render(); ?>
</body></html>
Thursday, October 22, 2009
<?php
/* Listing for address.php */
$form = new Form();
if ($form->isNew()) {
$countrySelect = new Select($form);
$countrySelect->
addChangeAction("countryChanged");
...
$stateSelect = new Select($form);
$stateSelect->enabled = false;
...
}
function countryChanged() {...}
include("address.tpl.php");
?>
event-driven in detail
• Use “Form State”
• Every HTML Control is stored in Form State
• Form State is serialized, and restored on submit
Thursday, October 22, 2009
the strategy
• Implement a true MVC approach
• componentize your HTML Controls
• utilize event-driven methodologies
• Add some Ajaxifying “Secret Sauce”
Thursday, October 22, 2009
what’s the “secret sauce”
• HTML wrapper for each AjaxifiedDOM element
<span id="_state">
<select id="state" disabled="disabled">
<option>Select One...</option>
</select>
</span>
Thursday, October 22, 2009
<?php
/* Listing for address.php */
$form = new Form();
if ($form->isNew()) {
$countrySelect = new Select($form);
$countrySelect->
addChangeAction("countryChanged");
...
$stateSelect = new Select($form);
$stateSelect->enabled = false;
...
include("address.tpl.php");
}
function countryChanged() {...}
?>
event-driven with mayo
• Make the form smarter
• Form should track which controls have changed and only return the updated HTML for those controls
• Client JavaScript does simple DOM replacements
Thursday, October 22, 2009
<html><body>
<form action="address.php">
<input type="hidden" id="formState"
value="abcd1234..."/>
<input type="hidden" id="methodName"
value=""/>
Country:<br/>
<select id="country"
onchange="AjaxCall('countryChanged');">
...
</select>
State:<br/>
<select id="state">...</select>
</body></html>
event-driven with mayo
• Make the form smarter
• Form should track which controls have changed and only return the updated HTML for those controls
• Client JavaScript does simple DOM replacements
Thursday, October 22, 2009
function AjaxCall(methodName) {
document.getElementById.methodName.value =
methodName;
XmlRpcCall(document.form.action,
"defaultCallback");
};
function defaultCallback(updatedControlArray) {
foreach (updatedControlArray as updatedControl) {
var control = document.getElementById("_" +
updatedControl.id);
control.innerHTML = updatedControl.html;
};
};
event-driven with mayo
• Make the form smarter
• Form should track which controls have changed and only return the updated HTML for those controls
• Client JavaScript does simple DOM replacements
<updatedControlArray>
<updatedControl id="state">
<!CDATA[
<select id="state">
<option>...</option>
<option>...</option>
</select>
]]>
</updatedControl>
</updatedControlArray>
Thursday, October 22, 2009
coding demo
Thursday, October 22, 2009
Thursday, October 22, 2009
so what about this?
• Now, only one file is dependent on structure of the data feed
Thursday, October 22, 2009
qcodo
• Developed in 2001Open Sourced in 2005MIT License
• Code Generation ORMComprehensive MVCServer-Side AJAX
• 120,000+ Downloads1500+ Registered Users
Thursday, October 22, 2009
closing thoughts...
• Questions?
• www.qcodo.com
Thursday, October 22, 2009