Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

LazyRecord: The Fast ORM for PHP

11,782 views

Published on

Published in: Technology
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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⽇日星期⽇日

×