摘要:移動端框架性能測評發(fā)布以來,不少團(tuán)隊(duì)試用了,我發(fā)現(xiàn)大家對這類數(shù)據(jù)庫相關(guān)的庫,第一反應(yīng)就是性能如何,之前確實(shí)沒做太多行業(yè)對比,最近覺得還是有必要做一下性能測試,給大家一個交代的。我會用跟上面提到的和端框架做對比。
移動端orm框架性能測評
flutter_orm_plugin 發(fā)布以來,不少團(tuán)隊(duì)試用了,我發(fā)現(xiàn)大家對這類數(shù)據(jù)庫相關(guān)的庫,第一反應(yīng)就是性能如何,之前確實(shí)沒做太多行業(yè)對比,最近覺得還是有必要做一下性能測試,給大家一個交代的。
在ios端,業(yè)界比較常用的orm框架應(yīng)該是蘋果官方推出的coredata,還有就是realm了。在android端orm框架我挑了三個比較常用的,greendao,realm和activeandroid。我會用flutter_orm_plugin跟上面提到的ios和android端orm框架做對比。 下面我會分別給出測試用例,測試代碼,還有最終數(shù)據(jù)比較的結(jié)果。
測試用例測試用例我列了以下這些
10000次插入數(shù)據(jù)
使用批量接口10000次插入數(shù)據(jù)
10000次讀取數(shù)據(jù)
10000次修改數(shù)據(jù)
使用批量接口10000次修改數(shù)據(jù)
10000次刪除數(shù)據(jù)
使用批量接口10000次刪除數(shù)據(jù)
為什么會有普通插入數(shù)據(jù)和使用批量接口插入數(shù)據(jù)的區(qū)別,大部分orm框架都會對批量操作有一定的優(yōu)化,所以需要對批量操作進(jìn)行測試,但是在平時使用,不一定都能用上批量接口(例如多次數(shù)據(jù)操作不在同一代碼塊,或者在不同的模塊中都要操作數(shù)據(jù)),所以我們會分別對普通操作和批量操作進(jìn)行測試。
android 測試代碼首先我們給出flutter_orm_plugin 的測試代碼,由于不想因?yàn)閒lutter和原生channel通訊產(chǎn)生誤差,我們直接用Luakit來寫lua代碼做測試(greendao、realm、activeandroid、coredata都不涉及flutter和原生channel通訊),flutter_orm_plugin其實(shí)底層就是luakit的orm框架,這個不影響測試準(zhǔn)確性。
循環(huán)插入Luakit定義orm模型結(jié)構(gòu)并做10000次插入,下面的代碼是ios和android通用的。
local Student = { __dbname__ = "test.db", __tablename__ = "Student", studentId = {"TextField",{primary_key = true}}, name = {"TextField",{}}, claName = {"TextField",{}}, teacherName = {"TextField",{}}, score = {"RealField",{}}, } local params = { name = "Student", args = Student, } Table.addTableInfo(params,function () local studentTable = Table("Student”) for i=1,10000 do local s = { studentId = "studentId"..i, name = "name"..i, claName = "claName"..i, teacherName = "teacherName"..i, score = 90, } studentTable(s):save() end end)
activeandroid定義orm模型結(jié)構(gòu)并做10000次插入
@Table(name = "Students") public class Student extends Base { @Column(name = "studentId") public String studentId; @Column(name = "name") public String name; @Column(name = "claName") public String claName; @Column(name = "teacherName") public String teacherName; @Column(name = "score") public float score; public Student() { super(); } @Override public String toString() { return this.studentId; } } for (int i=0 ; i<10000 ;i++) { ActiveAndroid.beginTransaction(); Student s = new Student(); s.studentId = "studentId"+i; s.name = "name"+i; s.teacherName = "teacherName"+i; s.claName = "claName"+i; s.score = 90; s.save(); ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction(); }
realm android 定義orm模型結(jié)構(gòu)并做10000次插入
public class StudentRealm extends RealmObject { @PrimaryKey private String studentId; @Required private String name; @Required private String teacherName; @Required private String claName; private float score; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClaName() { return claName; } public void setClaName(String ClaName) { this.claName = claName; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } public String getStudentId() { return studentId; } public void setStudentId(String id) { this.studentId = id; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } } for (int i=0 ; i<10000 ;i++) { realm.beginTransaction(); StudentRealm realmStudent = realm.createObject(StudentRealm.class,"studentId"+i); realmStudent.setName("name"+i); realmStudent.setTeacherName("setTeacherName"+i); realmStudent.setClaName("setClaName"+i); realmStudent.setScore(90); realm.commitTransaction(); }
GreenDao定義orm模型結(jié)構(gòu)并做10000次插入
@Entity() public class Student { @Id private String studentId; @NotNull private String name; private String claName; private String teacherName; private float score; @Generated(hash = 1491230551) public Student(String studentId, @NotNull String name, String claName, String teacherName, float score) { this.studentId = studentId; this.name = name; this.claName = claName; this.teacherName = teacherName; this.score = score; } @Generated(hash = 1556870573) public Student() { } public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } @NotNull public String getName() { return name; } /** Not-null value; ensure this value is available before it is saved to the database. */ public void setName(@NotNull String name) { this.name = name; } public String getClaName() { return claName; } public void setClaName(String claName) { this.claName = claName; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } } DaoSession daoSession = ((App) getApplication()).getDaoSession(); StudentDao sd = daoSession.getStudentDao(); for (int i = 0; i < 10000; i++) { Student s = new Student(); s.setStudentId("StudentId"+i); s.setClaName("getClaName"+i); s.setScore(90); s.setName("name"+i); s.setTeacherName("tn"+i); sd.insertOrReplace(s); }批量插入
Luakit沒有提供批量插入接口。
active android批量插入10000條數(shù)據(jù)。
ActiveAndroid.beginTransaction(); for (int i=0 ; i<10000 ;i++) { Student s = new Student(); s.studentId = "studentId"+i; s.name = "name"+i; s.teacherName = "teacherName"+i; s.claName = "claName"+i; s.score = 90; s.save(); } ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction();
realm android批量插入10000條數(shù)據(jù)。
Realm realm = Realm.getDefaultInstance(); realm.beginTransaction(); for (int i=0 ; i<10000 ;i++) { StudentRealm realmStudent = realm.createObject(StudentRealm.class,"studentId"+i); realmStudent.setName("name"+i); realmStudent.setTeacherName("setTeacherName"+i); realmStudent.setClaName("setClaName"+i); realmStudent.setScore(90); } realm.commitTransaction();
GreenDao批量插入10000條數(shù)據(jù)
DaoSession daoSession = ((App) getApplication()).getDaoSession(); StudentDao sd = daoSession.getStudentDao(); ArrayList數(shù)據(jù)查詢ss = new ArrayList (); for (int i = 0; i < 10000; i++) { Student s = new Student(); s.setStudentId("StudentId"+i); s.setClaName("getClaName"+i); s.setScore(90); s.setName("name"+i); s.setTeacherName("tn"+i); ss.add(s); } sd.insertOrReplaceInTx(ss);
Luakit做10000次查詢,下面的代碼是ios和android通用的。
local studentTable = Table("Student") for i=1,10000 do local result = studentTable.get:where({"studentId"..i},"studentId = ?"):all() end
active android做10000次查詢。
for (int i=0 ; i<10000 ;i++) { Liststudent = new Select() .from(Student.class) .where("studentId = ?", "studentId"+i) .execute(); }
realm android 做10000次查詢。
for (int i=0 ; i<10000 ;i++) { RealmResultsstudents = realm.where(StudentRealm.class).equalTo("studentId", "studentId"+i).findAll(); List list = realm.copyFromRealm(students); }
GreenDao 做10000次查詢
DaoSession daoSession = ((App) getApplication()).getDaoSession(); StudentDao sd = daoSession.getStudentDao(); for (int i = 0; i < 10000; i++) { List循環(huán)更新s = sd.queryBuilder() .where(StudentDao.Properties.StudentId.eq("StudentId"+i)) .list(); }
Luakit做10000次更新。
local studentTable = Table("Student") for i=1,10000 do local result = studentTable.get:where({"studentId"..i},"studentId = ?"):update({name = "name2”}) end
active android做10000次更新。
for (int i=0 ; i<10000 ;i++) { ActiveAndroid.beginTransaction(); Update update = new Update(Student.class); update.set("name = ?","name2") .where("studentId = ?", "studentId"+i) .execute(); ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction(); }
realm android做10000次更新。
for (int i=0 ; i<10000 ;i++) { realm.beginTransaction(); StudentRealm student = realm.where(StudentRealm.class).equalTo("studentId", "studentId"+i).findFirst(); student.setClaName("ClaName"+(i+1)); realm.copyToRealmOrUpdate(student); realm.commitTransaction(); }
GreenDao做10000次更新。
for (int i = 0; i < 10000; i++) { List批量更新s = sd.queryBuilder() .where(StudentDao.Properties.StudentId.eq("StudentId"+i)) .list(); s.get(0).setName("name2"); sd.update(s.get(0)); }
Luakit沒有批量更新接口。
active android批量更新10000條數(shù)據(jù)。
ActiveAndroid.beginTransaction(); for (int i=0 ; i<10000 ;i++) { Update update = new Update(Student.class); update.set("name = ?","name2") .where("studentId = ?", "studentId"+i) .execute(); } ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction();
realm android批量更新10000條數(shù)據(jù)。
realm.beginTransaction(); for (int i=0 ; i<10000 ;i++) { StudentRealm student = realm.where(StudentRealm.class).equalTo("studentId", "studentId"+i).findFirst(); student.setClaName("ClaName"+(i+1)); realm.copyToRealmOrUpdate(student); } realm.commitTransaction();
GreenDao批量更新10000條數(shù)據(jù)
ArrayList循環(huán)刪除ss = new ArrayList (); for (int i = 0; i < 10000; i++) { List s = sd.queryBuilder() .where(StudentDao.Properties.StudentId.eq("StudentId"+i)) .list(); s.get(0).setName("name2"); ss.add(s.get(0)); } sd.updateInTx(ss);
Luakit做10000次刪除操作。
local studentTable = Table("Student") for i=1,10000 do studentTable.get:where({"studentId"..i},"studentId = ?"):delete() end
active android做10000次刪除操作。
for (int i=0 ; i<10000 ;i++) { ActiveAndroid.beginTransaction(); new Delete().from(Student.class).where("studentId = ?", "studentId"+i).execute(); ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction(); }
realm android做10000次刪除操作。
for (int i=0 ; i<10000 ;i++) { realm.beginTransaction(); StudentRealm student = realm.where(StudentRealm.class).equalTo("studentId", "studentId"+i).findFirst(); student.deleteFromRealm(); realm.commitTransaction(); }
GreenDao做10000次刪除操作。
for (int i = 0; i < 10000; i++) { List批量刪除s = sd.queryBuilder() .where(StudentDao.Properties.StudentId.eq("StudentId"+i)) .list(); s.get(0).setName("name2"); sd.delete(s.get(0)); }
Luakit沒有批量刪除接口。
active android批量刪除10000條數(shù)據(jù)。
ActiveAndroid.beginTransaction(); for (int i=0 ; i<10000 ;i++) { new Delete().from(Student.class).where("studentId = ?", "studentId"+i).execute(); } ActiveAndroid.setTransactionSuccessful(); ActiveAndroid.endTransaction();
realm android批量刪除10000條數(shù)據(jù)。
realm.beginTransaction(); for (int i=0 ; i<10000 ;i++) { StudentRealm student = realm.where(StudentRealm.class).equalTo("studentId", "studentId"+i).findFirst(); student.deleteFromRealm(); } realm.commitTransaction();
GreenDao批量刪除10000條數(shù)據(jù)。
ArrayListandroid 測試結(jié)果及分析ss = new ArrayList (); for (int i = 0; i < 10000; i++) { List s = sd.queryBuilder() .where(StudentDao.Properties.StudentId.eq("StudentId"+i)) .list(); ss.add(s.get(0)); } sd.deleteInTx(ss);
下面給出測試結(jié)果,表格中所有數(shù)據(jù)的單位是秒,即做10000次操作需要的秒數(shù)。
可以看到,active android各項(xiàng)性能都一般。
在使用批量接口的情況下GreenDao和Realm的性能比較好。
在使用批量接口的情況下Realm的性能尤其好,批量插入、查詢、批量更改、批量刪除都是Realm的性能最好,但是Realm的非批量接口性能較差,所有可以這樣總結(jié),如果代碼高內(nèi)聚,可以把數(shù)據(jù)操作代碼入口都統(tǒng)一使用,Realm性能是最好的,但這對代碼質(zhì)量、模塊設(shè)計(jì)有要求,當(dāng)操作數(shù)據(jù)的代碼到處都有,不能使用批量接口時,Realm的性能是不好的。
Luakit沒有提供批量接口,但從圖中可以看出,Luakit的各項(xiàng)性能指標(biāo)都是比較好的,而且對代碼沒有要求,即使操作數(shù)據(jù)的代碼不內(nèi)聚,也不會對性能有影響。
ios測試代碼Luakit是跨平臺的,代碼跟android一樣,下面就不列了,只給出Coredata和 Realm ios
循環(huán)插入Coredata 定義orm模型結(jié)構(gòu)并做10000次插入
@interface Student (CoreDataProperties) + (NSFetchRequest*)fetchRequest; @property (nullable, nonatomic, copy) NSString *claName; @property (nullable, nonatomic, copy) NSString *name; @property (nonatomic) float score; @property (nullable, nonatomic, copy) NSString *studentId; @property (nullable, nonatomic, copy) NSString *teacherName; @end self.context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; for (int i=0; i<10000; i++) { Student *s = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context]; s.studentId = [NSString stringWithFormat:@"studentId%d",i]; s.name = [NSString stringWithFormat:@"name%d",i]; s.teacherName = [NSString stringWithFormat:@"teacherName%d",i]; s.claName = [NSString stringWithFormat:@"claName%d",i]; s.score = 90; NSError *error = nil; [self.context save:&error]; }
Realm ios定義orm模型結(jié)構(gòu)并做10000次插入
@interface StudentRLM : RLMObject @property NSString *studentId; @property NSString *name; @property NSString *teacherName; @property NSString *claName; @property float score; @end for (int i=0; i<10000; i++) { [realm beginWriteTransaction]; StudentRLM *s = [[StudentRLM alloc] init]; s.studentId = [NSString stringWithFormat:@"studentId%d",i];; s.name = [NSString stringWithFormat:@"name%d",i]; s.teacherName = [NSString stringWithFormat:@"teacherName%d",i]; s.claName = [NSString stringWithFormat:@"claName%d",i]; s.score = 90; [realm addOrUpdateObject:s]; [realm commitWriteTransaction]; [realm beginWriteTransaction]; }批量插入
Coredata 批量插入10000條數(shù)據(jù)。
for (int i=0; i<10000; i++) { Student *s = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context]; s.studentId = [NSString stringWithFormat:@"studentId%d",i]; s.name = [NSString stringWithFormat:@"name%d",i]; s.teacherName = [NSString stringWithFormat:@"teacherName%d",i]; s.claName = [NSString stringWithFormat:@"claName%d",i]; s.score = 90; } NSError *error = nil; [self.context save:&error];
Realm ios批量插入10000條數(shù)據(jù)。
[realm beginWriteTransaction]; for (int i=0; i<10000; i++) { StudentRLM *s = [[StudentRLM alloc] init]; s.studentId = [NSString stringWithFormat:@"studentId%d",i];; s.name = [NSString stringWithFormat:@"name%d",i]; s.teacherName = [NSString stringWithFormat:@"teacherName%d",i]; s.claName = [NSString stringWithFormat:@"claName%d",i]; s.score = 90; [realm addOrUpdateObject:s]; } [realm commitWriteTransaction]; [realm beginWriteTransaction];查詢
Coredata 做10000次查詢。
for (int i=0; i<10000; i++) { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; request.predicate = [NSPredicate predicateWithFormat:@"studentId = "studentId%d""]; NSArray *objs = [self.context executeFetchRequest:request error:&error]; }
Realm ios做10000次查詢。
for (int i=0; i<10000; i++) { RLMResults *results = [StudentRLM objectsWhere: [NSString stringWithFormat:@"studentId = "studentId%d"",i]]; StudentRLM *s = results.firstObject; }循環(huán)更新
Coredata 做10000次更新。
for (int i=0; i<10000; i++) { NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntityName:@"Student"]; batchUpdateRequest.predicate = [NSPredicate predicateWithFormat:@"studentId = "studentId%d""]; batchUpdateRequest.propertiesToUpdate = @{@"name" : @"name2"}; batchUpdateRequest.resultType = NSUpdatedObjectsCountResultType; NSBatchUpdateResult *batchResult = [self.context executeRequest:batchUpdateRequest error:&error]; NSError *error = nil; [self.context save:&error]; }
Realm ios做10000次更新。
for (int i=0; i<10000; i++) { [realm beginWriteTransaction]; RLMResults *results = [StudentRLM objectsWhere: [NSString stringWithFormat:@"studentId = "studentId%d"",i]]; NSLog(@"results %lu",(unsigned long)[results count]); StudentRLM *s = results.firstObject; [s setName:@"name"]; [realm addOrUpdateObject:s]; [realm commitWriteTransaction]; }批量更新
Coredata 批量更新10000條數(shù)據(jù)。
for (int i=0; i<10000; i++) { NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntityName:@"Student"]; batchUpdateRequest.predicate = [NSPredicate predicateWithFormat:@"studentId = "studentId%d""]; batchUpdateRequest.propertiesToUpdate = @{@"name" : @"name2"}; batchUpdateRequest.resultType = NSUpdatedObjectsCountResultType; NSBatchUpdateResult *batchResult = [self.context executeRequest:batchUpdateRequest error:&error]; } NSError *error = nil; [self.context save:&error];
Realm ios批量更新10000條數(shù)據(jù)。
[realm beginWriteTransaction]; for (int i=0; i<10000; i++) { RLMResults *results = [StudentRLM objectsWhere: [NSString stringWithFormat:@"studentId = "studentId%d"",i]]; NSLog(@"results %lu",(unsigned long)[results count]); StudentRLM *s = results.firstObject; [s setName:@"name”]; [realm addOrUpdateObject:s]; } [realm commitWriteTransaction];循環(huán)刪除
Coredata 做10000次刪除操作。
for (int i=0; i<10000; i++) { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; request.predicate = [NSPredicate predicateWithFormat:@"studentId = "studentId%d""]; NSBatchDeleteRequest *batchRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request]; batchRequest.resultType = NSUpdatedObjectsCountResultType; NSBatchUpdateResult *batchResult = [self.context executeRequest:batchRequest error:&error]; NSError *error = nil; [self.context save:&error]; }
Realm ios做10000次刪除操作。
for (int i=0; i<10000; i++) { [realm beginWriteTransaction]; RLMResults *results = [StudentRLM objectsWhere: [NSString stringWithFormat:@"studentId = "studentId%d"",i]]; StudentRLM *s = results.firstObject; [s setName:@"name"]; [realm deleteObject:s]; [realm commitWriteTransaction]; }批量刪除
Coredata 批量刪除10000條數(shù)據(jù)。
for (int i=0; i<10000; i++) { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; request.predicate = [NSPredicate predicateWithFormat:@"studentId = "studentId%d""]; NSBatchDeleteRequest *batchRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request]; batchRequest.resultType = NSUpdatedObjectsCountResultType; NSBatchUpdateResult *batchResult = [self.context executeRequest:batchRequest error:&error]; } NSError *error = nil; [self.context save:&error];
Realm ios批量刪除10000條數(shù)據(jù)。
[realm beginWriteTransaction]; for (int i=0; i<10000; i++) { RLMResults *results = [StudentRLM objectsWhere: [NSString stringWithFormat:@"studentId = "studentId%d"",i]]; StudentRLM *s = results.firstObject; [s setName:@"name"]; [realm deleteObject:s]; } [realm commitWriteTransaction];ios 測試結(jié)果及分析
下面給出測試結(jié)果,表格中所有數(shù)據(jù)的單位是秒,即做10000次操作需要的秒數(shù)。
可以看到,Coredata除了批量插入性能是最好的以外,其他項(xiàng)性能都一般。
Realm ios和Realm android性能非常相似,批量操作性能優(yōu)異,但是非批量操作性能一般。可以這樣總結(jié),如果代碼高內(nèi)聚,可以把數(shù)據(jù)操作代碼入口都統(tǒng)一使用,Realm性能是最好的,但這對代碼質(zhì)量、模塊設(shè)計(jì)有要求,當(dāng)操作數(shù)據(jù)的代碼到處都有,不能使用批量接口時,Realm的性能是不好的。
Luakit沒有提供批量接口,但從圖中可以看出,Luakit的各項(xiàng)性能指標(biāo)都是比較好的,而且對代碼沒有要求,即使操作數(shù)據(jù)的代碼不內(nèi)聚,也不會對性能有影響。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/75279.html
摘要:以蝸牛將要購買的快杰云服務(wù)器核內(nèi)存促銷方案為例。四快杰云主機(jī)測評蝸牛自己開的是核內(nèi)存帶寬系統(tǒng)盤數(shù)據(jù)盤的快杰云服務(wù)器下面是對性能速度的測評結(jié)果,供大家參考。基本信息內(nèi)存硬盤性能測試。文章目錄 一、快杰云主機(jī)1折特惠 二、UCloud海外云服務(wù)器 三、UCloud特惠云主機(jī)如何領(lǐng)券購買 四、UCloud快杰云主機(jī)測評 優(yōu)刻得UCloud怎么樣?優(yōu)刻得UCloud...
摘要:技術(shù)廣義上,指的是面向?qū)ο蟮膶ο竽P秃完P(guān)系型數(shù)據(jù)庫的數(shù)據(jù)結(jié)構(gòu)之間的相互轉(zhuǎn)換。狹義上,可以被認(rèn)為是,基于關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)存儲,實(shí)現(xiàn)一個虛擬的面向?qū)ο蟮臄?shù)據(jù)訪問接口。 數(shù)據(jù)庫隨筆 背景 目前軟件開發(fā)行業(yè)中,無論是移動端開發(fā)還是后端開發(fā),基本上都會碰到數(shù)據(jù)庫的開發(fā),這里就談?wù)劰P者對于數(shù)據(jù)庫的感想 沖突 在移動端亦或是后端開發(fā)中,很多時候,我們會感覺到無論是 ORM 還是其他方案,都會存在著...
摘要:難道,就沒有強(qiáng)類型特征答案是明確的,肯定有其實(shí)是一種強(qiáng)類型和弱類型的結(jié)合體。強(qiáng)類型語言中,編譯器通常提供編譯檢查錯誤的功能,它也是非常有用的。與此同時,強(qiáng)類型的代碼看起來也是很生硬的。 聲明:本文并非博主原創(chuàng),而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證90%的原汁性,另外因?yàn)槭抢斫夥g,肯定會...
摘要:網(wǎng)站功能結(jié)構(gòu)規(guī)劃和基礎(chǔ)服務(wù)安裝為了快速的構(gòu)建一個網(wǎng)站在這里我們采用飛哥的組件和的框架來做網(wǎng)站實(shí)戰(zhàn)首先我們需要做出一些基礎(chǔ)的規(guī)劃萬丈高樓平地起我們先來給他打下地基做一下簡單的模塊和基本的網(wǎng)站要素規(guī)劃一網(wǎng)站名字快新聞顧名思義就是要做到盡量簡短一 網(wǎng)站功能結(jié)構(gòu)規(guī)劃和基礎(chǔ)服務(wù)安裝 為了快速的構(gòu)建一個go web網(wǎng)站, 在這里, 我們采用 飛哥(fizzday) 的 gorose orm 組件和...
閱讀 1642·2021-09-22 15:21
閱讀 2861·2021-09-09 09:32
閱讀 2681·2021-09-02 09:52
閱讀 3299·2019-08-30 14:02
閱讀 2218·2019-08-26 13:25
閱讀 1447·2019-08-26 13:24
閱讀 1599·2019-08-26 10:31
閱讀 1553·2019-08-26 10:16