以 https://www.phoenix-china.org/ 为例.
当我们在浏览器中输入 https://www.phoenix-china.org/
, 按下回车后, 我们将访问phoenix-china论坛. 这是一个使用phoenix框架搭建的网站. 我们省略掉域名的解析等过程, 跟随我们的connection,直接进入phoenix, 看看究竟发生了什么.
接下来我们将称呼connection为Mr.conn.
按图索骥, 在router.ex文件里问路
首先, phoenix把 Mr.conn 带到了web/router.ex
文件, 这里是phoenix世界里的中转站. 我们访问的是根域名, 所以对应的路径是"/":
scope "/", PhoenixChina do
pipe_through [:browser, :browser_session, :admin_browser_session]
get "/", PageController, :index
以上代码表示当浏览器访问路径"/"时, 将会调用PageController
中的:index
函数.
Mr.conn 往 controller 文件走去, 却被叫住了, 原来还要先经过pipi_through [...]
中的一系列手续, 例如:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
进入控制器
"哎!你是来找我的吗?" ,一走进 page 控制器, Mr.conn 就看到有人拿着一大包东西朝他走来. "我就是 :index 啊, 等你好久了. 喏, 这些东西麻烦你帮我送到 templates/page
那里.我的兄弟 index.html
会好好招待你的."
def index(conn, %{"label" => label} = params) do
query = Post
|> order_by(desc: :is_top, desc: :latest_comment_inserted_at)
|> preload([:label, :user, :latest_comment, latest_comment: :user])
query = case PostLabel |> Repo.get_by(content: label) do
nil -> query
label_res -> query |> where(label_id: ^label_res.id)
end
pagination = query
|> Repo.paginate(params)
labels = PostLabel
|> where(is_hide: false)
|> order_by(:order)
|> Repo.all
user_count = Repo.one(from u in User, select: count(u.id))
post_count = Repo.one(from p in Post, select: count(p.id))
comment_count = Repo.one(from c in Comment, select: count(c.id))
conn
|> assign(:current_label, label)
|> assign(:labels, labels)
|> assign(:pagination, pagination)
|> assign(:user_count, user_count)
|> assign(:post_count, post_count)
|> assign(:comment_count, comment_count)
|> render("index.html")
end
Mr.conn 只好拿过包裹, 低头一看, 里面东西还真不少: 标题, 页码... 可是都杂乱地堆在一起. 告别了:index
, Mr.conn 背着包裹向 templates/page 文件前进.
渲染页面
到了 templates/page, Mr.conn 却见到了两个人. "你好, 我是 index.html
, 全名是 index.html.eex
, 旁边这位是来自 views 的page_view.ex
. 他负责page 旗下所有页面的渲染工作." Mr.conn 和他们俩握了握手.
"东西都带来了吗?" 'page_view.ex' 问到.
"带来了, 冒昧地问一句, 这些东西有什么用?"
"它们是 MVC 中的 M, 也就是 Model. 平常存储在数据库里, 渲染页面时需要的话就拿出来用. 什么? 你连 MVC 是什么都不知道? 亏你还走了这么远的路. MVC 是一种用来实现用户接口的设计模式, V 就是view(视图), 也就是我们现在要做的. C 指的是 controller(控制器), 你之前去过的."
"哦哦..明白了." Mr.conn 有点脸红, 突然又想起了什么 "那我呢, 我是 MVC 里的什么?"
"你呀, 就是个跑腿的. 待会儿用户点击链接, 你又要到 router 那儿领任务啦."
"..." Mr.conn陷入了深深的沉思.