介紹
http://keplerproject.github.io/orbit/
Orbit是lua語言版本的MVC框架。
此框架完全拋棄CGILUA的腳本模型, 支持的應用, 每個應用可以卸載一個單獨的文件中,當然你也可以將它拆為一個文件, 當你需要時候。
此框架運行在WSAPI協議的服務器上,所以可以工作在 Xavante和一些CGI和fastcgi程序上。
Orbit is an MVC web framework for Lua. The design is inspired by lightweight Ruby frameworks such as Camping. It completely abandons the CGILua model of "scripts" in favor of applications, where each Orbit application can fit in a single file, but you can split it into multiple files if you want. All Orbit applications follow the WSAPI protocol, so they currently work with Xavante, CGI and Fastcgi. It includes a launcher that makes it easy to launch a Xavante instance for development.
安裝運行
http://keplerproject.github.io/orbit/example.html
此程序依賴 sqlite。
Depending on your configuration, you might need to install the
luasql-sqlite3
andmarkdown
rocks before running the application. Now just start Xavante, and point your browser to blog.ws, and you should see the index page of the blog. If you created a blog.db from scratch you are not going to see any posts, though. The blog application in `samples/blog' includes a blog.db filled with random posts and comments.
安裝:
luarocks search sql
apt-get install sqlite3
luarocks install luasql-sqlite3 SQLITE_DIR=/usr/local
運行
root@fqs:/usr/local/lib/luarocks/rocks/orbit/2.2.4-1/samples/blog# orbit -p 8181 blog.lua
Starting Orbit server at port 8181
使用firefox sqlite插件, 查看db
APP接口
使用orbit.new則構造了一個APP環境, 此環境可以引用全局變量,
同時還定義了 blog應用繼承了 orbit項目的接口, 例如路由的get接口 dispatch_get
local blog = setmetatable(orbit.new(), { __index = _G }) if _VERSION == "Lua 5.2" then _ENV = blog else setfenv(1, blog) end
orbit.new
injects quite a lot of stuff in theblog
module's namespace. The most important of these are thedispatch_get
,dispatch_post
, andmodel
methods that let you define the main functionality of the application.
Creating Models
模型角色負責從數據庫中查詢數據, 后者新建和修改數據。
Our blog application has three kinds of objects: posts, comments, and "static" pages (things like an "About" page for the blog, for example). It's no coincidence that we also have three tables in the database, each table maps to a kind of object our application handles, and for each kind we will create a model. We first create a model object for posts:
posts = blog:model "post"function posts:find_recent() return self:find_all("published_at is not null", { order = "published_at desc", count = recent_count }) end
Defining Controllers
對於請求的URL,執行訪問什么數據, 怎么響應。 訪問數據調用model對象, 響應內容可以是html, 也可以是 xml json等。
Controllers are the interface between the web and your application. With Orbit you can map the path part of your application's URLs (in http://myserver.com/myapp.ws/foo/bar the path is /foo/bar, for example) to controllers. In Lua terms, an Orbit controller is a function that receives a request/response object (usually called
web
) plus parameters extracted from the path, and returns text that is sent to the client (usually HTML, but can be XML, or even an image).
GET請求一個URL,調用模型獲取數據
function index(web) local ps = posts:find_recent() local ms = posts:find_months() local pgs = pgs or pages:find_all() return render_index(web, { posts = ps, months = ms, recent = ps, pages = pgs }) end blog:dispatch_get(cache(index), "/", "/index")
POST修改數據, 調用模型,保存數據 。
function add_comment(web, post_id) local input = web.input if string.find(input.comment, "^%s*$") then return view_post(web, post_id, true) else local comment = comments:new() comment.post_id = tonumber(post_id) comment.body = markdown(input.comment) if not string.find(input.author, "^%s*$") then comment.author = input.author end if not string.find(input.email, "^%s*$") then comment.email = input.email end if not string.find(input.url, "^%s*$") then comment.url = input.url end comment:save() local post = posts:find(tonumber(post_id)) post.n_comments = (post.n_comments or 0) + 1 post:save() cache:invalidate("/") cache:invalidate("/post/" .. post_id) cache:invalidate("/archive/" .. os.date("%Y/%m", post.published_at)) return web:redirect(web:link("/post/" .. post_id)) end end blog:dispatch_post(add_comment, "/post/(%d+)/addcomment")
Views: Generating HTML
視圖定義的一個簡單函數, 在函數中生成視圖內容,例如HTML。
可以直接從控制器中返回,渲染的內容, 但是這里還是建議分離控制器和視圖,這是一個好的編程實踐。
Views are the last component of the MVC triad. For Orbit views are just simple functions that generate content (usually HTML), and are strictly optional, meaning you can return content directly from the controller. But it's still good programming practice to separate controllers and views.
你可使用concat將字符串拼接為視圖結果, 也可以使用一個第三方的模板庫, 將從model中獲取的數據, 使用模板引擎渲染到模板中。
orbit提供了使用的 HTML和XML生成器 orbit.htmlify, 但是你也可以自由選擇其它的你想用的方法。
How you generate content is up to you: concatenate Lua strings, use
table.concat
, use a third-party template library... Orbit provides programmatic HTML/XML generation throughorbit.htmlify
, but you are free to use any method you want. In this tutorial we will stick with programmatic generation, though, as the other methods (straight strings, Cosmo, etc.) are thoroughly documented elsewhere.
orbit.htmlify
function layout(web, args, inner_html) return html{ head{ title(blog_title), meta{ ["http-equiv"] = "Content-Type", content = "text/html; charset=utf-8" }, link{ rel = 'stylesheet', type = 'text/css', href = web:static_link('/style.css'), media = 'screen' } }, body{ div{ id = "container", div{ id = "header", title = "sitename" }, div{ id = "mainnav", _menu(web, args) }, div{ id = "menu", _sidebar(web, args) }, div{ id = "contents", inner_html }, div{ id = "footer", copyright_notice } } } } end
cosmo后台模板引擎
MVC架構中一直提到數據和視圖分離,
如果使用orbit.htmlify模式, 則只能寫出符合DOM結構化的lua代碼, 對於前端代碼如果能用HTML方式書寫,類似JSP格式, 也比orbit提供的這種方式好維護, 前端更加方便定制。
看看lua的后台模板引擎
Overview
Cosmo is a “safe templates” engine. It allows you to fill nested templates, providing many of the advantages of Turing-complete template engines, without without the downside of allowing arbitrary code in the templates.
Simple Form Filling
Let’s start with a simple example of filling a set of scalar values into a template: Here are a few examples of Cosmo in use:
> values = { rank="Ace", suit="Spades" } > template = "$rank of $suit" > require("cosmo") > = cosmo.fill(template, values) Ace of Spades
Note that the template is a string that marks where values should go. The table provides the values.
$rank
will get replaced byvalue.rank
(“Ace”) and$suit
will get replaced byvalue.suit
(“Spades”).
cosmo.fill()
takes two parameters at once. Cosmo also provides a “shortcut” methodf()
which takes only one parameter – the template – and returns a function that then takes the second parameter. This allows for a more compact notation:> = cosmo.f(template){ rank="Ace", suit="Spades" } Ace of Spades