对于早期Elixir开发者来说,当他们的项目采用Phoenix框架时,他们会感觉避免了开发中很多单调复杂的工作。目前,接受并主张使用Phoenix的开发者数量毫无悬念地在快速增长。更重要的是,Phoenix灵活和健壮的特点可以让你自由地选择以不同的方式来构建APIs。
为什么Phoenix可以如此呢?
在众多的原因中,以下几点是让Phoenix在Web框架之争中保持领先的主要原因:
- 它诞生于Elixir理念:有边界MVC(MVC-bounded)、简单明了、每个上下文单个请求等等
- 它非常的完整:有缺省的ORM、映射路径机制、测试工具,并且还有一个很棒的用以显示程序运行指标的dashboard(稍后会详细介绍)
- 它有非常完善的文档,并拥有一个强大的社区,截至本文撰写时间,在GitHub拥有15.9K颗星
例如,当调用API出错时,Phoenix会确保你收到尽可能多的信息,如下图所示,从代码、堆栈跟踪、堆栈调用等信息中定位问题并发现可以解决问题的办法。
虽然 Phoenix 主要是为单体应用程序的开发而设计的,但它也非常适合微服务。无论你的应用程序大小如何,你都可以轻松创建它,公开其路径映射,并将其置于群集的云服务中,完成这些后,Phoenix将会负责后续的事情。
我们将要构造什么
我们已经知道Phoenix在Elixir API开发中是一个绝佳的选择,但是该怎么使用Phoenix呢?我们在这里展示如何创建一个管理啤酒分类(beer catalog)的web API。
在这里对于你来讲,需要做的是像搭脚手架那样去了解Phoenix API框架的各种概念,这样你就会知道Phoenix是多么地强大。在教程结束,就会得到下面GET /beers的接口定义:
设置
我们先分解一下需要创建这个API例子的步骤。首先,需要按照官方指南在你的电脑上正确地安装Elixir,简单地执行下面的命令就可以完成:
brew install elixir
对于本教程,我们使用版本“Elixir 1.11.2(使用 Erlang/OTP 23 编译)”。 如果你对 Elixir 没有任何了解的话,建议你先看一下官方 Elixir 的学习资料。
其次,我们选择MySQL作为应用程序的数据库,确保你的电脑安装上MySQL Community Server和GUI工具(我个人比较喜欢MySQL Workbench)。对于任何新应用,Phoenix将使用PostgreSQL作为其默认数据库,如果你更习惯于使用PostgresSQL的话,那你可以继续选择它。但为了简单起见,我们这里还是使用MySQL。
最后,你需要一个集成开发环境IDE。对于Elixir开发来说,VS Code是最受欢迎的IDE之一,它提供了一个易于使用名为“vscode-elixir“的扩展,这个扩展可以帮助你完成代码,并对语法语句进行颜色标注等。
创建项目
我们已安装了所需的软件,现在可以开始创建我们的Phoenix web项目了。在你的电脑上选择一个目录,并运行以下命令:
mix archive.install hex phx_new
只要你安装了Elixir,mix命令就自动可以使用。Mix是一个build工具,它可以创建、管理代码各种依赖包(dependencies)、编译和测试Elixir项目。
上面的命令会将Phoenix应用程序安装在当前目录,接着执行下面命令创建Phoenix项目:
mix phx.new beer_catalog
我们这里把项目名称为beer_catalog,上面命令执行完毕后,在项目目录里有一个叫lib/beer_catalog的新文件夹,它是应用程序的主目录。在上一个命令结束时,系统会提示告知你是否要预先获取并安装所有依赖项。选择yes,下面的命令就会被执行:
mix deps.get
数据库配置
现在需要把Phoenix默认的PostgresSQL数据库更改为MySQL,为此,我们需将位于根目录下 mix.exs 文件中对 PostgresSQL的 依赖项更改为以下内容:
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
...{:myxql, ">= 0.0.0"},...
]
end
Elixir使用Ecto作为其项目的默认ORM,它提供了许多功能便于处理对数据库的各种操作,如存储库包装器(wrapper)、变更集、数据规格(Schema)生成等。Ecto需要有采用数据库的适配器,换句话说,适配器其实是Elixir和数据库交互的驱动程序。对于MySQL,我们使用MyXQL.
完成上述配置后,我们需要运行以下命令让Elixir在MySQL服务器创建相应的物理数据库:
mix ecto.create
上述命令还将验证连数据库连接是否正常,如果有问题,Pheonix会将错误日志显示在控制界面(console)上。当上述命令执行完后,在Workbench就会看到新创建的数据库:
Ecto也使用不同的后缀来标识是当前运行环境:
- -dev是本地开发环境
- -test是测试环境
- 没有后缀表示是生产环境。
要运行项目的话,你只需要执行mix phx.server命令即可。因Phoenix运行时把不认为依赖包是最新版本,所以当有任何依赖包提示更新时,确保点“Yes“让其更新,例如rebar3包。当在浏览器输入http://localhost:4000/,你将会看到以下界面:
Beer数据的规格(Schema)
让我们开始数据规格(schema)的设置,在我们的示例应用中,只有一个数据规格需要定义即Beer数据规格。Phoenix可以用下面的命令生成一个简单的数据规格:
mix phx.gen.schema Beer beers brand:string style:string origin:string quantity:integer
上述命令会把后面每个属性及其类型创建到模型中去,并为其创建相应数据迁移脚本,通过迁移脚本将这些属性保存到数据库中。如果你创建你自己APIs的模型时,确保所有的定义尽可能地清晰和有序。
Phoenix 提供了上下文(Contexts)的概念,它定义了一组功能相关联的模块。例如,如果你要定义一个名为User的实体,它通常不会孤立地存在,一个User通常属于一个或多个Account。 考虑到这一点,Phoenix 不会直接创建User的数据规格,而是要你在创建数据规格前先停下来考虑一下定义是否合理。最好使用Account>User这样的分组定义,而不是单个User。对于我们的Beer API来说,假设Beer属于一个Catalog,我们需要把创建数据规格的命令做如下改动:
mix phx.gen.context Catalog Beer beers brand:string style:string origin:string quantity:integer
这样就创建了一个如下有序的全新的数据规格文件:
-lib/beer_catalog/catalog/beer.ex: 这就是Beer数据规格定义。
下面是自动生成的代码:
defmodule BeerCatalog.Catalog.Beer do
use Ecto.Schema
import Ecto.Changesetschema "beers" do
field :brand, :string
field :origin, :string
field :quantity, :integer
field :style, :stringtimestamps()
end@doc false
def changeset(beer, attrs) do
beer
|> cast(attrs, [:brand, :style, :origin, :quantity])
|> validate_required([:brand, :style, :origin, :quantity])
end
end
在代码列表的顶部你可以发现Beer的调用路径包含了Cataglog。
下面还有更让你感到轻松的事情发生:
-lib/beer_catalog/catalog.ex, 当打开这个生成的文件时,你会看到一堆预先为Beer生成的CRUD 操作,基本 CRUD定义已完成了!你也可以根据需要对它们进行修改,不管怎样它们至少把基本工作都完成了!上述命令同时也在priv/repo/migrations/XXX_create_beers.exs创建了数据库迁移脚本文件,以及对数据规格和catalog查询的一些CRUD测试文件。
迁移并植入数据库
在运行CRUD API前,我们需要运行下述命令把上述的迁移脚本在物理数据库上完成相应操作:
mix ecto.migrate
当该命令执行完毕后,在Workbench就会看到新创建的beers表:
Ecto为每个新建的表增加了inserted_at和updated_at两个字段,以便在新插入或更新数据时进行追踪,它也通过schema_migrations来追踪迁移的历史记录。
如果你想用数据库中的数据开启API访问之旅,我们可以通过Ecto的植入功能来实现,它可以在启动应用程序之前插入数据。为此,需在priv/repo/seeds.exs文件里增加以下内容:
BeerCatalog.Catalog.Repo.insert!(%BeerCatalog.Catalog.Beer{
brand: "Milwaukee's Best Light",
style: "American-Style Light Lager",
origin: "USA",
quantity: 1200
})BeerCatalog.Catalog.Repo.insert!(%BeerCatalog.Catalog.Beer{
brand: "Dos Equis",
style: "Lager Especial",
origin: "Mexico",
quantity: 430
})BeerCatalog.Catalog.Repo.insert!(%BeerCatalog.Catalog.Beer{
brand: "Maibock",
style: "Bavarian lager",
origin: "Germany",
quantity: 4000
})
接着,运行下面的命令实现植入:
mix run priv/repo/seeds.exs
一旦上述命令执行完毕,就可以在数据库里看到植入的数据,如下图所示:
创建API的控制器
现在,我们需要执行以下命令生成控制器结构使数据库和 REST端能够进行交互:
mix phx.gen.json Catalog Beer beers brand:string style:string origin:string quantity:integer — no-context — no-schema
这个命令创建了基于JSON的REST资源并通过专门接口处理CRUD操作,因为我们之前已经创建了数据规格(schema)和上下文,所以命令后的两个参数标志是需要的。命令完成后,就可以看到lib/beer_catalog_web/controllers/beer_controller.ex下创建的文件。
最后,我们需要把新创建的资源映射到目前还无法识别它的默认映射路径系统中去,打开lib/beer_catalog_web/router.ex文件,在:api的设置区域内添加下行配置:
resources “/beers”, BeerController, except: [:new, :edit]
它会把所有的HTTP CRUD操作映射到相应的函数。到此为止,我们已经做完了所有准备工作。
测试
如我们之前提到的那样,Phoenix 已经搭建了一些集成测试功能,执行以下命令就可以执行所有测试来验证整个API配置是否正常:
mix test
如果一切都运行正常,可以继续用Postman测试REST端的功能,通过检查数据库数据来检验CRUD操作被正确地执行。
结论
作为红利,Phoenix提供了一个LiveDashboard来显示程序运行指标,输入http://localhost:4000/dashboard/home就可以看到如下所示的dashboard:
这是一个非常好的方式来监控应用程序的运行状况,如进程数量、内存利用率、框架版本等等。
Phoenix已经证明其足够灵活可以满足以你喜欢的方式来构建你的应用程序,并且自动生成工具可以提高你的开发效率并且给那些新手足够的帮助信息。这篇文章描述了Phoenix框架的主要特点,我希望这篇文章可以帮助你在此完美框架上构建应用程序迈出第一步,祝你好运!
{测试窝原创译文,译者:敏子}