Less Time, Less Code, Less Headache

12,947 views

Published on

Learn how developing with the Lithium framework for PHP 5.3+ not only allows you to develop applications on tighter deadlines, but how Lithium's unique, superior architecture allows much-improved maintainability over the life of your apps.

Published in: Technology
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
12,947
On SlideShare
0
From Embeds
0
Number of Embeds
68
Actions
Shares
0
Downloads
123
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Less Time, Less Code, Less Headache

    1. LESS TIME LESS CODE LESS HEADACHELithium: the framework that tries to suck less
    2. THE GOAL• Posting with photo upload• RSS updates• Geo-tagged images & geo-spatial search• Logging?
    3. $ git clone git://dev.lithify.me/lithium.git photoblogBonus Points – add the li3 command to your system PATH:http://bit.ly/li3path
    4. http://path/to/web/photoblog
    5. $ cd photoblog/app$ chmod -R 777 resources/
    6. http://path/to/web/photoblog
    7. photoblog/config/bootstrap.phprequire __DIR__ . /bootstrap/connections.php;photoblog/config/bootstrap/connections.phpuse lithiumdataConnections;Connections::add(default, array( type => MongoDb, host => localhost, database => photoblog));
    8. ALTERNATIVES...photoblog/config/bootstrap/connections.phpuse lithiumdataConnections;Connections::add(default, array( type => http, adapter => CouchDb, host => localhost, database => app));
    9. ALTERNATIVES...photoblog/config/bootstrap/connections.phpuse lithiumdataConnections;Connections::add(default, array( type => database, adapter => MySql, host => localhost, login => web, password => sekrit, database => app));
    10. $ li3 create PhotosPhotos created in appmodels.PhotosController created in appcontrollers.PhotosTest created in apptestscasesmodels.PhotosControllerTest created in apptestscasescontrollers.
    11. http://path/to/web/photoblog/photos
    12. photoblog/controllers/PhotosController.phpclass PhotosController extends lithiumactionController { public function index() { $photos = Photos::all(); return compact(photos); } // ...}
    13. photoblog/views/photos/index.html.php<?php if (!count($photos)): ?> <em>No photos</em>. <?=$this->html->link(Add one, Photos::add); ?>.<?php endif ?>
    14. http://path/to/web/photoblog/photos
    15. photoblog/controllers/PhotosController.php public function add() { $photo = Photo::create(); if (($this->request->data) && $photo->save($this->request->data)) { $this->redirect(array(Photos::view, id => $photo->_id)); $this->redirect(array(Photos::view, id => $photo->_id)); } $this->_render[template] = edit; return compact(photo); }
    16. photoblog/views/photos/edit.html.php<?=$this->form->create($photo, array(type => file)); ?> <?=$this->form->field(title); ?> <?=$this->form->field(description); ?> <?php if (!$photo->exists()) { ?> <?=$this->form->field(file, array(type => file)); ?> <?php } ?> <?=$this->form->submit(Save); ?><?=$this->form->end(); ?>
    17. http://path/to/web/photoblog/photos/add
    18. photoblog/models/Photos.phpclass Photo extends lithiumdataModel { public $validates = array(); protected $_meta = array(source => fs.files);}
    19. http://path/to/web/photoblog/photos/add
    20. http://path/to/web/photoblog/photos/add
    21. photoblog/config/routes.phpRouter::connect(/{:controller}/{:action}/{:id:[0-9a-f]{24}}.{:type}, array(id => null));Router::connect(/{:controller}/{:action}/{:id:[0-9a-f]{24}});
    22. photoblog/config/routes.phpRouter::connect(/{:controller}/{:action}/{:id:[0-9a-f]{24}}.{:type}, array(id => null));Router::connect(/{:controller}/{:action}/{:id:[0-9a-f]{24}}); {:id:[0-9a-f]{24}}
    23. http://path/to/web/photoblog/photos/view/...
    24. photoblog/views/photos/view.html.php<h1><?=$photo->title; ?></h1><p><?=$photo->description; ?></p><p> <?=$this->html->link(Edit, array(Photos::edit, id => $photo->_id)); ?></p><?=$this->html->image("/photos/view/{$photo->_id}.jpg", array( alt => $photo->title, width => 500)); ?>
    25. http://path/to/web/photoblog/photos/view/...
    26. photoblog/config/bootstrap.php/** * This file contains configurations for handling different * content types within the framework, including converting data to * and from different formats, and handling static media assets. */require __DIR__ . /bootstrap/media.php;photoblog/config/bootstrap/media.phpMedia::type(jpg, image/jpeg, array( cast => false, encode => function($data) { return $data[photo]->file->getBytes(); }));
    27. http://path/to/web/photoblog/photos/view/...
    28. Router::connect(/.../{:id:[0-9a-f]{24}}. {:type} {:type}, array(...)); Controller $photo Media HTML JSON JPEG templateView => array( ) Media type handlerView Layout json_encode( )
    29. photoblog/config/routes.phpuse appmodelsPhotos;use lithiumactionResponse;Router::connect(/photos/view/{:id:[0-9a-f]{24}}.jpg, array(), function($request) { return new Response(array( headers => array(Content-type => image/jpeg), body => Photos::first($request->id)->file->getBytes() ));});
    30. photoblog/views/photos/index.html.php<ul><?php foreach ($photos as $photo): ?> <li> <?=$this->html->link($photo->title, array( controller => photos, action => view, id => $photo->_id )); ?> </li><?php endforeach ?></ul>
    31. http://path/to/web/photoblog/photos
    32. photoblog/views/photos/index.html.php<ul><?php foreach ($photos as $photo): ?> <li> <?=$this->html->image( "/photos/view/{$photo->_id}.jpg", array(width=> 100) ); ?> <?=$this->html->link( $photo->title, array(Photos::view, id => $photo->_id) array(Photos::view, id => $photo->_id) ); ?> </li><?php endforeach ?></ul>
    33. http://path/to/web/photoblog/photos
    34. photoblog/config/bootstrap/media.phpMedia::type(rss, application/rss+xml);
    35. photoblog/views/layouts/default.rss.php<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>Photos</title> <pubDate> <?=date("D, j M Y H:i:s", gmmktime()) . GMT; ?> </pubDate> <?=$this->content(); ?> </channel></rss>
    36. photoblog/views/photos/index.rss.php<?php foreach ($photos as $photo): ?><item> <title><?=$photo->title; ?></title> <link><?=$this->url(array(Photos::view, id => $photo->_id)); ?></link> <description><?=$photo->description; ?></description></item><?php endforeach; ?>
    37. http://path/to/web/photoblog/photos.rss
    38. http://path/to/web/photoblog/photos.json[{ "photo": { "_id": "4d70c5017675ab4de900001f", "title": "FML", "description": "How the subway schedule sometimes makes me feel.", "filename": "FML.jpg", "uploadDate": 1299236097, "length": 452751, "chunkSize": 262144, "md5": "e74c961185efdd69acbccaa59b7b13c0", "file": { ... } }}]
    39. $ cd libraries/$ git clone code@dev.lithify.me:li3_geo.gitNote – you will need an account. Sign up here:http://dev.lithify.me/users/add
    40. photoblog/config/bootstrap/libraries.php/** * Add some plugins */Libraries::add(li3_geo);
    41. photoblog/models/Photos.phpuse li3_geoextensionsGeocoder;use li3_geoextensionsdatabehaviorLocatable;class Photos extends lithiumdataModel { // ... public static function __init() { parent::__init(); Locatable::bind(__CLASS__, array(fields => array( location.latitude, location.longitude ))); }}
    42. photoblog/models/Photos.php public function save($entity, $data = null, array $options = array()) { if ($data) { $entity->set($data); } if (!$entity->exists() && isset($entity->file->tmp_name)) { $entity->location = Geocoder::exifCoords( exif_read_data($entity->file->tmp_name) ); } return parent::save($entity, null, $options); }
    43. photoblog/controllers/PhotosController.phpuse li3_geoextensionsGeocoder;// ... public function near($place = null) { $this->_render[template] = index; $location = Geocoder::find(google, $place); $photos = Photos::near($location, array(limit => 5)); return compact(photos); }
    44. http://.../photos/near/New+York,+NY
    45. photoblog/config/bootstrap/logging.phpuse lithiumanalysisLogger;use lithiumdataConnections;Logger::config(array( default => array(adapter => File)));
    46. photoblog/config/bootstrap/logging.phpConnections::get(default)->applyFilter(read, function($self, $params, $chain) { $query = $params[query]; Logger::debug( Read: . $query->source() . : . json_encode($query->conditions()) ); return $chain->next($self, $params, $chain);});
    47. photoblog/config/bootstrap/logging.phpConnections::get(default)->applyFilter(update, function($self, $params, $chain) { $query = $params[query]; $data = json_encode($query->conditions()) . , . json_encode($query->data()); Logger::debug(Update: . $query->source() . ": {$data}"); return $chain->next($self, $params, $chain);});
    48. photoblog/resources/tmp/logs/debug.log2011-03-04 18:37:07 Read: fs.files: {"location":{"$near":{"latitude":40.7143528,"longitude":-74.0059731}}}2011-03-04 18:37:07 Read: fs.files: {"_id":"4d710afc7675ab95d0000004"}
    49. Thanks, y’all!Getting connected AOP Resourceslithify.me bit.ly/aop-designgithub.com/UnionOfRAD bit.ly/aop-gwoo#li3 on irc.freenode.net bit.ly/aop-li3@nateabele bit.ly/aop-oop@UnionOfRAD bit.ly/mwop-aop

    ×