Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Agavi (IPC2008 2008-10-28)

Agavi (IPC2008 2008-10-28)

Presentation given at International PHP Conference 2008 in Mainz, Germany.

David Zuelke

October 28, 2008
Tweet

More Decks by David Zuelke

Other Decks in Programming

Transcript

  1. • 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.
  2. 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.
  3. 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.
  4. 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!
  5. 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!
  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. 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
  13. 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).
  14. 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.
  15. 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.
  16. For the FrOSCon folks following me - the Agavi numbers

    were low because I was in development mode - slides updated “ 126.91 trans/s (not 8.24 trans/s!)
  17. Now let’s add JSON! class
Shop_LatestProductsSuccessView
extends
AcmeStoreBaseShopView
{ 

public
function
executeHtml(AgaviRequestDataHolder
$rd)
{
/*...*/
} 

 

public
function
executeJson(AgaviRequestDataHolder
$rd)
{ 



return
json_encode($this‐>getAttribute('products')); 

}

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

<parameter
name="http_headers"> 



<parameter
name="Content‐Type">application/json</parameter> 

</parameter> </output_type>
  18. Or how about CSV? class
Shop_LatestProductsSuccessView
extends
AcmeStoreBaseShopView
{ 

public
function
executeHtml(AgaviRequestDataHolder
$rd)
{
/*...*/
} 

public
function
executeJson(AgaviRequestDataHolder
$rd)
{
/*...*/
} 

public
function
executeCsv(AgaviRequestDataHolder
$rd)
{ 



$csv
=
fopen('php://temp',
'r+'); 



fputcsv($csv,
$this‐>getAttribute('products'));

    



rewind($fp); 



return
$fp; 

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

<parameter
name="http_headers"> 



<parameter
name="Content‐Type">text/csv</parameter> 

</parameter> </output_type>
  19. This is the Template file: <form
action="<?php
echo
$ro‐>gen('login');
?>"
method="post"> 

<dl> 



<dt><label
for="fe‐username">Username:</label></dt> 



<dd><input
type="text"
name="username"
id="fe‐username"
/></dd> 



<dt><label
for="fe‐password">Password:</label></dt>

    



<dd><input
type="password"
name="password"
id="fe‐password"
/></dd> 



<dt>&#160;</dt> 



<dd><input
type="checkbox"
name="remember"
id="fe‐remember"
/><label
for="fe‐remember">
Log
 me
in
automatically.</label></dd> 



<dt>&#160;</dt> 



<dd><input
type="submit"
value="Login"
/></dd> 

</dl> </form>
  20. A Layout: 

<configuration
context="web"> 



<output_types
default="html"> 





<output_type
name="html"> 







<renderers
default="php"> 









<renderer
name="php"
class="AgaviPhpRenderer"> 











<!‐‐
renderer
options
you
want
‐‐> 









</renderer> 







</renderers>

    







<layouts
default="default"> 









<layout
name="default"> 











<layer
name="content"
/> 











<layer
name="decorator"> 













<slot
name="menu"
module="Default"
action="Menu"
/> 













<parameter
name="directory">%core.template_dir%</parameter> 













<parameter
name="template">Master</parameter> 











</layer> 









</layout> 









<layout
name="slot"> 











<layer
name="content"
/> 









</layout> 







</layouts> 







<parameter
name="http_headers"> 









<parameter
name="Content‐Type">text/html;
charset=UTF‐8</parameter> 







</parameter> 





</output_type>
  21. The Caching rules: <caching
method="read"
lifetime="2
hours"> 

<group>products</group> 

<group
source="request_parameter">id</group> 

<group
source="locale"
/> 

 

<view>Success</view> 



    

<output_type
name="html"> 



<layer
name="content"
/> 



<template_variable>title</template_variable> 

</output_type> </caching>
  22. The Chuckwalla A 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. <configuration
context="irc"> 

<!‐‐
so
someone
can
type
"!seen
Wombert"
on
IRC
‐‐> 

<route
pattern="^!seen
(username:\S+)$"
action="LastSeen"
/> </configuration> <configuration
context="web"> 

<!‐‐
on
the
web,
the
URL
is
/seen/Wombert
‐‐> 

<route
pattern="^/seen/(username:\S+)$"
action="LastSeen"
/> </configuration>
  23. One More Thing... We have a new website! - Online

    today! - A lot of brand new tutorial and reference docs!
  24. 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