ipc 2008: agavi (2008-10-28)

56

Upload: david-zuelke

Post on 05-Dec-2014

1.790 views

Category:

Technology


7 download

DESCRIPTION

My presentation "Scaling Your Development With The Agavi Framework" I gave at International PHP Conference 2008 in Mainz, Germany

TRANSCRIPT

Page 1: IPC 2008: Agavi (2008-10-28)
Page 2: IPC 2008: Agavi (2008-10-28)

Scaling Your Developmentwith the Agavi Framework

Page 3: IPC 2008: Agavi (2008-10-28)

David Zülke

Page 4: IPC 2008: Agavi (2008-10-28)

David Zuelke

Page 5: IPC 2008: Agavi (2008-10-28)

(assuming everyone kmows where Germany is, I’ll move on)

Page 6: IPC 2008: Agavi (2008-10-28)

• Bitextender GmbH, based in Munich.de

• We’ve been doing development, consulting and training for 5+ years.

• Team of 7.

• The company behind Agavi, backing and developing it.

Page 7: IPC 2008: Agavi (2008-10-28)

But let’s move on to the non-boring stuff, shall we?

Page 8: IPC 2008: Agavi (2008-10-28)

From Mojavi to AgaviA brief history lesson.

Page 9: IPC 2008: Agavi (2008-10-28)

Anyone heard of Mojavi before, or used it?

Page 10: IPC 2008: Agavi (2008-10-28)

Mojavi 1, 2 and 3 were developed by Sean Kerr.

Development wasn’t open and transparent, despite the license (and awesomeness!), and died eventually.

Mojavi 3 was forked by some guys from Keller, Texas, and given the name Agavi in 2005.

Because Agave plants grow in the Mojave desert.

Since late 2005, Agavi is maintained by Bitextender.

symfony is also based on Mojavi 3.

Page 11: IPC 2008: Agavi (2008-10-28)

Speaking of Mojavi...

Sean Kerr is back from the dead, and loves Agavi!

Page 12: IPC 2008: Agavi (2008-10-28)

AgaviKey Features and Differences.

Page 13: IPC 2008: Agavi (2008-10-28)

No Assumptions

Being PHP based, it works best for websites and other HTTP-based stuff, but you can use it to write any app.

No requirements for specific template engines, DBMSes, ORMs, client side JS libraries etc.

Abstraction of HTTP request method verbs, output types, response implementations etc.

Form Handling is independent of libraries, template engines etc.

Page 14: IPC 2008: Agavi (2008-10-28)

Reuse Code

The right things are done in the right places, and the framework prevents common mistakes.

Exposing Actions of a web application through a SOAP web service API etc. can be done in minutes.

Want an RSS feed of your latest products? It’s just a new output type away.

Want to return JSON for Ajax features? Have it done when a JS framework sends the right request headers!

Page 15: IPC 2008: Agavi (2008-10-28)

Environments and Contexts

An Environment is bootstrapped for every box or developer. Could be “production”, or “dev-joecool” etc.

A Context represents a way of accessing the application, like “web”, “soap” or “console”.

Any configuration can be specific to one or more Environment(s) and/or Context(s).→ no more copying and overwriting of DB configs!

Page 16: IPC 2008: Agavi (2008-10-28)

Modules, Actions, Views etc

An Application has a number of Modules.

Each Module has Actions with corresponding Views and Templates, as well as various configuration files that control caching, validation and so on.

Actions, which can also be nested into folders, contain application logic, make calls to Models, and have one or more Views (“Error”, “Success”, “Input” etc.)

Views handle presentation, usually using Templates.

Page 17: IPC 2008: Agavi (2008-10-28)

Execution Containers

Every Action execution happens in an isolated Container.

Every container has it’s own request data, response, filters etc.

A normal execution is idempotent, i.e. does not affect the “outside world”.

Internal forwarding can be done by returning a new Container from a View.

Page 18: IPC 2008: Agavi (2008-10-28)

Filters

Global Filters or per-Action/Container filters.

Wrap the execution, and call the next Filter in the chain - like an Onion or a Russian Nested Doll.

Features like Security or Form Handling are implemented using Filters inside Agavi.

Flow can be redirected internally, response info can be modified etc; numerous possibilities.

Page 19: IPC 2008: Agavi (2008-10-28)

Layers and Layouts

A View can leave instructions on Templates to render; these are called Layers.

Each Layer has access to the output of the previous Layers, and can define Slots - Containers with Actions that are run before rendering, returning the content.

Layer and Slot definitions can be made in a configuration file; the result is a Layout.

All this can be done programmatically, as well.

Page 20: IPC 2008: Agavi (2008-10-28)

Routing

Used for matching URLs, SOAP method names.

Every route can have children.

Callbacks can control and modify behavior on matching or when generating URLs.

Routes can also set Output Types, force continuing of execution even though they matched, and much more.

Also very nice for refactoring existing applications.

Page 21: IPC 2008: Agavi (2008-10-28)

Form Handling

Form Population Filter makes form handling a breeze.

Can pre-populate forms using given values.

Re-populates a form when an error occurred.

Highlights erroneous fields and labels.

Can insert error messages into the document.

All without a single line of code in templates.

Page 22: IPC 2008: Agavi (2008-10-28)

Caching

Cache the entire execution of a request, or just parts.

Action-based, so a Slot that runs can be cached, too.

Output can be cached on a per-layer basis, so that the outer master template always runs even when cached.

Also caches cookies (with correct lifetime!), HTTP headers that were set etc.

Stampede Protection will be included in Agavi 1.0

Page 23: IPC 2008: Agavi (2008-10-28)

Validation

Validates not only request parameters, but also Files, Cookies and HTTP Headers.

Default settings mean you only have access to data you validated.

Drastically reduces the possibility for dev mistakes.

Validators can have dependencies (“only validate email if checkbox is on”), different severities, handle arrays, normalize values (e.g. make Unix TS from date value).

Page 24: IPC 2008: Agavi (2008-10-28)

Security

Security Filter is the internal mechanism to auto-check against credentials, authentication status etc.

Ships with plain and RBAC implementations, easily extensible.

Provided implementations work with the standard getCredentials() and isSecure() methods on Actions; any other behavior, additional authentication levels etc can be implemented in a custom Security Filter.

Page 25: IPC 2008: Agavi (2008-10-28)

Internationalization

Bundles the Unicode CLDR database with information about all locales of this world.

Functions for translating text, formatting and parsing dates, numbers and currency values, calendar and timezone operations, locale information (e.g. list of all countries in Japanese language etc.)

Parts of the functionality are ports of ICU, IBM’s Java/C library for globalization.

Page 26: IPC 2008: Agavi (2008-10-28)

And no, it is not as slow as Rasmus claimed at FrOSCon.

Page 27: IPC 2008: Agavi (2008-10-28)

For the FrOSCon folks followingme - the Agavi numbers were low because I was in development mode - slides updated

126.91 trans/s (not 8.24 trans/s!)

Page 28: IPC 2008: Agavi (2008-10-28)

ExamplesA.k.a. real code, the stuff everyone’s here for.

Page 29: IPC 2008: Agavi (2008-10-28)

An Action that lists productsclassProducts_LatestActionextendsAcmeStoreBaseProductsAction{publicfunctionexecute(AgaviRequestDataHolder$rd){//grabtheproductfindermodel.couldalsobedoctrineetc.$pfm=$this‐>getContext()‐>getModel('ProductFinder');//fetchalistoflatestproducts,let'sassumeit'sanarray$latestProducts=$pfm‐>fetchLatest()://assignitfortheView$this‐>setAttribute('products',$latestProducts);//gotoProducts_LatestSuccessViewreturn'Success';}}

Page 30: IPC 2008: Agavi (2008-10-28)

The corresponding View

classProducts_LatestSuccessViewextendsAcmeStoreBaseProductsView{publicfunctionexecuteHtml(AgaviRequestDataHolder$rd){//notmuchtodohere.let'sjustloadthedefaultlayout$this‐>setupHtml($rd);//andmaybesetapagetitle$this‐>setAttribute('title','LatestACMEProducts');}}

Page 31: IPC 2008: Agavi (2008-10-28)

The template, obviously...

<h2><?=$t['title']?></h2><dl><?phpforeach($t['products']as$p):?><dt><ahref="<?=$ro‐>gen('products.product.view',array('id'=>$p['id']))?>"><?=htmlspecialchars($p['name'])?></a></dt><dd><?=$tm‐>_c($p['price'])?></dd><?phpendforeach;?></dl>

Page 32: IPC 2008: Agavi (2008-10-28)

And routes to make it work

<routename="products"pattern="^/products"module="Products"><routename=".index"pattern="^$"action="Index"/><routename=".latest"pattern="^/latest$"action="Latest"/><routename=".product"pattern="^/(id:\d+)"action="Product"><routename=".view"pattern="^$"action=".View"/><routename=".gallery"pattern="^/gallery$"action=".Gallery"/></route></route>

Page 33: IPC 2008: Agavi (2008-10-28)

Now let’s add JSON!classShop_LatestProductsSuccessViewextendsAcmeStoreBaseShopView{publicfunctionexecuteHtml(AgaviRequestDataHolder$rd){/*...*/}publicfunctionexecuteJson(AgaviRequestDataHolder$rd){returnjson_encode($this‐>getAttribute('products'));}}

<routepattern="application/json"source="_SERVER[HTTP_ACCEPT]"stop="false"output_type="json"/><routename="products"pattern="^/products"module="Products"><!‐‐...‐‐></route>

<output_typename="html"><!‐‐...‐‐></output_type><output_typename="json"><parametername="http_headers"><parametername="Content‐Type">application/json</parameter></parameter></output_type>

Page 34: IPC 2008: Agavi (2008-10-28)

Or how about CSV?classShop_LatestProductsSuccessViewextendsAcmeStoreBaseShopView{publicfunctionexecuteHtml(AgaviRequestDataHolder$rd){/*...*/}publicfunctionexecuteJson(AgaviRequestDataHolder$rd){/*...*/}publicfunctionexecuteCsv(AgaviRequestDataHolder$rd){$csv=fopen('php://temp','r+');fputcsv($csv,$this‐>getAttribute('products'));rewind($fp);return$fp;}}

<routepattern="application/json"source="_SERVER[HTTP_ACCEPT]"stop="false"output_type="json"/><routepattern="/csv$"stop="false"cut="true"output_type="csv"/><routename="products"pattern="^/products"module="Products"><!‐‐...‐‐></route>

<output_typename="csv"><parametername="http_headers"><parametername="Content‐Type">text/csv</parameter></parameter></output_type>

Page 35: IPC 2008: Agavi (2008-10-28)

Form Handling

Page 36: IPC 2008: Agavi (2008-10-28)

Didn’t login as Chuck Norris!

Page 37: IPC 2008: Agavi (2008-10-28)

This is the Template file:

<formaction="<?phpecho$ro‐>gen('login');?>"method="post"><dl><dt><labelfor="fe‐username">Username:</label></dt><dd><inputtype="text"name="username"id="fe‐username"/></dd><dt><labelfor="fe‐password">Password:</label></dt><dd><inputtype="password"name="password"id="fe‐password"/></dd><dt>&#160;</dt><dd><inputtype="checkbox"name="remember"id="fe‐remember"/><labelfor="fe‐remember">Logmeinautomatically.</label></dd><dt>&#160;</dt><dd><inputtype="submit"value="Login"/></dd></dl></form>

Page 38: IPC 2008: Agavi (2008-10-28)

A Layout:<configurationcontext="web"><output_typesdefault="html"><output_typename="html">

<renderersdefault="php"><renderername="php"class="AgaviPhpRenderer"><!‐‐rendereroptionsyouwant‐‐></renderer></renderers>

<layoutsdefault="default"><layoutname="default"><layername="content"/><layername="decorator"><slotname="menu"module="Default"action="Menu"/><parametername="directory">%core.template_dir%</parameter><parametername="template">Master</parameter></layer></layout>

<layoutname="slot"><layername="content"/></layout></layouts>

<parametername="http_headers"><parametername="Content‐Type">text/html;charset=UTF‐8</parameter></parameter></output_type>

Page 39: IPC 2008: Agavi (2008-10-28)

The result:

Content LayerMenu Slot

Page 40: IPC 2008: Agavi (2008-10-28)

Nonsense Store Example

Page 41: IPC 2008: Agavi (2008-10-28)

Search Engine Spam Route:

<routename="search_engine_spam"pattern="^/products(/buy‐cheap‐{name:[\S\s]+}‐at‐agavi‐dot‐org)?/(id:\d+)$"module="Default"action="SearchEngineSpam"><defaultfor="name">/buy‐cheap‐{nonsense}‐at‐agavi‐dot‐org</default></route>

Page 42: IPC 2008: Agavi (2008-10-28)

The Caching rules:<cachingmethod="read"lifetime="2hours"><group>products</group><groupsource="request_parameter">id</group><groupsource="locale"/><view>Success</view><output_typename="html"><layername="content"/><template_variable>title</template_variable></output_type></caching>

Page 43: IPC 2008: Agavi (2008-10-28)

The Result:

Restored from cache

Page 44: IPC 2008: Agavi (2008-10-28)

ShowcaseProof that it’s not just all theory.

Page 45: IPC 2008: Agavi (2008-10-28)
Page 46: IPC 2008: Agavi (2008-10-28)
Page 47: IPC 2008: Agavi (2008-10-28)
Page 50: IPC 2008: Agavi (2008-10-28)

The ChuckwallaA fat lizard from the Mojave desert (likely eats Agaves).

Was a prototype IRC bot application with an IRC Context and a Web interface.

IRC Routing implementation matched patterns against incoming messages.

<configurationcontext="irc"><!‐‐sosomeonecantype"!seenWombert"onIRC‐‐><routepattern="^!seen(username:\S+)$"action="LastSeen"/></configuration><configurationcontext="web"><!‐‐ontheweb,theURLis/seen/Wombert‐‐><routepattern="^/seen/(username:\S+)$"action="LastSeen"/></configuration>

Page 51: IPC 2008: Agavi (2008-10-28)

!e End

Page 52: IPC 2008: Agavi (2008-10-28)

Oh wait.

Page 53: IPC 2008: Agavi (2008-10-28)

One More Thing...We have a new website!

- Online today!

- A lot of brand new tutorial and reference docs!

Page 54: IPC 2008: Agavi (2008-10-28)
Page 55: IPC 2008: Agavi (2008-10-28)

Questions?

Page 56: IPC 2008: Agavi (2008-10-28)

Thank You for Attending!

Shoot me an E-Mail: [email protected]

Slides are available online at http://talks.wombert.de/

http://agavi.org/ is the Agavi website

With Trac, Mailing Lists, PEAR Channel, Docs, ...

Join the Agavi IRC channel: #agavi on irc.freenode.net