[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-working-with-fw1-and-qb":3},{"id":4,"title":5,"body":6,"date":1449,"description":12,"extension":219,"meta":1450,"navigation":1451,"path":1452,"published":1451,"seo":1453,"slug":1454,"stem":1455,"summary":1456,"tags":1457,"__hash__":1461},"blog/blog/2017-08-22-working-with-fw1-and-qb.md","Working With FW/1 & QB - Steps to Integrate Using Subsystems",{"type":7,"value":8,"toc":1441},"minimark",[9,13,35,38,51,54,57,96,99,159,162,168,173,176,181,186,195,199,206,212,215,293,298,305,401,405,418,495,500,504,507,511,518,541,550,649,652,680,683,692,696,699,702,708,742,745,754,962,969,972,978,984,1001,1006,1009,1016,1020,1022,1025,1057,1060,1067,1099,1104,1149,1154,1197,1202,1242,1251,1300,1307,1406,1410,1419,1422,1425,1434,1437],[10,11,12],"p",{},"Today I wanted to go over a library that I think is pretty awesome and echoes capabilities found in many other modern languages: QB.",[10,14,15,22,23,28,29,34],{},[16,17,21],"a",{"href":18,"rel":19},"https://www.forgebox.io/view/qb",[20],"nofollow","QB"," is a query builder DSL written by ",[16,24,27],{"href":25,"rel":26},"https://github.com/elpete",[20],"Eric Peterson",", who's been putting out some ",[16,30,33],{"href":31,"rel":32},"https://www.forgebox.io/user/elpete",[20],"really cool modular libraries"," for the CFML community.",[10,36,37],{},"With QB, you can:",[39,40,41,45,48],"ul",{},[42,43,44],"li",{},"Quickly scaffold simple queries",[42,46,47],{},"Make complex, out-of-order queries possible",[42,49,50],{},"Abstract away differences between database engines",[10,52,53],{},"The syntax uses a builder pattern that makes writing queries more readable and easy to understand when glancing through code.",[10,55,56],{},"As simple as:",[58,59,64],"pre",{"className":60,"code":61,"language":62,"meta":63,"style":63},"language-js shiki shiki-themes github-light github-dark github-dark monokai","query.from('Posts').get();\n","js","",[65,66,67],"code",{"__ignoreMap":63},[68,69,72,76,80,83,87,90,93],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"s__4a","query.",[68,77,79],{"class":78},"s9ihy","from",[68,81,82],{"class":74},"(",[68,84,86],{"class":85},"svw4x","'Posts'",[68,88,89],{"class":74},").",[68,91,92],{"class":78},"get",[68,94,95],{"class":74},"();\n",[10,97,98],{},"And complex as:",[58,100,102],{"className":60,"code":101,"language":62,"meta":63,"style":63},"query.from('Posts').whereNotNull('PublishDate').whereIn('AuthorID', [1, 2, 3]).get();\n",[65,103,104],{"__ignoreMap":63},[68,105,106,108,110,112,114,116,119,121,124,126,129,131,134,137,141,144,147,149,152,155,157],{"class":70,"line":71},[68,107,75],{"class":74},[68,109,79],{"class":78},[68,111,82],{"class":74},[68,113,86],{"class":85},[68,115,89],{"class":74},[68,117,118],{"class":78},"whereNotNull",[68,120,82],{"class":74},[68,122,123],{"class":85},"'PublishDate'",[68,125,89],{"class":74},[68,127,128],{"class":78},"whereIn",[68,130,82],{"class":74},[68,132,133],{"class":85},"'AuthorID'",[68,135,136],{"class":74},", [",[68,138,140],{"class":139},"s-7EV","1",[68,142,143],{"class":74},", ",[68,145,146],{"class":139},"2",[68,148,143],{"class":74},[68,150,151],{"class":139},"3",[68,153,154],{"class":74},"]).",[68,156,92],{"class":78},[68,158,95],{"class":74},[10,160,161],{},"QB is written to integrate with ColdBox as a module but, in this post, I'll go over how to integrate it as a subsystem in an FW/1 application and mimic the WireBox dependencies with FW/1's baked in dependency injection library, DI/1. While FW/1 and ColdBox have many differences in feature set, their convention to MVC patterns and syntax is still quite relatable.",[163,164,165],"blockquote",{},[10,166,167],{},"If you're ever glancing through ForgeBox and see a standalone library that's built to integrate with ColdBox, integrating it in your FW/1 app might (emphasis on might!) be easier than you think; as I'll demonstrate below.",[169,170,172],"h2",{"id":171},"getting-started","Getting Started",[174,175],"hr",{},[177,178,180],"h3",{"id":179},"prerequisites","Prerequisites",[182,183,185],"h4",{"id":184},"commandbox","CommandBox",[10,187,188,189,194],{},"The examples will be making use of CommandBox to build out dependencies so you will want to have that ",[16,190,193],{"href":191,"rel":192},"https://ortus.gitbooks.io/commandbox-documentation/content/setup/installation.html",[20],"installed",".",[182,196,198],{"id":197},"framework-one-structure","Framework One Structure",[10,200,201,205],{},[202,203,204],"em",{},"I'm going to assume you have a fair grasp of FW/1, configuring DI/1 in an FW/1 application and basic knowledge of how to use FW/1's subsystems feature",". If not, no worries. You'll still be able to follow along and I'll do my best at explaining and pointing out documentation when I can.",[10,207,208,209],{},"In my examples I'll be using Lucee and an H2 database using MySQL dialect, but you can use whatever engine/db combo you'd like. H2 is an in memory database that is easy to set up in a Lucee Application.cfc without having to touch the admin settings. ",[202,210,211],{},"Setting up the H2 driver in Adobe ColdFusion may differ as I've never tried.",[10,213,214],{},"You'll want a basic FW/1 application fleshed out. Create a project directory and name it fw1-qb-example (or whatever you'd like). Next, build out a folder structure that follows the standard conventions like so...",[58,216,220],{"className":217,"code":218,"language":219,"meta":63,"style":63},"language-md shiki shiki-themes github-light github-dark github-dark monokai","fw1-qb-example\n|- /controllers\n|- /layouts\n|- /model\n|-- /data\n|- /subsystems\n|- /views\n|-- /main\n|--- default.cfm\n|--- error.cfm\n|- Application.cfc\n|- index.cfm\n","md",[65,221,222,227,233,239,245,251,257,263,269,275,281,287],{"__ignoreMap":63},[68,223,224],{"class":70,"line":71},[68,225,226],{"class":74},"fw1-qb-example\n",[68,228,230],{"class":70,"line":229},2,[68,231,232],{"class":74},"|- /controllers\n",[68,234,236],{"class":70,"line":235},3,[68,237,238],{"class":74},"|- /layouts\n",[68,240,242],{"class":70,"line":241},4,[68,243,244],{"class":74},"|- /model\n",[68,246,248],{"class":70,"line":247},5,[68,249,250],{"class":74},"|-- /data\n",[68,252,254],{"class":70,"line":253},6,[68,255,256],{"class":74},"|- /subsystems\n",[68,258,260],{"class":70,"line":259},7,[68,261,262],{"class":74},"|- /views\n",[68,264,266],{"class":70,"line":265},8,[68,267,268],{"class":74},"|-- /main\n",[68,270,272],{"class":70,"line":271},9,[68,273,274],{"class":74},"|--- default.cfm\n",[68,276,278],{"class":70,"line":277},10,[68,279,280],{"class":74},"|--- error.cfm\n",[68,282,284],{"class":70,"line":283},11,[68,285,286],{"class":74},"|- Application.cfc\n",[68,288,290],{"class":70,"line":289},12,[68,291,292],{"class":74},"|- index.cfm\n",[163,294,295],{},[10,296,297],{},"Some convention based directories will not be used in my examples such as controllers & layouts.",[10,299,300,301,304],{},"Your framework settings in ",[65,302,303],{},"Application.cfc"," should capture something like this to start:",[58,306,308],{"className":60,"code":307,"language":62,"meta":63,"style":63},"variables.framework = {\n  defaultSection: 'main',\n  defaultItem: 'default',\n  error: 'main.error',\n  diEngine: 'di1',\n  diLocations: '/model',\n  subsystems: {},\n  trace: true,\n  reloadApplicationOnEveryRequest: true\n};\n",[65,309,310,322,333,343,353,363,373,378,388,396],{"__ignoreMap":63},[68,311,312,315,319],{"class":70,"line":71},[68,313,314],{"class":74},"variables.framework ",[68,316,318],{"class":317},"sOw68","=",[68,320,321],{"class":74}," {\n",[68,323,324,327,330],{"class":70,"line":229},[68,325,326],{"class":74},"  defaultSection: ",[68,328,329],{"class":85},"'main'",[68,331,332],{"class":74},",\n",[68,334,335,338,341],{"class":70,"line":235},[68,336,337],{"class":74},"  defaultItem: ",[68,339,340],{"class":85},"'default'",[68,342,332],{"class":74},[68,344,345,348,351],{"class":70,"line":241},[68,346,347],{"class":74},"  error: ",[68,349,350],{"class":85},"'main.error'",[68,352,332],{"class":74},[68,354,355,358,361],{"class":70,"line":247},[68,356,357],{"class":74},"  diEngine: ",[68,359,360],{"class":85},"'di1'",[68,362,332],{"class":74},[68,364,365,368,371],{"class":70,"line":253},[68,366,367],{"class":74},"  diLocations: ",[68,369,370],{"class":85},"'/model'",[68,372,332],{"class":74},[68,374,375],{"class":70,"line":259},[68,376,377],{"class":74},"  subsystems: {},\n",[68,379,380,383,386],{"class":70,"line":265},[68,381,382],{"class":74},"  trace: ",[68,384,385],{"class":139},"true",[68,387,332],{"class":74},[68,389,390,393],{"class":70,"line":271},[68,391,392],{"class":74},"  reloadApplicationOnEveryRequest: ",[68,394,395],{"class":139},"true\n",[68,397,398],{"class":70,"line":277},[68,399,400],{"class":74},"};\n",[182,402,404],{"id":403},"if-running-lucee-setup-for-h2-database","If Running Lucee: Setup For H2 Database",[10,406,407,408,411,412,415,416,194],{},"Create a directory in ",[65,409,410],{},"/model"," called ",[65,413,414],{},"data",". This is where H2 will store it's temp files. Based on the structure above, all you need to do is add a few lines of code to your ",[65,417,303],{},[58,419,421],{"className":60,"code":420,"language":62,"meta":63,"style":63},"this.datasource = 'qb_test';\nthis.datasources[this.datasource] = {\n  class: 'org.h2.Driver',\n  connectionString: 'jdbc:h2:#expandPath(' / model / data / ' & this.datasource)#;MODE=MySQL'\n};\n",[65,422,423,440,456,466,491],{"__ignoreMap":63},[68,424,425,429,432,434,437],{"class":70,"line":71},[68,426,428],{"class":427},"s0XdW","this",[68,430,431],{"class":74},".datasource ",[68,433,318],{"class":317},[68,435,436],{"class":85}," 'qb_test'",[68,438,439],{"class":74},";\n",[68,441,442,444,447,449,452,454],{"class":70,"line":229},[68,443,428],{"class":427},[68,445,446],{"class":74},".datasources[",[68,448,428],{"class":427},[68,450,451],{"class":74},".datasource] ",[68,453,318],{"class":317},[68,455,321],{"class":74},[68,457,458,461,464],{"class":70,"line":235},[68,459,460],{"class":74},"  class: ",[68,462,463],{"class":85},"'org.h2.Driver'",[68,465,332],{"class":74},[68,467,468,471,474,477,480,483,486,488],{"class":70,"line":241},[68,469,470],{"class":74},"  connectionString: ",[68,472,473],{"class":85},"'jdbc:h2:#expandPath('",[68,475,476],{"class":317}," /",[68,478,479],{"class":74}," model ",[68,481,482],{"class":317},"/",[68,484,485],{"class":74}," data ",[68,487,482],{"class":317},[68,489,490],{"class":85}," ' & this.datasource)#;MODE=MySQL'\n",[68,492,493],{"class":70,"line":247},[68,494,400],{"class":74},[163,496,497],{},[10,498,499],{},"Note: H2 supports a number of mainstream SQL dialects.",[177,501,503],{"id":502},"putting-it-all-together","Putting It All Together",[10,505,506],{},"So far, you should have locked down getting CommandBox and a basic FW/1 structure ready. You may have noticed I didn't include FW/1's actual files in the breakdown. That's because we're going to pull it in as a dependency along with QB. Let's go ahead and do that now.",[182,508,510],{"id":509},"installing-dependencies-with-boxjson","Installing Dependencies With box.json",[10,512,513,514,517],{},"First, we need to fire up CommandBox from a terminal/command prompt, point it at our project and create a project file (",[65,515,516],{},"box.json",") for CommandBox to identify with.",[58,519,523],{"className":520,"code":521,"language":522,"meta":63,"style":63},"language-shell shiki shiki-themes github-light github-dark github-dark monokai","#> box\n#> cd /path/to/fw1-qb-example\n#> init fw1-qb-example\n","shell",[65,524,525,531,536],{"__ignoreMap":63},[68,526,527],{"class":70,"line":71},[68,528,530],{"class":529},"sq-8i","#> box\n",[68,532,533],{"class":70,"line":229},[68,534,535],{"class":529},"#> cd /path/to/fw1-qb-example\n",[68,537,538],{"class":70,"line":235},[68,539,540],{"class":529},"#> init fw1-qb-example\n",[10,542,543,546,547,549],{},[65,544,545],{},"init"," creates our ",[65,548,516],{}," to define dependencies; among other bits, we won't cover today. The file will have pre-generated settings but we really just need something that looks like this:",[58,551,555],{"className":552,"code":553,"language":554,"meta":63,"style":63},"language-json shiki shiki-themes github-light github-dark github-dark monokai","{\n  \"name\": \"fw1-qb-example\",\n  \"dependencies\": {\n    \"fw1\": \"be\",\n    \"qb\": \"x\"\n  },\n  \"installPaths\": {\n    \"fw1\": \"framework\",\n    \"qb\": \"subsystems/qb/\"\n  }\n}\n","json",[65,556,557,562,577,585,597,607,612,619,630,639,644],{"__ignoreMap":63},[68,558,559],{"class":70,"line":71},[68,560,561],{"class":74},"{\n",[68,563,564,568,571,575],{"class":70,"line":229},[68,565,567],{"class":566},"sHysA","  \"name\"",[68,569,570],{"class":74},": ",[68,572,574],{"class":573},"sSnWl","\"fw1-qb-example\"",[68,576,332],{"class":74},[68,578,579,582],{"class":70,"line":235},[68,580,581],{"class":566},"  \"dependencies\"",[68,583,584],{"class":74},": {\n",[68,586,587,590,592,595],{"class":70,"line":241},[68,588,589],{"class":566},"    \"fw1\"",[68,591,570],{"class":74},[68,593,594],{"class":573},"\"be\"",[68,596,332],{"class":74},[68,598,599,602,604],{"class":70,"line":247},[68,600,601],{"class":566},"    \"qb\"",[68,603,570],{"class":74},[68,605,606],{"class":573},"\"x\"\n",[68,608,609],{"class":70,"line":253},[68,610,611],{"class":74},"  },\n",[68,613,614,617],{"class":70,"line":259},[68,615,616],{"class":566},"  \"installPaths\"",[68,618,584],{"class":74},[68,620,621,623,625,628],{"class":70,"line":265},[68,622,589],{"class":566},[68,624,570],{"class":74},[68,626,627],{"class":573},"\"framework\"",[68,629,332],{"class":74},[68,631,632,634,636],{"class":70,"line":271},[68,633,601],{"class":566},[68,635,570],{"class":74},[68,637,638],{"class":573},"\"subsystems/qb/\"\n",[68,640,641],{"class":70,"line":277},[68,642,643],{"class":74},"  }\n",[68,645,646],{"class":70,"line":283},[68,647,648],{"class":74},"}\n",[10,650,651],{},"We've defined 2 key things here:",[39,653,654,674],{},[42,655,656,659,660,665,666,669,670,673],{},[65,657,658],{},"dependencies",": The libraries we want to get from ",[16,661,664],{"href":662,"rel":663},"https://www.forgebox.io/",[20],"ForgeBox",". ",[65,667,668],{},"be"," refers to the latest \"bleeding edge\" version (FW/1 is good about reasonably stable dev releases) and ",[65,671,672],{},"x"," means to get the latest stable release.",[42,675,676,679],{},[65,677,678],{},"installPaths",": Where we want those libraries to be physically placed. FW/1 will go in /framework and QB will go in /subsystems/qb.",[10,681,682],{},"Once our dependencies are fleshed out, we can go ahead and tell CommandBox to install them.",[58,684,686],{"className":520,"code":685,"language":522,"meta":63,"style":63},"#> install\n",[65,687,688],{"__ignoreMap":63},[68,689,690],{"class":70,"line":71},[68,691,685],{"class":529},[182,693,695],{"id":694},"final-settings","Final Settings",[10,697,698],{},"At this point, we now have a functioning FW/1 application with QB set up as a subsystem on a very minimal level. It's time to wire up QB and its components in DI/1. This way we can access it directly in FW/1 and also satisfy its own dependencies.",[10,700,701],{},"For ease of defining paths to QB, we'll create an application mapping.",[10,703,704,705,707],{},"Add this to your ",[65,706,303],{},":",[58,709,711],{"className":60,"code":710,"language":62,"meta":63,"style":63},"this.mappings = {\n    \"/qb\" = expandPath(\"./subsystems/qb\")\n};\n",[65,712,713,724,738],{"__ignoreMap":63},[68,714,715,717,720,722],{"class":70,"line":71},[68,716,428],{"class":427},[68,718,719],{"class":74},".mappings ",[68,721,318],{"class":317},[68,723,321],{"class":74},[68,725,726,729,732,735],{"class":70,"line":229},[68,727,728],{"class":85},"    \"/qb\"",[68,730,731],{"class":74}," = expandPath(",[68,733,734],{"class":85},"\"./subsystems/qb\"",[68,736,737],{"class":74},")\n",[68,739,740],{"class":70,"line":235},[68,741,400],{"class":74},[10,743,744],{},"Next, we will tell DI/1 where QB and its components are and define some arguments for a constructor method.",[10,746,747,748,751,752,194],{},"Add this block of code to the empty ",[65,749,750],{},"variables.framework.subsystems"," struct in ",[65,753,303],{},[58,755,757],{"className":60,"code":756,"language":62,"meta":63,"style":63},"qb.diLocations: \"/qb/models\",\nqb.diConfig: {\n    loadListener: function(di1) {\n        di1.declare(\"BaseGrammar\").instanceOf(\"qb.models.Grammars.Grammar\").done()\n           .declare(\"MySQLGrammar\").instanceOf(\"qb.models.Grammars.MySQLGrammar\").done()\n           .declare(\"QueryUtils\").instanceOf(\"qb.models.Query.QueryUtils\").done()\n           .declare(\"QueryBuilder\").instanceOf(\"qb.models.Query.QueryBuilder\")\n           .withOverrides({\n                grammar: di1.getBean(\"MySQLGrammar\"),\n                utils: di1.getBean(\"QueryUtils\"),\n                returnFormat: \"array\"\n           });\n    }\n}\n",[65,758,759,769,774,794,825,852,878,900,910,925,938,946,951,957],{"__ignoreMap":63},[68,760,761,764,767],{"class":70,"line":71},[68,762,763],{"class":74},"qb.diLocations: ",[68,765,766],{"class":85},"\"/qb/models\"",[68,768,332],{"class":74},[68,770,771],{"class":70,"line":229},[68,772,773],{"class":74},"qb.diConfig: {\n",[68,775,776,779,781,785,787,791],{"class":70,"line":235},[68,777,778],{"class":78},"    loadListener",[68,780,570],{"class":74},[68,782,784],{"class":783},"seVH3","function",[68,786,82],{"class":74},[68,788,790],{"class":789},"sYQ0Z","di1",[68,792,793],{"class":74},") {\n",[68,795,796,799,802,804,807,809,812,814,817,819,822],{"class":70,"line":241},[68,797,798],{"class":74},"        di1.",[68,800,801],{"class":78},"declare",[68,803,82],{"class":74},[68,805,806],{"class":85},"\"BaseGrammar\"",[68,808,89],{"class":74},[68,810,811],{"class":78},"instanceOf",[68,813,82],{"class":74},[68,815,816],{"class":85},"\"qb.models.Grammars.Grammar\"",[68,818,89],{"class":74},[68,820,821],{"class":78},"done",[68,823,824],{"class":74},"()\n",[68,826,827,830,832,834,837,839,841,843,846,848,850],{"class":70,"line":247},[68,828,829],{"class":74},"           .",[68,831,801],{"class":78},[68,833,82],{"class":74},[68,835,836],{"class":85},"\"MySQLGrammar\"",[68,838,89],{"class":74},[68,840,811],{"class":78},[68,842,82],{"class":74},[68,844,845],{"class":85},"\"qb.models.Grammars.MySQLGrammar\"",[68,847,89],{"class":74},[68,849,821],{"class":78},[68,851,824],{"class":74},[68,853,854,856,858,860,863,865,867,869,872,874,876],{"class":70,"line":253},[68,855,829],{"class":74},[68,857,801],{"class":78},[68,859,82],{"class":74},[68,861,862],{"class":85},"\"QueryUtils\"",[68,864,89],{"class":74},[68,866,811],{"class":78},[68,868,82],{"class":74},[68,870,871],{"class":85},"\"qb.models.Query.QueryUtils\"",[68,873,89],{"class":74},[68,875,821],{"class":78},[68,877,824],{"class":74},[68,879,880,882,884,886,889,891,893,895,898],{"class":70,"line":259},[68,881,829],{"class":74},[68,883,801],{"class":78},[68,885,82],{"class":74},[68,887,888],{"class":85},"\"QueryBuilder\"",[68,890,89],{"class":74},[68,892,811],{"class":78},[68,894,82],{"class":74},[68,896,897],{"class":85},"\"qb.models.Query.QueryBuilder\"",[68,899,737],{"class":74},[68,901,902,904,907],{"class":70,"line":265},[68,903,829],{"class":74},[68,905,906],{"class":78},"withOverrides",[68,908,909],{"class":74},"({\n",[68,911,912,915,918,920,922],{"class":70,"line":271},[68,913,914],{"class":74},"                grammar: di1.",[68,916,917],{"class":78},"getBean",[68,919,82],{"class":74},[68,921,836],{"class":85},[68,923,924],{"class":74},"),\n",[68,926,927,930,932,934,936],{"class":70,"line":277},[68,928,929],{"class":74},"                utils: di1.",[68,931,917],{"class":78},[68,933,82],{"class":74},[68,935,862],{"class":85},[68,937,924],{"class":74},[68,939,940,943],{"class":70,"line":283},[68,941,942],{"class":74},"                returnFormat: ",[68,944,945],{"class":85},"\"array\"\n",[68,947,948],{"class":70,"line":289},[68,949,950],{"class":74},"           });\n",[68,952,954],{"class":70,"line":953},13,[68,955,956],{"class":74},"    }\n",[68,958,960],{"class":70,"line":959},14,[68,961,648],{"class":74},[10,963,964,965,968],{},"If you have a look in the ",[65,966,967],{},"ModuleConfig.cfc"," in the QB directory, you'll see some declarations set up with WireBox. The above code is essentially the equivalent mimicked in FW/1. Keep in mind, there's more than one way to accomplish what we have above so you may be familiar with a different approach.",[10,970,971],{},"So what's going on here?",[10,973,974,977],{},[65,975,976],{},"qb.diLocations: \"/qb/models\""," tells DI/1 to create a subsystem bean factory and gather objects in /qb/models based on the default conventions.",[10,979,980,983],{},[65,981,982],{},"qb.diConfig"," is more involved...",[10,985,986,987,992,993,996,997,1000],{},"We define a ",[16,988,991],{"href":989,"rel":990},"http://framework-one.github.io/documentation/using-di-one.html#using-load-listeners",[20],"load listener"," with a closure that takes the DI/1 object as an argument. This is for defining our bean factory settings. In the function block, we use DI/1's convenient builder syntax to declare individual bean objects of QB's components. The ",[65,994,995],{},"declare()"," method is used to define an \"alias\" to the component. This is useful for having DI/1 automagically satisfy an object's constructor arguments. The last declaration of \"QueryBuilder\" calls ",[65,998,999],{},"withOverrides()"," to pass in specific arguments to the the object's constructor, or init method.",[163,1002,1003],{},[10,1004,1005],{},"Note: The declaration of MySQLGrammar. This is specific support in QB for the MySQL dialect. There are other options available. See the /qb/models/Query/Grammars folder.",[10,1007,1008],{},"Now that we've programmatically squared away our component requirements, we're ready to fire up a server and actually do things!",[10,1010,1011,1012,1015],{},"From CommandBox we just need to enter ",[65,1013,1014],{},"start"," and a server will start up and open a browser with our application.",[169,1017,1019],{"id":1018},"examples","Examples",[174,1021],{},[10,1023,1024],{},"To use QB from DI/1, we can call on it like so:",[58,1026,1028],{"className":60,"code":1027,"language":62,"meta":63,"style":63},"builder = getBeanFactory('qb').getBean('QueryBuilder');\n",[65,1029,1030],{"__ignoreMap":63},[68,1031,1032,1035,1037,1040,1042,1045,1047,1049,1051,1054],{"class":70,"line":71},[68,1033,1034],{"class":74},"builder ",[68,1036,318],{"class":317},[68,1038,1039],{"class":78}," getBeanFactory",[68,1041,82],{"class":74},[68,1043,1044],{"class":85},"'qb'",[68,1046,89],{"class":74},[68,1048,917],{"class":78},[68,1050,82],{"class":74},[68,1052,1053],{"class":85},"'QueryBuilder'",[68,1055,1056],{"class":74},");\n",[10,1058,1059],{},"Let's assume some simple scenarios...",[10,1061,1062,1063,1066],{},"Given a ",[65,1064,1065],{},"Posts"," table, return all posts.",[58,1068,1070],{"className":60,"code":1069,"language":62,"meta":63,"style":63},"// Returns an array of structs\nposts = builder.from('Posts').get();\n",[65,1071,1072,1077],{"__ignoreMap":63},[68,1073,1074],{"class":70,"line":71},[68,1075,1076],{"class":529},"// Returns an array of structs\n",[68,1078,1079,1082,1084,1087,1089,1091,1093,1095,1097],{"class":70,"line":229},[68,1080,1081],{"class":74},"posts ",[68,1083,318],{"class":317},[68,1085,1086],{"class":74}," builder.",[68,1088,79],{"class":78},[68,1090,82],{"class":74},[68,1092,86],{"class":85},[68,1094,89],{"class":74},[68,1096,92],{"class":78},[68,1098,95],{"class":74},[10,1100,1062,1101,1103],{},[65,1102,1065],{}," table, return all posts that are not drafts.",[58,1105,1107],{"className":60,"code":1106,"language":62,"meta":63,"style":63},"posts = builder.from('Posts').where('IsDraft', '=', 0).get();\n",[65,1108,1109],{"__ignoreMap":63},[68,1110,1111,1113,1115,1117,1119,1121,1123,1125,1128,1130,1133,1135,1138,1140,1143,1145,1147],{"class":70,"line":71},[68,1112,1081],{"class":74},[68,1114,318],{"class":317},[68,1116,1086],{"class":74},[68,1118,79],{"class":78},[68,1120,82],{"class":74},[68,1122,86],{"class":85},[68,1124,89],{"class":74},[68,1126,1127],{"class":78},"where",[68,1129,82],{"class":74},[68,1131,1132],{"class":85},"'IsDraft'",[68,1134,143],{"class":74},[68,1136,1137],{"class":85},"'='",[68,1139,143],{"class":74},[68,1141,1142],{"class":139},"0",[68,1144,89],{"class":74},[68,1146,92],{"class":78},[68,1148,95],{"class":74},[10,1150,1062,1151,1153],{},[65,1152,1065],{}," table, return post by ID.",[58,1155,1157],{"className":60,"code":1156,"language":62,"meta":63,"style":63},"posts = builder.from('Posts').where('ID', '=', 5).get();\n",[65,1158,1159],{"__ignoreMap":63},[68,1160,1161,1163,1165,1167,1169,1171,1173,1175,1177,1179,1182,1184,1186,1188,1191,1193,1195],{"class":70,"line":71},[68,1162,1081],{"class":74},[68,1164,318],{"class":317},[68,1166,1086],{"class":74},[68,1168,79],{"class":78},[68,1170,82],{"class":74},[68,1172,86],{"class":85},[68,1174,89],{"class":74},[68,1176,1127],{"class":78},[68,1178,82],{"class":74},[68,1180,1181],{"class":85},"'ID'",[68,1183,143],{"class":74},[68,1185,1137],{"class":85},[68,1187,143],{"class":74},[68,1189,1190],{"class":139},"5",[68,1192,89],{"class":74},[68,1194,92],{"class":78},[68,1196,95],{"class":74},[10,1198,1062,1199,1201],{},[65,1200,1065],{}," table, return all posts that include \"CFML\" in the title.",[58,1203,1205],{"className":60,"code":1204,"language":62,"meta":63,"style":63},"posts = builder.from('Posts').whereLike('Title', '%CFML%').get();\n",[65,1206,1207],{"__ignoreMap":63},[68,1208,1209,1211,1213,1215,1217,1219,1221,1223,1226,1228,1231,1233,1236,1238,1240],{"class":70,"line":71},[68,1210,1081],{"class":74},[68,1212,318],{"class":317},[68,1214,1086],{"class":74},[68,1216,79],{"class":78},[68,1218,82],{"class":74},[68,1220,86],{"class":85},[68,1222,89],{"class":74},[68,1224,1225],{"class":78},"whereLike",[68,1227,82],{"class":74},[68,1229,1230],{"class":85},"'Title'",[68,1232,143],{"class":74},[68,1234,1235],{"class":85},"'%CFML%'",[68,1237,89],{"class":74},[68,1239,92],{"class":78},[68,1241,95],{"class":74},[10,1243,1062,1244,1246,1247,1250],{},[65,1245,1065],{}," & ",[65,1248,1249],{},"Authors"," table, return all posts by that author.",[58,1252,1254],{"className":60,"code":1253,"language":62,"meta":63,"style":63},"posts = builder.from('Posts').join('Authors', 'Authors.ID', '=', 'Posts.AuthorID').get();\n",[65,1255,1256],{"__ignoreMap":63},[68,1257,1258,1260,1262,1264,1266,1268,1270,1272,1275,1277,1280,1282,1285,1287,1289,1291,1294,1296,1298],{"class":70,"line":71},[68,1259,1081],{"class":74},[68,1261,318],{"class":317},[68,1263,1086],{"class":74},[68,1265,79],{"class":78},[68,1267,82],{"class":74},[68,1269,86],{"class":85},[68,1271,89],{"class":74},[68,1273,1274],{"class":78},"join",[68,1276,82],{"class":74},[68,1278,1279],{"class":85},"'Authors'",[68,1281,143],{"class":74},[68,1283,1284],{"class":85},"'Authors.ID'",[68,1286,143],{"class":74},[68,1288,1137],{"class":85},[68,1290,143],{"class":74},[68,1292,1293],{"class":85},"'Posts.AuthorID'",[68,1295,89],{"class":74},[68,1297,92],{"class":78},[68,1299,95],{"class":74},[10,1301,1062,1302,1246,1304,1306],{},[65,1303,1065],{},[65,1305,1249],{}," table, return all posts by that author within a date range.",[58,1308,1310],{"className":60,"code":1309,"language":62,"meta":63,"style":63},"posts = builder\n  .from('Posts')\n  .join('Authors', 'Authors.ID', '=', 'Posts.AuthorID')\n  .whereBetween('PublishDate', createDate('2017', '8', '1'), now())\n  .get();\n",[65,1311,1312,1321,1334,1358,1398],{"__ignoreMap":63},[68,1313,1314,1316,1318],{"class":70,"line":71},[68,1315,1081],{"class":74},[68,1317,318],{"class":317},[68,1319,1320],{"class":74}," builder\n",[68,1322,1323,1326,1328,1330,1332],{"class":70,"line":229},[68,1324,1325],{"class":74},"  .",[68,1327,79],{"class":78},[68,1329,82],{"class":74},[68,1331,86],{"class":85},[68,1333,737],{"class":74},[68,1335,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356],{"class":70,"line":235},[68,1337,1325],{"class":74},[68,1339,1274],{"class":78},[68,1341,82],{"class":74},[68,1343,1279],{"class":85},[68,1345,143],{"class":74},[68,1347,1284],{"class":85},[68,1349,143],{"class":74},[68,1351,1137],{"class":85},[68,1353,143],{"class":74},[68,1355,1293],{"class":85},[68,1357,737],{"class":74},[68,1359,1360,1362,1365,1367,1369,1371,1374,1376,1379,1381,1384,1386,1389,1392,1395],{"class":70,"line":241},[68,1361,1325],{"class":74},[68,1363,1364],{"class":78},"whereBetween",[68,1366,82],{"class":74},[68,1368,123],{"class":85},[68,1370,143],{"class":74},[68,1372,1373],{"class":78},"createDate",[68,1375,82],{"class":74},[68,1377,1378],{"class":85},"'2017'",[68,1380,143],{"class":74},[68,1382,1383],{"class":85},"'8'",[68,1385,143],{"class":74},[68,1387,1388],{"class":85},"'1'",[68,1390,1391],{"class":74},"), ",[68,1393,1394],{"class":78},"now",[68,1396,1397],{"class":74},"())\n",[68,1399,1400,1402,1404],{"class":70,"line":247},[68,1401,1325],{"class":74},[68,1403,92],{"class":78},[68,1405,95],{"class":74},[169,1407,1409],{"id":1408},"whats-next","What's Next?",[10,1411,1412,1413,1418],{},"That was just a few examples to scratch the surface of what QB is capable of. You can refer to the ",[16,1414,1417],{"href":1415,"rel":1416},"https://elpete.gitbooks.io/qb/content/",[20],"Official QB Docs"," for more examples. You can always glance through the source code to see what has been implemented as well.",[10,1420,1421],{},"Kudos to Eric Peterson for creating such a cool library.",[10,1423,1424],{},"If you work with FW/1 apps and haven't taken the plunge into incorporating CommandBox / ForgeBox with your typical workflow, I hope this helps get the wheels turning.",[10,1426,1427,1428,1433],{},"I've also put together an ",[16,1429,1432],{"href":1430,"rel":1431},"https://github.com/tonyjunkes/fw1-qb-example",[20],"example application on GitHub"," based on this post.",[10,1435,1436],{},"Happy coding!",[1438,1439,1440],"style",{},"html pre.shiki code .s__4a, html code.shiki .s__4a{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .s9ihy, html code.shiki .s9ihy{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .svw4x, html code.shiki .svw4x{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .s-7EV, html code.shiki .s-7EV{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sOw68, html code.shiki .sOw68{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s0XdW, html code.shiki .s0XdW{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-sepia:#FD971F}html pre.shiki code .sq-8i, html code.shiki .sq-8i{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .sHysA, html code.shiki .sHysA{--shiki-light:#005CC5;--shiki-light-font-style:inherit;--shiki-default:#79B8FF;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sSnWl, html code.shiki .sSnWl{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-sepia:#CFCFC2}html pre.shiki code .seVH3, html code.shiki .seVH3{--shiki-light:#D73A49;--shiki-light-font-style:inherit;--shiki-default:#F97583;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sYQ0Z, html code.shiki .sYQ0Z{--shiki-light:#E36209;--shiki-light-font-style:inherit;--shiki-default:#FFAB70;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}",{"title":63,"searchDepth":229,"depth":229,"links":1442},[1443,1447,1448],{"id":171,"depth":229,"text":172,"children":1444},[1445,1446],{"id":179,"depth":235,"text":180},{"id":502,"depth":235,"text":503},{"id":1018,"depth":229,"text":1019},{"id":1408,"depth":229,"text":1409},"2017-08-22",{},true,"/blog/2017-08-22-working-with-fw1-and-qb",{"title":5,"description":12},"working-with-fw1-and-qb","blog/2017-08-22-working-with-fw1-and-qb","Working With FW/1 & QB",[1458,1459,21,1460],"CFML","FW1","SQL","UEz8rw2IzYM7BC_4Qi6WTGCl7rXMbc7yI34xI55eC1w"]