Você está na página 1de 31

Server-Side, PHP-Generated AJAX

Mike Ho, Quasidea Development


Zend/PHP Conference Thursday, October 22, 2009
Soli Deo Gloria John 3:16 Romans 12
Thursday, October 22, 2009

a bit about me...


Quasidea Development 10+ years of IT
consulting experience Qcodo Development Framework

Lead Developer,

Thursday, October 22, 2009

a bit about you...


Developers vs.
Others

AJAX Frameworks

Thursday, October 22, 2009

a bit of history...
Database

PHP 3 and PHP 4


PHP

Thursday, October 22, 2009

a bit of history...
Database

PHP 3 and PHP 4 PHP 5, ORM and


frameworks

PHP Model / ORM

PHP View / Controller

Thursday, October 22, 2009

a bit of history...
Database

PHP 3 and PHP 4 PHP 5, ORM and


frameworks AJAX

PHP Model / ORM

PHP with client-side

PHP View / Controller

JavaScript

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 and a 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 generates
the key client JavaScript
(via traditional MVC approach)

Code generation is More secure;


Signicant ease of maintenance

Thursday, October 22, 2009

keep javascript dum


JavaScript should do
the absolute bare minimum

The ECMA Standard Shout-out to


Douglas Crockford
Yahoo! Sr. JavaScript Architect

Minimizes security
Thursday, October 22, 2009

holes and exposure of business logic

the strategy
Implement a true MVC
approach

componentize your
HTML Controls on the server methodologies

utilize event-driven Add some Ajaxifying


Secret Sauce
Thursday, October 22, 2009

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

the strategy
Implement a true MVC
approach

componentize your
HTML Controls on the server methodologies

$countrySelect = new Select(); $countrySelect->addOption("China"); $countrySelect->addOption("Japan"); $countrySelect->addOption("Taiwan"); $countrySelect->addOption("UK"); $countrySelect->addOption("US");

utilize event-driven Add some Ajaxifying


Secret Sauce
Thursday, October 22, 2009

<h3>Please select a country</h3> <?php $countrySelect->render(); ?> <p>Lorem ipsum dolorem est...</p>

the strategy
Implement a true MVC
approach

componentize your
HTML Controls on the server methodologies

$countrySelect->addChangeAction("countryChanged"); function countryChanged() { $stateArray = States::LoadArrayForCountry ($countrySelect->selectedValue); $stateSelect->removeAllOptions(); foreach ($stateArray as $state) { $stateSelect->addOption($state); } }

utilize event-driven Add some Ajaxifying


Secret Sauce
Thursday, October 22, 2009

event-driven in detail
Use Form State Every HTML Control Form State is
<?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"); ?>

is stored in Form State serialized, and restored on submit

Thursday, October 22, 2009

event-driven in detail
Use Form State Every HTML Control Form State is
<html><body> <?php $form->render(); ?> Country:<br/> <?php $country->render(); ?> State:<br/> <?php $state->render(); ?> </body></html>

is stored in Form State serialized, and restored on submit

Thursday, October 22, 2009

event-driven in detail
Use Form State Every HTML Control Form State is
<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>

is stored in Form State serialized, and restored on submit

Thursday, October 22, 2009

event-driven in detail
<html><body>

Use Form State Every HTML Control


<?php $form->render(); ?> Country:<br/> <?php $country->render(); ?> State:<br/> <?php $state->render(); ?>

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

is stored in Form State

serialized, and restored </body></html> on submit

Form State is

Thursday, October 22, 2009

event-driven in detail
Use Form State Every HTML Control Form State is
<?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"); ?>

is stored in Form State serialized, and restored on submit

Thursday, October 22, 2009

the strategy
Implement a true MVC
approach

componentize your
HTML Controls methodologies

utilize event-driven Add some Ajaxifying


Secret Sauce
Thursday, October 22, 2009

whats the secret sauce


<span id="_state"> <select id="state" disabled="disabled"> <option>Select One...</option> </select> </span>

HTML wrapper for each Ajaxied


DOM element

Thursday, October 22, 2009

event-driven with mayo


Make the form smarter Form should track
<?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() {...} ?>

which controls have changed and only return the updated HTML for those controls simple DOM replacements

Client JavaScript does

Thursday, October 22, 2009

event-driven with mayo


Make the form smarter Form should track
which controls have changed and only return the updated HTML for those controls simple DOM replacements
<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>

Client JavaScript does

Thursday, October 22, 2009

event-driven with mayo


Form should track
Make the form smarter which controls have changed and only return the updated HTML for those controls simple DOM replacements
<updatedControlArray> <updatedControl id="state"> <!CDATA[ <select id="state"> <option>...</option> <option>...</option> </select> ]]> </updatedControl> </updatedControlArray> 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; }; };

Client JavaScript does

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 2001
Open Sourced in 2005 MIT License Comprehensive MVC Server-Side AJAX

Code Generation ORM 120,000+ Downloads


Thursday, October 22, 2009

1500+ Registered Users

closing thoughts...

Questions? www.qcodo.com mike@quasidea.com

Thursday, October 22, 2009

Você também pode gostar