第一个应用 #

一、创建项目 #

1.1 生成项目 #

bash
# 创建新项目
mix phx.new hello

# 进入项目目录
cd hello

# 安装依赖
mix deps.get

# 创建数据库
mix ecto.create

1.2 启动服务器 #

bash
# 启动开发服务器
mix phx.server

# 访问 http://localhost:4000

二、理解请求流程 #

2.1 请求处理流程 #

text
用户请求
    │
    ▼
Endpoint (hello_web/endpoint.ex)
    │
    ▼
Router (hello_web/router.ex)
    │
    ▼
Pipeline (browser)
    │
    ▼
Controller (hello_web/controllers/page_controller.ex)
    │
    ▼
View (hello_web/views/page_view.ex)
    │
    ▼
Template (hello_web/controllers/page_html/index.html.heex)
    │
    ▼
响应返回

2.2 Endpoint入口 #

elixir
defmodule HelloWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :hello

  @session_options [
    store: :cookie,
    key: "_hello_key",
    signing_salt: "your_salt"
  ]

  plug Plug.Static,
    at: "/",
    from: :hello,
    gzip: false,
    only: HelloWeb.static_paths()

  plug Plug.Session, @session_options
  plug HelloWeb.Router
end

三、创建第一个页面 #

3.1 添加路由 #

elixir
defmodule HelloWeb.Router do
  use HelloWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", HelloWeb do
    pipe_through :browser

    get "/", PageController, :home
    get "/hello", HelloController, :index
    get "/hello/:name", HelloController, :show
  end
end

3.2 创建控制器 #

elixir
defmodule HelloWeb.HelloController do
  use HelloWeb, :controller

  def index(conn, _params) do
    render(conn, :index)
  end

  def show(conn, %{"name" => name}) do
    render(conn, :show, name: name)
  end
end

3.3 创建视图模块 #

elixir
defmodule HelloWeb.HelloHTML do
  use HelloWeb, :html

  embed_templates "hello_html/*"
end

3.4 创建模板 #

heex
defmodule HelloWeb.HelloHTML do
  use HelloWeb, :html

  embed_templates "hello_html/*"
end
heex
heex

四、使用布局 #

4.1 应用布局 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end
heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

4.2 在模板中使用布局内容 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

五、添加样式 #

5.1 使用CSS #

css
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

5.2 使用Tailwind CSS #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

六、处理表单 #

6.1 创建表单页面 #

elixir
defmodule HelloWeb.Router do
  scope "/", HelloWeb do
    pipe_through :browser

    get "/", PageController, :home
    get "/greet", GreetController, :new
    post "/greet", GreetController, :create
  end
end

6.2 创建表单控制器 #

elixir
defmodule HelloWeb.GreetController do
  use HelloWeb, :controller

  def new(conn, _params) do
    render(conn, :new)
  end

  def create(conn, %{"name" => name}) do
    redirect(conn, to: "/hello/#{name}")
  end
end

6.3 创建表单模板 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

七、使用Flash消息 #

7.1 设置Flash消息 #

elixir
defmodule HelloWeb.GreetController do
  use HelloWeb, :controller

  def create(conn, %{"name" => name}) do
    conn
    |> put_flash(:info, "Hello, #{name}!")
    |> redirect(to: "/hello/#{name}")
  end
end

7.2 显示Flash消息 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

八、JSON响应 #

8.1 创建API路由 #

elixir
defmodule HelloWeb.Router do
  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api", HelloWeb do
    pipe_through :api

    get "/users", UserController, :index
    get "/users/:id", UserController, :show
  end
end

8.2 创建API控制器 #

elixir
defmodule HelloWeb.UserController do
  use HelloWeb, :controller

  def index(conn, _params) do
    users = [
      %{id: 1, name: "Alice"},
      %{id: 2, name: "Bob"}
    ]

    json(conn, users)
  end

  def show(conn, %{"id" => id}) do
    user = %{id: String.to_integer(id), name: "User #{id}"}
    json(conn, user)
  end
end

九、错误处理 #

9.1 自定义错误页面 #

elixir
defmodule HelloWeb.ErrorHTML do
  use HelloWeb, :html

  def render("404.html", _assigns) do
    "Page not found"
  end

  def render("500.html", _assigns) do
    "Internal server error"
  end
end

9.2 自定义错误模板 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end
heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

十、项目结构 #

10.1 目录结构 #

text
hello/
├── config/                 # 配置文件
│   ├── config.exs
│   ├── dev.exs
│   ├── runtime.exs
│   └── test.exs
├── lib/
│   ├── hello/             # 业务逻辑
│   │   ├── application.ex
│   │   ├── repo.ex
│   │   └── accounts/      # Context
│   └── hello_web/         # Web层
│       ├── controllers/
│       ├── components/
│       ├── endpoint.ex
│       ├── router.ex
│       └── views/
├── priv/
│   └── repo/
│       └── migrations/
├── assets/                # 前端资源
│   ├── css/
│   └── js/
├── test/                  # 测试文件
├── mix.exs               # 项目配置
└── README.md

10.2 核心文件说明 #

文件 说明
lib/hello/application.ex OTP应用定义
lib/hello/repo.ex Ecto仓库
lib/hello_web/endpoint.ex HTTP入口
lib/hello_web/router.ex 路由定义
lib/hello_web/controllers/ 控制器
lib/hello_web/components/ 组件
config/ 配置文件

十一、热重载 #

11.1 开发模式热重载 #

Phoenix在开发模式下自动支持热重载:

elixir
config :hello, HelloWeb.Endpoint,
  live_reload: [
    patterns: [
      ~r"priv/static/(?!uploads/).*(js|css|png|jpeg|jpg|gif|svg)$",
      ~r"lib/hello_web/(controllers|live|components)/.*(ex|heex)$"
    ]
  ]

11.2 修改代码后 #

text
修改控制器或模板后,刷新浏览器即可看到变化
Phoenix会自动重新编译并加载修改的模块

十二、总结 #

12.1 学到的内容 #

内容 说明
项目创建 mix phx.new
路由定义 Router模块
控制器 处理请求,返回响应
视图 模板渲染辅助
模板 HEEx模板语法
布局 应用布局模板
Flash 临时消息

12.2 下一步 #

现在你已经创建了第一个Phoenix应用,接下来让我们深入了解 目录结构,理解Phoenix项目的组织方式!

最后更新:2026-03-28