1

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陷入了深深的沉思.


Ljzn
399 声望102 粉丝

网络安全;函数式编程;数字货币;人工智能