介绍
Phoenix 是一个用 Elixir 编写的 Web 开发框架,它实现了服务器端模型视图控制器 (MVC) 模式。它的许多组件和概念对于我们这些具有其他 Web 框架(如 Ruby on Rails 或 Python 的 Django)经验的人来说似乎很熟悉。
Phoenix 提供了两全其美的优势 - 高开发人员生产力和高应用程序性能。它还具有一些有趣的新功能,例如用于实现实时功能的通道和用于超快速度的预编译模板。
如果您已经熟悉 Elixir,那就太好了!如果没有,有很多地方可以学习。
安装
为了构建 Phoenix 应用程序,我们需要在操作系统中安装一些依赖项:
- Erlang VM 和 Elixir 编程语言
- 数据库:Phoenix 推荐 PostgreSQL,但您可以选择其他数据库或不使用数据库
Elixir 1.12 或更高版本
Phoenix 是用 Elixir 编写的,我们的应用程序代码也将使用 Elixir 编写。
如果我们是第一次安装 Elixir,我们还需要安装 Hex 包管理器。Hex 是运行 Phoenix 应用程序(通过安装依赖项)和安装我们可能需要的任何额外依赖项所必需的。
这是安装 Hex 的命令(如果您已经安装了 Hex,它将把 Hex 升级到最新版本):
mix local.hex
要检查我们是否使用了 Elixir 1.12 和 Erlang 22 或更高版本,请运行:
elixir -v
一旦我们有了 Elixir 和 Erlang,我们就可以安装 Phoenix 应用程序生成器了:
mix archive.install hex phx_new
启动并运行
我们可以mix phx.new从任何目录运行以引导我们的 Phoenix 应用程序。Phoenix 将接受我们新项目目录的绝对路径或相对路径。
假设我们的应用程序的名称是hello,让我们运行以下命令:
mix phx.new hello
mix phx.new hello
* creating hello/config/config.exs
* creating hello/config/dev.exs
* creating hello/config/prod.exs
...
Fetch and install dependencies? [Yn]
Phoenix 将会生成我们应用程序所需的所有文件和目录结构。
完成后,它会询问我们是否希望它为我们安装依赖项。让我们当然选是。
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running mix deps.compile
We are almost there! The following steps are missing:
$ cd hello
Then configure your database in config/dev.exs and run:
$ mix ecto.create
Start your Phoenix app with:
$ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phx.server
cd进入 hello 我们刚刚创建的目录:
cd hello
启动 Phoenix 服务器:
mix phx.server
[info] Running HelloWeb.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)
[info] Access HelloWeb.Endpoint at http://localhost:4000
[watch] build finished, watching for changes...
...
关于数据库
Phoenix 假设我们的 PostgreSQL 数据库将有一个postgres具有正确权限的用户帐户和密码“postgres”。如果不是,你可以参照 Mix tasks指南 了解有关该mix ecto.create任务的更多信息。
创建项目指定为MySQL数据库
创建时就可以进行指定
mix phx.new hello_phoenix --database mysql
修改PostgreSQL为MySQL数据库
如果你没有指定,那默认就是PostgreSQL,那就需要进行相关修改
首先将配置改变一下,这个在手册就可以找到:using-mysql
我们需要删除 Postgrex 依赖并为 Myxql 添加一个新依赖
让我们现在打开我们的mix.exs文件并执行此操作。
defmodule HelloPhoenix.MixProject do
use Mix.Project
. . .
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, "~> 1.4.0"},
{:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.6"},
{:myxql, ">= 0.0.0"},
...
]
end
end
接下来,我们需要通过更新配置我们的适配器以使用默认的 MySQL 凭据config/dev.exs:
config :hello_phoenix, HelloPhoenix.Repo,
username: "root",
password: "",
database: "hello_phoenix_dev"
如果我们有一个现有的配置块HelloPhoenix.Repo,我们可以简单地更改值以匹配我们的新值。
还需要在config/test.exs和config/runtime.exs(以前的config/prod.secret.exs)文件中配置正确的值。
config :hello, Hello.Repo,
username: "root",
password: "...",
hostname: "localhost",
database: "hello_test#{System.get_env("MIX_TEST_PARTITION")}",
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 10
...
最后一个更改是打开lib/hello_phoenix/repo.ex并确保:adapter将Ecto.Adapters.MyXQL.
比如我这里默认生成的名称为:hello,那路径就是 lib/hello/repo.ex
我们将 Ecto.Adapters.Postgres
defmodule Hello.Repo do
use Ecto.Repo,
otp_app: :hello,
adapter: Ecto.Adapters.Postgres
end
修改为
defmodule Hello.Repo do
use Ecto.Repo,
otp_app: :hello,
adapter: Ecto.Adapters.MyXQL
end
现在我们需要做的就是获取我们的新依赖,然后我们就可以开始了。
mix do deps.get, compile
安装并配置好我们的新适配器后,我们就可以创建我们的数据库了。
mix ecto.create
使用mix创建我们的数据库
现在我们将创建我们的数据库:
mix ecto.create
Compiling 13 files (.ex)
Generated hello app
The database for Hello.Repo has been created
如果无法创建数据库,请参阅mix ecto.create一般故障排除指南。
注意:如果这是您第一次运行此命令,Phoenix 可能还会要求安装 Rebar。继续安装,因为 Rebar 用于构建 Erlang 包。
创建成功
HelloPhoenix.Repo 的数据库已创建。我们还准备好运行任何迁移,或使用 Ecto 执行我们可能选择的任何其他操作。
mix ecto.migrate
[info] == Running HelloPhoenix.Repo.Migrations.CreateUser.change/0 forward
[info] create table users
[info] == Migrated in 0.2s
启动后
默认情况下,Phoenix 接受端口 4000 上的请求。如果我们将我们最喜欢的 Web 浏览器指向http://localhost:4000,我们应该会看到 Phoenix 框架欢迎页面。
如果您的屏幕如上图所示,恭喜!您现在有一个工作的 Phoenix 应用程序。如果您看不到上面的页面,请尝试通过http://127.0.0.1:4000访问它,然后确保您的操作系统已将“localhost”定义为“127.0.0.1”。
想停止它?我们连续按ctrl-c两次。
目录结构
当我们mix phx.new用来生成一个新的 Phoenix 应用程序时,它会构建一个像这样的顶级目录结构:
├── _build
├── assets
├── config
├── deps
├── lib
│ ├── hello
│ ├── hello.ex
│ ├── hello_web
│ └── hello_web.ex
├── priv
└── test
下面是机器翻译
我们将一一浏览这些目录:
-
_build- 由mix命令行工具创建的目录,它作为 Elixir 的一部分提供,包含所有编译工件。正如我们在“启动并运行”中看到的,mix是您的应用程序的主界面。我们使用 Mix 来编译我们的代码、创建数据库、运行我们的服务器等等。此目录不得签入版本控制,并且可以随时删除。删除它将强制 Mix 从头开始重建您的应用程序。
-
assets- 一个目录,保存与源前端资产相关的所有内容,例如 JavaScript 和 CSS,并由该esbuild工具自动管理。
-
config- 保存项目配置的目录。该config/config.exs文件是您的配置的入口点。在 的末尾config/config.exs,它导入环境特定的配置,可以在 config/dev.exs、config/test.exs和中找到config/prod.exs。最后,config/runtime.exs执行,它是读取秘密和其他动态配置的最佳位置。
-
deps- 一个包含我们所有 Mix 依赖项的目录。您可以在函数定义中找到mix.exs文件中列出的所有依赖项。defp deps do此目录不得签入版本控制,并且可以随时删除。删除它会强制 Mix 从头开始下载所有的 deps。
-
lib- 保存应用程序源代码的目录。该目录分为两个子目录,lib/hello和lib/hello_web. 该lib/hello目录将负责托管您的所有业务逻辑和业务域。它通常直接与数据库交互——它是模型-视图-控制器 (MVC) 架构中的“模型”。lib/hello_web负责将您的业务域公开给世界,在这种情况下,通过 Web 应用程序。它同时拥有 MVC 的视图和控制器。我们将在下一节中更详细地讨论这些目录的内容。
-
priv- 一个目录,用于保存生产中必需但不直接包含在源代码中的所有资源。您通常会在此处保留数据库脚本、翻译文件等。默认情况下,来自assets目录的静态和生成资产也从这里提供。
-
test- 包含我们所有应用程序测试的目录。它通常反映lib.
业务目录
lib/hello 目录
该lib/hello目录托管您的所有业务域。由于我们的项目还没有任何业务逻辑,所以目录大多是空的。您只会找到三个文件:
lib/hello
├── application.ex
├── mailer.ex
└── repo.ex
为了能更快上手,我认为先从控制器(路由)给大家将起,然后到这里
下面我会从路由开始
啊哈
路由
Phoenix 生成的路由器文件是lib/hello_web/router.ex
内容看起来像这样:
defmodule HelloWeb.Router do
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {HelloWeb.LayoutView, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", HelloWeb do
pipe_through :browser
get "/", PageController, :index
end
# Other scopes may use custom stacks.
# scope "/api", HelloWeb do
# pipe_through :api
# end
# ...
end
HTTP
在 scope 块中,我们有我们的第一个实际例子:
get "/", PageController, :index
get是对应于 HTTP GET 的 Phoenix 宏。其他 HTTP 动词也存在类似的宏,包括 POST、PUT、PATCH、DELETE、OPTIONS、CONNECT、TRACE 和 HEAD。
Phoenix 提供了一个出色的工具来查看应用程序中的路由:
mix phx.routes.
mix phx.routes
page_path GET / HelloWeb.PageController :index
...
Resources
除了用于 HTTP 动词(如get、post和put)其中最重要的是resources。
让我们像这样向我们的lib/hello_web/router.ex文件中添加一个资源:
scope "/", HelloWeb do
pipe_through :browser
get "/", PageController, :index
resources "/users", UserController
...
end
现在,我们实际上没有HelloWeb.UserController.
mix phx.routes在项目的根目录下再次运行。您应该会看到如下内容:
...
user_path GET /users HelloWeb.UserController :index
user_path GET /users/:id/edit HelloWeb.UserController :edit
user_path GET /users/new HelloWeb.UserController :new
user_path GET /users/:id HelloWeb.UserController :show
user_path POST /users HelloWeb.UserController :create
user_path PATCH /users/:id HelloWeb.UserController :update
PUT /users/:id HelloWeb.UserController :update
user_path DELETE /users/:id HelloWeb.UserController :delete
...
这是 HTTP 动词、路径和控制器操作的标准矩阵。有一段时间,这被称为 RESTful 路由,但现在大多数人认为这是用词不当。让我们以稍微不同的顺序分别看它们。
- GET 请求/users将调用index操作以显示所有用户。
- GET 请求/users/:id/edit将调用edit带有 ID 的操作,以从数据存储中检索单个用户并以表单形式显示信息以供编辑。
- 一个 GET 请求/users/new将调用该new操作来呈现用于创建新用户的表单。
- GET 请求/users/:id将调用show带有 id 的操作以显示由该 ID 标识的单个用户。
- POST 请求/users将调用create操作以将新用户保存到数据存储。
- PATCH 请求/users/:id将调用update带有 ID 的操作,以将更新的用户保存到数据存储中。
- PUT 请求/users/:id还将调用update带有 ID 的操作,以将更新的用户保存到数据存储中。
- 一个 DELETE 请求/users/:id将调用delete带有 ID 的操作,以从数据存储中删除单个用户。
如果我们不需要所有这些路由,我们可以选择性地使用:only和:except选项来过滤特定操作。
假设我们有一个只读的帖子资源。我们可以这样定义:
resources "/posts", PostController, only: [:index, :show]
运行mix phx.routes表明我们现在只定义了指向索引和显示操作的路由。
post_path GET /posts HelloWeb.PostController :index
post_path GET /posts/:id HelloWeb.PostController :show
同样,如果我们有一个评论资源,并且我们不想提供删除它的路由,我们可以定义这样的路由。
resources "/comments", CommentController, except: [:delete]
现在运行mix phx.routes显示我们拥有除删除操作的 DELETE 请求之外的所有路由。
comment_path GET /comments HelloWeb.CommentController :index
comment_path GET /comments/:id/edit HelloWeb.CommentController :edit
comment_path GET /comments/new HelloWeb.CommentController :new
comment_path GET /comments/:id HelloWeb.CommentController :show
comment_path POST /comments HelloWeb.CommentController :create
comment_path PATCH /comments/:id HelloWeb.CommentController :update
PUT /comments/:id HelloWeb.CommentController :update
嵌套资源
也可以在 Phoenix 路由器中嵌套资源。假设我们还有一个posts与 具有多对一关系的资源users。也就是说,一个用户可以创建很多帖子,而单个帖子只属于一个用户。我们可以通过lib/hello_web/router.ex像这样添加嵌套路由来表示:
resources "/users", UserController do
resources "/posts", PostController
end
当我们mix phx.routes现在运行时,除了users上面看到的路线外,我们还得到了以下一组路线:
...
user_post_path GET /users/:user_id/posts HelloWeb.PostController :index
user_post_path GET /users/:user_id/posts/:id/edit HelloWeb.PostController :edit
user_post_path GET /users/:user_id/posts/new HelloWeb.PostController :new
user_post_path GET /users/:user_id/posts/:id HelloWeb.PostController :show
user_post_path POST /users/:user_id/posts HelloWeb.PostController :create
user_post_path PATCH /users/:user_id/posts/:id HelloWeb.PostController :update
PUT /users/:user_id/posts/:id HelloWeb.PostController :update
user_post_path DELETE /users/:user_id/posts/:id HelloWeb.PostController :delete
...
我们看到这些路由中的每一个都将帖子的范围限定为用户 ID。
对于第一个,我们将调用PostController的index动作,但我们将传入 a user_id。这意味着我们将只显示该个人用户的所有帖子。
相同的范围适用于所有这些路由。
范围路由
路径助手
遇见的一些问题
运行的时候出现:there are pending migrations for repo: Blog.Repo. Try running mix ecto.migrate
in the command line to migrate it
解决方式:
首先尝试一下(它将重置您的数据库,如果您需要保留您的数据,请当心!):
mix ecto.reset
如果无效
只能通过删除_build
文件夹来解决
rm -rf _build/
当然上面是Linux命令,如果你的是Windows,只需要删除文件夹就行。
后面遇见问题我再补充
就是这样