0
LazyRecord                 The Fast PHP ORM                                       林佑安                                    Y...
.metadata                • 林佑安 (c9s)                • 190 repo/projects on GitHub                • Perl programming since ...
Why another PHP                    ORM ?12年4月22⽇日星期⽇日
PHP ORMs                • Doctrine12年4月22⽇日星期⽇日
PHP ORMs                • Doctrine                • Propel12年4月22⽇日星期⽇日
PHP ORMs                • Doctrine                • Propel                • Idiorm / Paris12年4月22⽇日星期⽇日
Propel / Doctrine                • Propel uses XML Schema file.12年4月22⽇日星期⽇日
Propel / Doctrine                • Propel uses XML Schema file.                • Doctrine uses XML/YAML/Annotations.12年4月22...
Propel / Doctrine                • Propel uses XML Schema file.                • Doctrine uses XML/YAML/Annotations.       ...
Propel / Doctrine                • Propel uses XML Schema file.                • Doctrine uses XML/YAML/Annotations.       ...
Common characteristic12年4月22⽇日星期⽇日
• XML for configuration file.                • XML for schema file.                • XML for everything.                • Con...
Propel XML                runtime.conf12年4月22⽇日星期⽇日
<?xml version="1.0"?>            <config>              <log>                <ident>propel-bookstore</ident>               ...
<datasource id="bookstore">                    <adapter>sqlite</adapter>                    <connection>                  ...
12年4月22⽇日星期⽇日
It should be simpler12年4月22⽇日星期⽇日
Inspirations                • JiftyDBI / Perl                • KiokuDB / Perl                • ActiveRecord / Ruby        ...
ActiveRecord Pattern12年4月22⽇日星期⽇日
client = Client.find(10)        client = Client.first        Client.where("orders_count = ?", params[:orders])        Clie...
Object::Declare    use Object::Declare [MyApp::Column, MyApp::Param];    my %objects = declare {    param foo =>        !i...
Jifty::DBI                package Simple;                use Jifty::DBI::Schema;                use Jifty::DBI::Record sch...
Jifty::DBI        package TestApp::Model::Phone;        use Jifty::DBI::Schema;        use Jifty::DBI::Record schema {    ...
Jifty                Model Schema12年4月22⽇日星期⽇日
Jifty       Model Schema ⇛ Action12年4月22⽇日星期⽇日
Jifty     Model Schema ⇛ Action ⇛                               CRUD12年4月22⽇日星期⽇日
Jifty                App::Model::Phone ☚ write once12年4月22⽇日星期⽇日
Jifty                     App::Model::Phone                App::Model::PhoneCollection12年4月22⽇日星期⽇日
Jifty                     App::Model::Phone                App::Model::PhoneCollection                 App::Action::Create...
Jifty                     App::Model::Phone                App::Model::PhoneCollection                 App::Action::Create...
Jifty                     App::Model::Phone                App::Model::PhoneCollection                 App::Action::Create...
Jifty                         App::Model::Phone                    App::Model::PhoneCollection                      App::A...
12年4月22⽇日星期⽇日
What we need                •   Can use PHP closures for validation, default value,                    completion ..etc.  ...
PHP 5.3 Characteristic                •   APC is fast.                •   json_encode / json_decode (file) are slower than ...
$array[] vs array_push                                  https://github.com/c9s/SimpleBench12年4月22⽇日星期⽇日
Function calls                     https://github.com/c9s/SimpleBench12年4月22⽇日星期⽇日
PHP ORM v112年4月22⽇日星期⽇日
EteDB                • Initialize model schema in runtime.                • Schema is defined in Model (in                 ...
PHP ORM v212年4月22⽇日星期⽇日
LazyRecord                • Lazy schema                  loader                                      • SQL Generator      ...
Based on SQLBuilder12年4月22⽇日星期⽇日
SQLBuilder                • A Simple SQL Generator.                • Prevent Injection.                • Migration generat...
<?php        $sqlbuilder = new SQLBuilderQueryBuilder( $driver );        $sql = $sqlbuilder->table(authors)->insert([     ...
-- General syntax    INSERT INTO authors ( name , address ) VALUES ( Name , Address );    -- PgSQL    INSERT INTO "Authors...
<?php           $sql = $builder->table(Member)->select(*)               ->where()                   ->equal( a , bar )    ...
Overview12年4月22⽇日星期⽇日
Model Overview12年4月22⽇日星期⽇日
<?php                $author = new Author;                $ret = $author->create([                    name => "Deflator Te...
<?php                $ret = $author->update(array( name => Bar ));                if( $ret->success ) {                   ...
<?php          $record = Author::load(array( name => Foo ));          // To find a record with primary key:          $reco...
$author->toJson();                $author->toArray();                $author->toXml();                $author->toYaml();12...
Collection Overview12年4月22⽇日星期⽇日
Iterator                    <?php                    $authors = new AuthorCollection;                    foreach( $authors...
SQLBuilder Mix-In                   <?php                       $names = new NameCollection;                       $names-...
Filter           <?php               $newCollection = $names->filter(function($item) {                       // do somethi...
Each                  <?php                      $names->each(function($item) {                          $item->update([ ....
Collection Pager                <?php                    /* page 1, 10 per page */                    $authors = new Autho...
Relationship                <?php                // has many                $address = $author->addresses->create([       ...
Schema12年4月22⽇日星期⽇日
Powered by            CascadingAttribute.php12年4月22⽇日星期⽇日
<?php                use LazyRecordSchemaSchemaDeclare;                class AddressSchema extends SchemaDeclare          ...
<?php                use LazyRecordSchemaSchemaDeclare;                class AddressSchema extends SchemaDeclare          ...
<?php                use LazyRecordSchemaSchemaDeclare;                class AddressSchema extends SchemaDeclare          ...
<?php                use LazyRecordSchemaSchemaDeclare;                class AddressSchema extends SchemaDeclare          ...
Default value & builder12年4月22⽇日星期⽇日
$this->column(name)                        ->varchar(30)                        ->default(Default);12年4月22⽇日星期⽇日
$this->column(name)                        ->varchar(30)                        ->default( array(current_timestamp) );12年4...
$this->column(name)                        ->varchar(30)                        ->defaultBuilder(function() {             ...
$this->column(name)                        ->varchar(30)                        ->default(Default)                        ...
Validator12年4月22⽇日星期⽇日
$this->column(name)                                ->varchar(30)                                ->validator(ValidatorClass...
$this->column(name)                     ->varchar(30)                     ->validator( array(ValidatorClass,method) )12年4月...
$this->column(name)                                ->varchar(30)                                ->validator(function_name)...
$this->column(name)                                ->varchar(30)                                ->validator(function($val)...
Filter12年4月22⽇日星期⽇日
$this->column(name)                     ->varchar(30)                     ->filter( function($val) {                      ...
Deflator / Inflator12年4月22⽇日星期⽇日
use LazyRecordSchemaSchemaDeclare;                class NameSchema extends SchemaDeclare                {                 ...
$name->created_on; // DateTime object          $name->created_on->format(Y-m-d);          $name->create([              cre...
Mixin schema12年4月22⽇日星期⽇日
$this->mixin(MetadataMixinSchema);          $this->mixin(I18nMixinSchema);          $this->mixin(CommentMinxSchema);12年4月2...
Multiple data source12年4月22⽇日星期⽇日
database.yml        data_sources:          master:            dsn: mysql:host=localhost;dbname=lazy_test            user: ...
database.yml        data_sources:          master:            dsn: mysql:host=localhost;dbname=lazy_test            user: ...
database.yml        data_sources:          master:            dsn: mysql:host=localhost;dbname=lazy_test            user: ...
拼裝時刻12年4月22⽇日星期⽇日
LazyBone                http://github.com/c9s/LazyBone.git12年4月22⽇日星期⽇日
LazyBone =12年4月22⽇日星期⽇日
LazyRecord                + Roller Router                + RESTful Plugin                 + Backbone.js12年4月22⽇日星期⽇日
Install LazyRecord12年4月22⽇日星期⽇日
sudo bash -c "$(curl -s -L https://raw.github.com/c9s/LazyRecord/master/install.sh)"12年4月22⽇日星期⽇日
Define config file12年4月22⽇日星期⽇日
config/database.yml                       ---                       bootstrap:                         - bootstrap.php     ...
$ lazy build-conf config/database.yml                             Convert YAML to PHP.                             <?php  ...
Define model12年4月22⽇日星期⽇日
<?php                class TodoSchema extends LazyRecordSchemaSchemaDeclare                {                    function s...
Create static schema                        files12年4月22⽇日星期⽇日
12年4月22⽇日星期⽇日
$ lazy build-schema model/TodoSchema.php12年4月22⽇日星期⽇日
$ lazy build-schema model/TodoSchema.php ... Classmap: ! TodoSchemaProxy                   => model/TodoSchemaProxy.php ! ...
Initialize database12年4月22⽇日星期⽇日
12年4月22⽇日星期⽇日
$ lazy build-sql model/TodoSchema.php12年4月22⽇日星期⽇日
$ lazy build-sql model/TodoSchema.php Building SQL for TodoSchema --- SQL for TodoSchema CREATE TABLE todos ( id integer p...
Integrate with your                    application12年4月22⽇日星期⽇日
<?php         use LazyRecordConfigLoader;         $config = new ConfigLoader;         $config->load( __DIR__ . /.lazy.php)...
Define routes12年4月22⽇日星期⽇日
Roller Router                High performance router for PHP12年4月22⽇日星期⽇日
Roller Router                •   APC cache                •   FileSystem cache                •   Use Array to store route...
$router = new RollerRouter;         $router->get( /blog/:id/:title   , function($id,$title) {             return Blog;    ...
RouteSet                     <?php                     $subroutes = new RollerRouteSet;                     $subroutes->ad...
Dispatch                $r = $router->dispatch( isset($_SERVER[PATH_INFO])                            ? $_SERVER[PATH_INFO...
RESTful Plugin12年4月22⽇日星期⽇日
<?php         $router = new RollerRouter( null, array(             cache_id => router_demo         ));         $restful = ...
Auto-generated routes                  GET      /=/restful/posts                  GET      /=/restful/posts.json          ...
Define Your Resource                      Handler12年4月22⽇日星期⽇日
<?php                use RollerPluginRESTfulResourceHandler;                use RollerPluginRESTfulGenericHandler;        ...
<?php                namespace LazyBoneResource;                use RollerPluginRESTfulResourceHandler;                use...
Backbone.js12年4月22⽇日星期⽇日
Todo = Backbone.Model.extend({                    // Default attributes for the todo item.                    defaults: fu...
TodoList = Backbone.Collection.extend({                    // Reference to this collections model.                    mode...
12年4月22⽇日星期⽇日
Hacking                          forks welcome!                http://github.com/c9s/LazyRecord.git12年4月22⽇日星期⽇日
Q &A ?12年4月22⽇日星期⽇日
Upcoming SlideShare
Loading in...5
×

LazyRecord: The Fast ORM for PHP

10,114

Published on

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

No Downloads
Views
Total Views
10,114
On Slideshare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
66
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide

Transcript of "LazyRecord: The Fast ORM for PHP"

  1. 1. LazyRecord The Fast PHP ORM 林佑安 Yo-An Lin (c9s)12年4月22⽇日星期⽇日
  2. 2. .metadata • 林佑安 (c9s) • 190 repo/projects on GitHub • Perl programming since 2008 • PHP programming since last year • c, c++, javascript, obj-c, ruby, python, haskell, java, c#,VB .NET ...12年4月22⽇日星期⽇日
  3. 3. Why another PHP ORM ?12年4月22⽇日星期⽇日
  4. 4. PHP ORMs • Doctrine12年4月22⽇日星期⽇日
  5. 5. PHP ORMs • Doctrine • Propel12年4月22⽇日星期⽇日
  6. 6. PHP ORMs • Doctrine • Propel • Idiorm / Paris12年4月22⽇日星期⽇日
  7. 7. Propel / Doctrine • Propel uses XML Schema file.12年4月22⽇日星期⽇日
  8. 8. Propel / Doctrine • Propel uses XML Schema file. • Doctrine uses XML/YAML/Annotations.12年4月22⽇日星期⽇日
  9. 9. Propel / Doctrine • Propel uses XML Schema file. • Doctrine uses XML/YAML/Annotations. • Slow & Fat.12年4月22⽇日星期⽇日
  10. 10. Propel / Doctrine • Propel uses XML Schema file. • Doctrine uses XML/YAML/Annotations. • Slow & Fat. • Doctrine is too complicated.12年4月22⽇日星期⽇日
  11. 11. Common characteristic12年4月22⽇日星期⽇日
  12. 12. • XML for configuration file. • XML for schema file. • XML for everything. • Concepts are from Java, too complicated.12年4月22⽇日星期⽇日
  13. 13. Propel XML runtime.conf12年4月22⽇日星期⽇日
  14. 14. <?xml version="1.0"?> <config> <log> <ident>propel-bookstore</ident> <type>console</type> <level>7</level> </log> <propel> <datasources default="bookstore"> <datasource id="bookstore"> <adapter>sqlite</adapter> <connection> <classname>DebugPDO</classname> <dsn>mysql:host=localhost;dbname=bookstore</dsn> <user>testuser</user> <password>password</password> <options> <option id="ATTR_PERSISTENT">false</option> </options> <attributes> <option id="ATTR_EMULATE_PREPARES">true</option> </attributes> <settings> <setting id="charset">utf8</setting> <setting id="queries"> <query>set search_path myschema, public</query><!-- automatically set postgresqls search_path --> <query>INSERT INTO BAR (hey, there)</query><!-- execute some other query --> </setting> </settings> </connection> <slaves> <connection> <dsn>mysql:host=slave-server1; dbname=bookstore</dsn> </connection> <connection> <dsn>mysql:host=slave-server2; dbname=bookstore</dsn> </connection> </slaves> </datasource> </datasources> <debugpdo> <logging> <details> <method> <enabled>true</enabled> </method> <time> <enabled>true</enabled> <precision>3</precision> </time> <mem> <enabled>true</enabled> <precision>1</precision>12年4月22⽇日星期⽇日 </mem>
  15. 15. <datasource id="bookstore"> <adapter>sqlite</adapter> <connection> <classname>DebugPDO</classname> <dsn>mysql:host=localhost;dbname=bookstore</dsn> <user>testuser</user> <password>password</password> <options> <option id="ATTR_PERSISTENT">false</option> </options> <attributes> <option id="ATTR_EMULATE_PREPARES">true</option> </attributes> <settings> <setting id="charset">utf8</setting> <setting id="queries"> <query>set search_path myschema, public</query><!-- automatically set postgresqls search_path --> <query>INSERT INTO BAR (hey, there)</query><!-- execute some other query --> </setting> </settings> </connection> <slaves> <connection> <dsn>mysql:host=slave-server1; dbname=bookstore</dsn> </connection> <connection> <dsn>mysql:host=slave-server2; dbname=bookstore</dsn> </connection> </slaves> </datasource> </datasources> <debugpdo> <logging> <details> <method> <enabled>true</enabled> </method> <time> <enabled>true</enabled> <precision>3</precision> </time> <mem> <enabled>true</enabled> <precision>1</precision> </mem> </details> </logging> </debugpdo> </propel> </config>12年4月22⽇日星期⽇日
  16. 16. 12年4月22⽇日星期⽇日
  17. 17. It should be simpler12年4月22⽇日星期⽇日
  18. 18. Inspirations • JiftyDBI / Perl • KiokuDB / Perl • ActiveRecord / Ruby • Propel / PHP12年4月22⽇日星期⽇日
  19. 19. ActiveRecord Pattern12年4月22⽇日星期⽇日
  20. 20. client = Client.find(10) client = Client.first Client.where("orders_count = ?", params[:orders]) Client.where("created_at >= :start_date AND created_at <= :end_date", {:start_date => params[:start_date], :end_date => params[:end_date]}) Client.order("created_at DESC") Client.limit(5).offset(30)12年4月22⽇日星期⽇日
  21. 21. Object::Declare use Object::Declare [MyApp::Column, MyApp::Param]; my %objects = declare { param foo => !is global, is immutable, valid_values are qw( more values ); column bar => field1 is value, field2 is some_other_value, sub_params are param( is happy ), param ( is sad ); }; print $objects{foo}; # a MyApp::Param object print $objects{bar}; # a MyApp::Column object # Assuming that MyApp::Column::new simply blesses into a hash... print $objects{bar}{sub_params}[0]; # a MyApp::Param object print $objects{bar}{sub_params}[1]; # a MyApp::Param object Audrey Tang 唐鳳 200612年4月22⽇日星期⽇日
  22. 22. Jifty::DBI package Simple; use Jifty::DBI::Schema; use Jifty::DBI::Record schema { column foo => type is text; column bar => type is text; };12年4月22⽇日星期⽇日
  23. 23. Jifty::DBI package TestApp::Model::Phone; use Jifty::DBI::Schema; use Jifty::DBI::Record schema { column user => references TestApp::Model::User by id, is mandatory; column type => ...; column value => validator is sub { ... }, default is sub { } ; };12年4月22⽇日星期⽇日
  24. 24. Jifty Model Schema12年4月22⽇日星期⽇日
  25. 25. Jifty Model Schema ⇛ Action12年4月22⽇日星期⽇日
  26. 26. Jifty Model Schema ⇛ Action ⇛ CRUD12年4月22⽇日星期⽇日
  27. 27. Jifty App::Model::Phone ☚ write once12年4月22⽇日星期⽇日
  28. 28. Jifty App::Model::Phone App::Model::PhoneCollection12年4月22⽇日星期⽇日
  29. 29. Jifty App::Model::Phone App::Model::PhoneCollection App::Action::CreatePhone12年4月22⽇日星期⽇日
  30. 30. Jifty App::Model::Phone App::Model::PhoneCollection App::Action::CreatePhone App::Action::UpdatePhone12年4月22⽇日星期⽇日
  31. 31. Jifty App::Model::Phone App::Model::PhoneCollection App::Action::CreatePhone App::Action::UpdatePhone App::Action::DeletePhone12年4月22⽇日星期⽇日
  32. 32. Jifty App::Model::Phone App::Model::PhoneCollection App::Action::CreatePhone App::Action::UpdatePhone App::Action::DeletePhone $phone->as_create_action()->render();12年4月22⽇日星期⽇日
  33. 33. 12年4月22⽇日星期⽇日
  34. 34. What we need • Can use PHP closures for validation, default value, completion ..etc. • Everything should be lazy. • Simple API • No overdesign. • Mixin schema • CRUD generation. • Front-end CRUD integration.12年4月22⽇日星期⽇日
  35. 35. PHP 5.3 Characteristic • APC is fast. • json_encode / json_decode (file) are slower than require a simple array from php source code. • function is faster than class method. • class method is slower than properties. • magic method is slower than normal class method. • array is faster than object.12年4月22⽇日星期⽇日
  36. 36. $array[] vs array_push https://github.com/c9s/SimpleBench12年4月22⽇日星期⽇日
  37. 37. Function calls https://github.com/c9s/SimpleBench12年4月22⽇日星期⽇日
  38. 38. PHP ORM v112年4月22⽇日星期⽇日
  39. 39. EteDB • Initialize model schema in runtime. • Schema is defined in Model (in __constructor). • MySQL only. • dynamic class generator (using eval) • too slow.12年4月22⽇日星期⽇日
  40. 40. PHP ORM v212年4月22⽇日星期⽇日
  41. 41. LazyRecord • Lazy schema loader • SQL Generator • Lazy attribute for MySQL, PgSQL, SQLite • Lazy class loader • Lazy connection • SplClassLoader • Static class • ... etc generator12年4月22⽇日星期⽇日
  42. 42. Based on SQLBuilder12年4月22⽇日星期⽇日
  43. 43. SQLBuilder • A Simple SQL Generator. • Prevent Injection. • Migration generator. (index, alter table...etc) • Support SQLite, Pgsql, Mysql syntax. • Pure SQL or with named-parameters.12年4月22⽇日星期⽇日
  44. 44. <?php $sqlbuilder = new SQLBuilderQueryBuilder( $driver ); $sql = $sqlbuilder->table(authors)->insert([ name => Mary, address => Paris, ])->build();12年4月22⽇日星期⽇日
  45. 45. -- General syntax INSERT INTO authors ( name , address ) VALUES ( Name , Address ); -- PgSQL INSERT INTO "Authors" ( "Name" , "Address" ) VALUES ( Name , Address ); -- MySQL INSERT INTO `Authors` ( `Name` , `Address` ) VALUES ( Name , Address ); -- PDO INSERT INTO authors ( name , address ) VALUES ( ? , ? ); INSERT INTO authors ( name , address ) VALUES ( :name , :address );12年4月22⽇日星期⽇日
  46. 46. <?php $sql = $builder->table(Member)->select(*) ->where() ->equal( a , bar ) // a = bar ->notEqual( a , bar ) // a != bar ->is( a , null ) // a is null ->isNot( a , null ) // a is not equal ->greater( a , 2011-01-01 ); ->greater( a , [date(2011-01-01)] ); // do not escape ->or()->less( a , 123 ) ->and()->like( content , %content% ); ->group() // and ( a = 123 or b != 123 ) ->is( a , 123 ) ->isNot( b, 123 ) ->ungroup() ->build();12年4月22⽇日星期⽇日
  47. 47. Overview12年4月22⽇日星期⽇日
  48. 48. Model Overview12年4月22⽇日星期⽇日
  49. 49. <?php $author = new Author; $ret = $author->create([ name => "Deflator Test $i", country => Tokyo, confirmed => true, date => new DateTime(2011-01-01 00:00:00), ]); if( $ret->success ) { echo "Created!"; }12年4月22⽇日星期⽇日
  50. 50. <?php $ret = $author->update(array( name => Bar )); if( $ret->success ) { echo "Updated!"; } else { echo $ret; // __toString support }12年4月22⽇日星期⽇日
  51. 51. <?php $record = Author::load(array( name => Foo )); // To find a record with primary key: $record = Author::load( 1 ); // To update a record (static): $ret = Author::update( array( name => Author ))->where() ->equal(id,3) ->execute();12年4月22⽇日星期⽇日
  52. 52. $author->toJson(); $author->toArray(); $author->toXml(); $author->toYaml();12年4月22⽇日星期⽇日
  53. 53. Collection Overview12年4月22⽇日星期⽇日
  54. 54. Iterator <?php $authors = new AuthorCollection; foreach( $authors as $author ) { echo $author->name , "n" }12年4月22⽇日星期⽇日
  55. 55. SQLBuilder Mix-In <?php $names = new NameCollection; $names->where() ->equal(name,Foo) ->groupBy(name,address); ?>12年4月22⽇日星期⽇日
  56. 56. Filter <?php $newCollection = $names->filter(function($item) { // do something else })->filter(function($item) { return $item->confirmed; }); ?>12年4月22⽇日星期⽇日
  57. 57. Each <?php $names->each(function($item) { $item->update([ .... ]); }); ?>12年4月22⽇日星期⽇日
  58. 58. Collection Pager <?php /* page 1, 10 per page */ $authors = new AuthorCollection; $pager = $authors->pager(1,10); $pager = $authors->pager(); $items = $pager->items(); $pager->next(); // next page ?> Integrate with OFFSET & LIMIT12年4月22⽇日星期⽇日
  59. 59. Relationship <?php // has many $address = $author->addresses->create([ address => farfaraway ]); // create related address $author->addresses[] = [ address => Harvard ]; $addresses = $author->addresses->items(); foreach( $author->addresses as $address ) { echo $address->address , "n"; }12年4月22⽇日星期⽇日
  60. 60. Schema12年4月22⽇日星期⽇日
  61. 61. Powered by CascadingAttribute.php12年4月22⽇日星期⽇日
  62. 62. <?php use LazyRecordSchemaSchemaDeclare; class AddressSchema extends SchemaDeclare { function schema() { } }12年4月22⽇日星期⽇日
  63. 63. <?php use LazyRecordSchemaSchemaDeclare; class AddressSchema extends SchemaDeclare { function schema() { $this->column(address) ->varchar(128); } }12年4月22⽇日星期⽇日
  64. 64. <?php use LazyRecordSchemaSchemaDeclare; class AddressSchema extends SchemaDeclare { function schema() { $this->column(address) ->integer(); } }12年4月22⽇日星期⽇日
  65. 65. <?php use LazyRecordSchemaSchemaDeclare; class AddressSchema extends SchemaDeclare { function schema() { $this->column(address) ->timestamp(); } }12年4月22⽇日星期⽇日
  66. 66. Default value & builder12年4月22⽇日星期⽇日
  67. 67. $this->column(name) ->varchar(30) ->default(Default);12年4月22⽇日星期⽇日
  68. 68. $this->column(name) ->varchar(30) ->default( array(current_timestamp) );12年4月22⽇日星期⽇日
  69. 69. $this->column(name) ->varchar(30) ->defaultBuilder(function() { return date(c); })12年4月22⽇日星期⽇日
  70. 70. $this->column(name) ->varchar(30) ->default(Default) ->default( array(current_timestamp) ) ->defaultBuilder(function() { return date(c); })12年4月22⽇日星期⽇日
  71. 71. Validator12年4月22⽇日星期⽇日
  72. 72. $this->column(name) ->varchar(30) ->validator(ValidatorClass)12年4月22⽇日星期⽇日
  73. 73. $this->column(name) ->varchar(30) ->validator( array(ValidatorClass,method) )12年4月22⽇日星期⽇日
  74. 74. $this->column(name) ->varchar(30) ->validator(function_name)12年4月22⽇日星期⽇日
  75. 75. $this->column(name) ->varchar(30) ->validator(function($val) { .... })12年4月22⽇日星期⽇日
  76. 76. Filter12年4月22⽇日星期⽇日
  77. 77. $this->column(name) ->varchar(30) ->filter( function($val) { return preg_replace(#word#,zz,$val); });12年4月22⽇日星期⽇日
  78. 78. Deflator / Inflator12年4月22⽇日星期⽇日
  79. 79. use LazyRecordSchemaSchemaDeclare; class NameSchema extends SchemaDeclare { function schema() { $this->column(created_on) ->date() ->isa(DateTime) ->deflator( function($val) { if( is_a( $val, DateTime ) ) return $val->format(Y-m-d); elseif( is_integer($val) ) { return strftime( %Y-%m-%d , $val ); } return $val; }) ->inflator( function($val) { return new DateTime( $val ); }); } }12年4月22⽇日星期⽇日
  80. 80. $name->created_on; // DateTime object $name->created_on->format(Y-m-d); $name->create([ created_on => new DateTime; ]);12年4月22⽇日星期⽇日
  81. 81. Mixin schema12年4月22⽇日星期⽇日
  82. 82. $this->mixin(MetadataMixinSchema); $this->mixin(I18nMixinSchema); $this->mixin(CommentMinxSchema);12年4月22⽇日星期⽇日
  83. 83. Multiple data source12年4月22⽇日星期⽇日
  84. 84. database.yml data_sources: master: dsn: mysql:host=localhost;dbname=lazy_test user: root pass: 12312312年4月22⽇日星期⽇日
  85. 85. database.yml data_sources: master: dsn: mysql:host=localhost;dbname=lazy_test user: root pass: 123123 slave: dsn: mysql:dbname=lazy_test query_options: { quote_column: true, quote_table: true }12年4月22⽇日星期⽇日
  86. 86. database.yml data_sources: master: dsn: mysql:host=localhost;dbname=lazy_test user: root pass: 123123 slave: dsn: mysql:dbname=lazy_test query_options: { quote_column: true, quote_table: true } schema // data source for writing $this->writeTo(master); // data source for reading $this->readFrom(slave);12年4月22⽇日星期⽇日
  87. 87. 拼裝時刻12年4月22⽇日星期⽇日
  88. 88. LazyBone http://github.com/c9s/LazyBone.git12年4月22⽇日星期⽇日
  89. 89. LazyBone =12年4月22⽇日星期⽇日
  90. 90. LazyRecord + Roller Router + RESTful Plugin + Backbone.js12年4月22⽇日星期⽇日
  91. 91. Install LazyRecord12年4月22⽇日星期⽇日
  92. 92. sudo bash -c "$(curl -s -L https://raw.github.com/c9s/LazyRecord/master/install.sh)"12年4月22⽇日星期⽇日
  93. 93. Define config file12年4月22⽇日星期⽇日
  94. 94. config/database.yml --- bootstrap: - bootstrap.php schema: paths: - model data_sources: default: dsn: sqlite:/tmp/todos.db12年4月22⽇日星期⽇日
  95. 95. $ lazy build-conf config/database.yml Convert YAML to PHP. <?php $config = require .lazy.php; APC caches this automatically.12年4月22⽇日星期⽇日
  96. 96. Define model12年4月22⽇日星期⽇日
  97. 97. <?php class TodoSchema extends LazyRecordSchemaSchemaDeclare { function schema() { $this->column(id) ->primary() ->autoIncrement() ->integer(); $this->column(title) ->text(); $this->column(done) ->boolean() ->default(false); $this->column(created_on) ->defaultBuilder( function() { return date(c); } ) ->timestamp(); } function bootstrap($model) { $model->create(array( title => Foo, )); } }12年4月22⽇日星期⽇日
  98. 98. Create static schema files12年4月22⽇日星期⽇日
  99. 99. 12年4月22⽇日星期⽇日
  100. 100. $ lazy build-schema model/TodoSchema.php12年4月22⽇日星期⽇日
  101. 101. $ lazy build-schema model/TodoSchema.php ... Classmap: ! TodoSchemaProxy => model/TodoSchemaProxy.php ! TodoBase => model/TodoBase.php ! Todo => model/Todo.php ! TodoCollectionBase => model/TodoCollectionBase.php ! TodoCollection => model/TodoCollection.php Done12年4月22⽇日星期⽇日
  102. 102. Initialize database12年4月22⽇日星期⽇日
  103. 103. 12年4月22⽇日星期⽇日
  104. 104. $ lazy build-sql model/TodoSchema.php12年4月22⽇日星期⽇日
  105. 105. $ lazy build-sql model/TodoSchema.php Building SQL for TodoSchema --- SQL for TodoSchema CREATE TABLE todos ( id integer primary key autoincrement, title text, done boolean default 0, created_on timestamp );12年4月22⽇日星期⽇日
  106. 106. Integrate with your application12年4月22⽇日星期⽇日
  107. 107. <?php use LazyRecordConfigLoader; $config = new ConfigLoader; $config->load( __DIR__ . /.lazy.php); $config->init();12年4月22⽇日星期⽇日
  108. 108. Define routes12年4月22⽇日星期⽇日
  109. 109. Roller Router High performance router for PHP12年4月22⽇日星期⽇日
  110. 110. Roller Router • APC cache • FileSystem cache • Use Array to store routes • through PHP extension, can dispatch 1607% faster than pure php version • Annotation reader support • RESTful plugin12年4月22⽇日星期⽇日
  111. 111. $router = new RollerRouter; $router->get( /blog/:id/:title , function($id,$title) { return Blog; }); $router->post( /blog/:year/:month/:id/:title, array(Controller,method) ); $router->any( /path/to/:year , array(Callback,method) , array( year => d+, ));12年4月22⽇日星期⽇日
  112. 112. RouteSet <?php $subroutes = new RollerRouteSet; $subroutes->add( /subitem , $cb ); $routes = new RollerRouteSet; $routes->mount( /item , $subroutes ); /item/subitem => $cb12年4月22⽇日星期⽇日
  113. 113. Dispatch $r = $router->dispatch( isset($_SERVER[PATH_INFO]) ? $_SERVER[PATH_INFO] : / ); if( $r ) { echo $r(); } else { die(Page not found); }12年4月22⽇日星期⽇日
  114. 114. RESTful Plugin12年4月22⽇日星期⽇日
  115. 115. <?php $router = new RollerRouter( null, array( cache_id => router_demo )); $restful = new RollerPluginRESTful(array( prefix => /=/restful )); $restful->setGenericHandler( MyGenericHandler ); $router->addPlugin($restful);12年4月22⽇日星期⽇日
  116. 116. Auto-generated routes GET /=/restful/posts GET /=/restful/posts.json GET /=/restful/posts.yml GET /=/restful/posts/23 GET /=/restful/posts/23.json POST /=/restful/posts/23 DELETE /=/restful/posts/2312年4月22⽇日星期⽇日
  117. 117. Define Your Resource Handler12年4月22⽇日星期⽇日
  118. 118. <?php use RollerPluginRESTfulResourceHandler; use RollerPluginRESTfulGenericHandler; class MyGenericHandler extends GenericHandler { public function create($resource) { } public function load($resource,$id) { } public function update($resource,$id) { } public function delete($resource,$id) { } public function find($resource) { } }12年4月22⽇日星期⽇日
  119. 119. <?php namespace LazyBoneResource; use RollerPluginRESTfulResourceHandler; use Todo; use TodoCollection; class TodoResource extends ResourceHandler { public function create() { $vars = json_decode($this->readInput(),true); $todo = new Todo; $ret = $todo->create($vars); if( $ret->success ) { return $todo->toArray(); } $this->codeBadRequest(); return array( error => $ret->message ); } public function update($id) { $todo = new Todo( $id ); if( ! $todo->id ) { return $this->codeNotFound(); } $vars = json_decode($this->readInput(),true); unset( $vars[created_on] ); // lazy record bug if($vars) { $todo->update( $vars ); return $todo->toArray(); } return $this->codeBadRequest(); } ....12年4月22⽇日星期⽇日
  120. 120. Backbone.js12年4月22⽇日星期⽇日
  121. 121. Todo = Backbone.Model.extend({ // Default attributes for the todo item. defaults: function() { return { title: "empty todo...", done: false // order: Todos.nextOrder(), }; }, // Toggle the `done` state of this todo item. toggle: function() { this.save({done: !this.get("done")}); }, clear: function() { this.destroy(); } });12年4月22⽇日星期⽇日
  122. 122. TodoList = Backbone.Collection.extend({ // Reference to this collections model. model: Todo, url:"/=/todos", done: function() { return this.filter(function(todo){ return todo.get(done); }); }, remaining: function() { return this.without.apply(this, this.done()); }, });12年4月22⽇日星期⽇日
  123. 123. 12年4月22⽇日星期⽇日
  124. 124. Hacking forks welcome! http://github.com/c9s/LazyRecord.git12年4月22⽇日星期⽇日
  125. 125. Q &A ?12年4月22⽇日星期⽇日
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×