的确,Elixir 是一个好语言,它的函数式不如 Haskell 那么激烈,也不像 Rust 一类通用语言那样内敛。Elixir 的函数式是折中的,既要实用、又要优雅,同时,借由 Erlang VM 虚拟机的支持,它能够高性能地运行动态类型的代码。
Phoenix 是基于 Elixir 的 Web 框架,是我近期的学习重心。这个框架的学习资料很多,但中文资料较少且比较陈旧,我写这个系列文章的目的是记录我的学习内容。
路由流程
当我们访问 Phoenix 监听的端口,请求会经过 Router
传递给 Controller
。
让我们查看以下 Router
的定义(我的工程名为preflight
,故模块名中带有Preflight
):
该文件位于
lib/${your_project_name}_web/router.ex
1 | defmodule PreflightWeb.Router do |
忽略大部分内容(因为现在的我看不懂),单单看这个模块的几个部分:
1 | defmodule PreflightWeb.Router do |
真正定义了路由操作的是get "/", PageController, :home
,它将访问根目录的GET
请求交予PageContorller.home
处理,我们来看一下该函数的定义:
该模块位于
lib/${your_project_name}_web/controllers/page_controller.ex
1 | defmodule PreflightWeb.PageController do |
这个函数调用了render
函数渲染页面。
等等,问题来了,页面呢?让我们重新审视以下这个函数,谁最像是那个页面?没错,一定是那个:home
。
这个原子变量指向PageHTML
中声明的模板:
该模块位于
lib/${your_project_name}_web/controllers/page_html.ex
1 | defmodule PreflightWeb.PageHTML do |
该模块将page_html
下的所有heex
模板导入到当前目录,我们能够在该目录下发现home.html.heex
,这就是我们真正的渲染对象。
路由宏
上文的get
是 Phoenix 提供的宏,类似的,还有post
、put
、patch
、delete
、options
、connect
、trace
、head
等。
我们可以通过mix phx.routes
检查当前所有的路由:
1 | mix phs.routes |
除了默认的/
路径外,还有一系列 Phoenix 预定义的路径。
resources
resources
是特殊的宏,目的是为了快速生成针对资源的增删改查:
1 | defmodule PreflightWeb.Router do |
将生成以下路由:
1 | GET /users PreflightWeb.UserController :index |
我们可以为该宏传入第三个配置参数来移除个别路由:
1 | # 保留 |
resources
可以嵌套,将生成嵌套路由:
1 | resources "/users", UserController do |
将生成以下结构:
1 | GET /users/:user_id/posts PreflightWeb.PostController :index |
scope
scope
可以声明 API 域:
1 | scope "/admin, PreflightWeb do |
以上调用将该域内定义的请求路由至PreflightWeb
对应的Controller
中。