До сих пор мы видели, как использовать базовые типы данных и принципы кодирования виртуальной машины Erlang через язык Elixir. Теперь мы пройдем полный круг и создадим работающее веб-приложение с использованием Phoenix Web Framework.
Phoenix использует серверный шаблон MVC и фактически является верхним слоем многоуровневой модульной системы, включающей Plug (модульная спецификация, используемая для маршрутизации , контроллеров и т. Д.), Ecto (оболочка БД для MongoDB, MySQL, SQLite3, PostgreSQL и MSSQL) и HTTP- сервер (Cowboy).
Структура Феникса покажется знакомой Джанго для Python или Ruby on Rails. И производительность, и скорость разработки приложений были ключевыми факторами при проектировании Phoenix, и в сочетании с функциями реального времени они дают ему мощный потенциал в качестве среды веб-приложений производственного качества.
Начиная
Требуется эликсир, поэтому, пожалуйста, обратитесь к инструкции по установке в начале этой серии.
Нам также потребуется Hex для работы Phoenix
(для установки зависимостей). Вот команда для установки Hex (если у вас уже установлен Hex, он обновит Hex до последней версии):
1
|
$ mix local.hex
|
Если вы еще не ознакомились с языком эликсира, я могу порекомендовать вам продолжить чтение первых шагов этого руководства, прежде чем перейти к этой части.
Обратите внимание, что если вы хотите прочитать краткое руководство, вы также можете обратиться к Руководству по обучающему эликсиру и эрлангу , которое предоставляется командой Phoenix.
Erlang
Примечание. По умолчанию это включено в установку Elixir.
Для запуска Elixir нам понадобится виртуальная машина Erlang, потому что код Elixir компилируется в байтовый код Erlang.
Если вы используете систему на основе Debian, вам может понадобиться явно установить Erlang, чтобы получить все необходимые пакеты.
1
2
3
|
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
$ sudo apt-get update
$ sudo apt-get install esl-erlang
|
Феникс
Теперь, когда мы позаботились об Elixir и Erlang, вы готовы установить архив Mix.
Архив микс действительно похож на Zip-файл, за исключением того, что он содержит приложение, а также скомпилированные файлы BEAM и привязан к определенной версии приложения.
Архив миксов — это то, что мы будем использовать для создания нового базового приложения Phoenix, из которого мы можем построить наше приложение!
Запустите следующее в своем терминале:
1
|
$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez
|
Если архив Phoenix Mix не будет установлен должным образом с помощью этой команды, мы можем загрузить пакет из архивов Phoenix , сохранить его в файловой системе и запустить: mix archive.install /path/to/local/phoenix_new.ez
.
Узел
Нам понадобится node.js версии 5 или выше , поскольку Phoenix будет использовать пакет brunch.io для компиляции статических ресурсов, таких как css и js, которые в свою очередь используют npm
.
Загрузите Node.js со страницы загрузки . При выборе пакета для загрузки важно отметить, что для Phoenix требуется версия 5.0.0 или выше.
Пользователи Mac OS X также могут установить Node.js с помощью homebrew .
Если у вас возникли проблемы с установкой Node, обратитесь к официальному справочному руководству Phoenix.
PostgreSQL
По умолчанию Phoenix настраивает приложения для использования сервера базы данных отношений PostgreSQL, но мы можем переключиться на MySQL, передав флаг --database mysql
при создании нового приложения.
В дальнейшем, работая с моделями Ecto в этом руководстве, мы будем использовать PostgreSQL и адаптер Postgrex.
Чтобы следовать примерам, вы должны установить PostgreSQL. Вики PostgreSQL содержит руководства по установке для различных операционных систем.
Обратите внимание, что Postgrex — это прямая зависимость от Phoenix, и она будет автоматически установлена вместе с остальными нашими зависимостями при запуске нашего приложения.
Пользователь по умолчанию
Phoenix предполагает, что наша база данных PostgreSQL будет иметь учетную запись пользователя postgres
с правильными разрешениями и паролем «postgres». Если это не так, как вы хотите настроить, обратитесь к инструкциям для задачи ecto.create mix, чтобы настроить учетные данные.
Скелет Установить
Если вы хотите, чтобы ваше приложение Phoenix работало только без костей, без Ecto или Plug (без db или brunch.io), создайте свое приложение со следующими флагами --no-brunch
и --no-ecto
:
1
|
mix phoenix.new web —no-brunch —no-ecto
|
Предполетная проверка
К этому моменту вы должны иметь:
- Эликсир
- Erlang (по умолчанию предоставляется при установке Elixir)
- наговор
- Установлен архив миксов Phoenix
- Кроме того , если вы выбрали поддержку БД и статических ресурсов, у вас также будут PostgreSQL и Node.js> = 5.0.0, и в этом случае вы будете готовы к созданию своего приложения.
Создайте свое приложение
Вы можете запустить mix phoenix.new
из любого каталога, чтобы запустить приложение Phoenix.
Для вашего нового проекта Phoenix примет либо абсолютный, либо относительный путь; при условии, что имя нашего приложения — hello_world
, любой из них будет работать нормально:
1
|
$ mix phoenix.new /home/me/code/hello_world
|
1
|
$ mix phoenix.new hello_world
|
Когда вы будете готовы, запустите команду create, и вы получите следующий результат:
1
2
3
4
5
6
7
8
9
|
mix phoenix.new hello_world
* creating hello_world/config/config.exs
* creating hello_world/config/dev.exs
* creating hello_world/config/prod.exs
…
* creating hello_world/web/views/layout_view.ex
* creating hello_world/web/views/page_view.ex
Fetch and install dependencies?
|
Поэтому здесь Phoenix позаботился о создании всей структуры каталогов и файлов для вашего приложения. Вы можете взглянуть на то, что он создает, перейдя непосредственно к файлам в выбранном вами редакторе кода.
Когда это будет сделано, мы увидим приглашение с просьбой установить зависимости. Продолжайте с да:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
Fetch and install dependencies?
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build
We are all set!
$ cd hello_world
$ mix phoenix.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phoenix.server
Before moving on, configure your database in config/dev.exs and run:
$ mix ecto.create
|
Теперь, когда все загружено, мы можем перейти в каталог, в который Elixir mix ecto.create
файлы проекта, и создать базу данных с помощью mix ecto.create
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
$ cd hello_world
$ mix ecto.create
==> connection
Compiling 1 file (.ex)
Generated connection app
==> fs (compile)
Compiled src/sys/inotifywait.erl
Compiled src/sys/fsevents.erl
Compiled src/sys/inotifywait_win32.erl
Compiled src/fs_event_bridge.erl
Compiled src/fs_sup.erl
Compiled src/fs_app.erl
Compiled src/fs_server.erl
Compiled src/fs.erl
…
The database for HelloPhoenix.Repo has been created.
|
Примечание: если вы запускаете эту команду впервые, Phoenix может также попросить установить Rebar. Продолжайте установку, так как Rebar используется для сборки пакетов Erlang.
Проблемы с базой данных
Если вы видите следующую ошибку:
1
2
3
4
5
6
|
State: Postgrex.Protocol
** (Mix) The database for HelloWorld.Repo couldn’t be created: an exception was raised:
** (DBConnection.ConnectionError) tcp connect: connection refused — :econnrefused
(db_connection) lib/db_connection/connection.ex:148: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
|
Убедитесь, что служба PostgreSQL работает и доступна с предоставленными учетными данными пользователя (по умолчанию используется пользователь postgres
с паролем «postgres»).
Запустите веб-сервер Phoenix!
Теперь мы можем запустить сервер для нашего приложения Elixir! Запустите следующее:
1
2
3
|
$ mix phoenix.server
[info] Running HelloWorld.Endpoint with Cowboy using http on port 4000
23 Nov 05:25:14 — info: compiled 5 files into 2 files, copied 3 in 1724ms
|
По умолчанию Phoenix принимает запросы через порт 4000.
Посетите http: // localhost: 4000 , и вы увидите страницу приветствия Phoenix Framework.
Если вы не видите страницу выше, попробуйте получить к ней доступ через http://127.0.0.1:4000 (если localhost не определен в вашей ОС).
Локально, теперь мы можем видеть запросы, обрабатываемые в нашем терминальном сеансе, когда наше приложение выполняется в сеансе iex
. Чтобы остановить это, мы дважды iex
ctrl-c
, как обычно, чтобы остановить iex
.
1
2
3
4
5
6
7
8
9
|
$ mix phoenix.server
[info] Running HelloWorld.Endpoint with Cowboy using http://localhost:4000
28 Nov 15:32:33 — info: compiling
28 Nov 15:32:34 — info: compiled 6 files into 2 files, copied 3 in 5 sec
[info] GET /
[debug] Processing by HelloWorld.PageController.index/2
Parameters: %{}
Pipelines: [:browser]
[info] Sent 200 in 50ms
|
Настройка вашего приложения
Когда Phoenix генерирует для нас новое приложение, оно создает структуру каталогов верхнего уровня, как мы увидим в следующем разделе ниже.
Мы создали новое приложение с помощью команды mix phoenix.new
, которая сгенерировала новое приложение, включая структуру каталогов следующим образом:
1
2
3
4
5
6
7
|
├── _build
├── config
├── deps
├── lib
├── priv
├── test
├── web
|
Сейчас мы будем работать над веб-каталогом, который содержит следующее:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
├── channels
└── user_socket.ex
├── controllers
│ └── page_controller.ex
├── models
├── static
│ ├── assets
│ |
|
|
|
│ |
├── templates
│ ├── layout
│ │ └── app.html.eex
│ └── page
│ └── index.html.eex
└── views
|
|
|
|
├── router.ex
├── gettext.ex
├── web.ex
|
Чтобы изменить логотип в верхней части страницы, нам нужно отредактировать статические ресурсы, которые хранятся в priv/static
. Логотип хранится в каталоге так: priv/static/images/phoenix.png
.
Не стесняйтесь добавлять свою собственную графику здесь; мы свяжем его с CSS и начнем модифицировать шаблон дальше. По умолчанию Phoenix будет компилировать любые статические ресурсы (например, здесь, в каталоге изображений) в рабочий комплект.
Когда нам нужна фаза сборки для js или css, мы app.js
ресурсы в web/static
, а исходные файлы встраиваются в их соответствующий app.js
/ app.css
в priv/static
.
Модификация CSS
Путь к вашему CSS — это web/static/css/phoenix.css
. Чтобы изменить логотип, посмотрите строки 29-36.
01
02
03
04
05
06
07
08
09
10
11
12
|
/* Custom page header */
.header {
border-bottom: 1px solid #e5e5e5;
}
.logo {
width: 519px;
height: 71px;
display: inline-block;
margin-bottom: 1em;
background-image: url(«/images/phoenix.png»);
background-size: 519px 71px;
}
|
Внесите изменения и сохраните файл, и изменения будут автоматически обновлены.
1
2
3
|
28 Nov 15:49:00 — info: copied gript.png in 67ms
28 Nov 15:49:04 — info: compiled phoenix.css and 1 cached file into app.css in 77ms
28 Nov 15:49:33 — info: compiled phoenix.css and 1 cached file into app.css in 75ms
|
Перезагрузите веб-браузер или загрузите http: // localhost: 4000 .
Модификация шаблонов
Чтобы изменить содержимое вашего шаблона, просто просмотрите файлы в web/templates/layout
и web/templates/page
. Вы можете начать изменять файлы, чтобы увидеть изменения в вашем приложении.
Стандартный шаблонизатор Phoenix использует EEx, что означает Embedded Elixir . Все файлы шаблонов имеют расширение .eex
.
Шаблоны ограничены видом, который, в свою очередь, ограничен контроллером.
Phoenix создает каталог web/templates
куда мы можем поместить все это. Для организации лучше всего указывать пространство имен, поэтому, если вы хотите создать новую страницу, это означает, что вам нужно создать новый каталог в web/templates
а затем создать в нем файл index.html.eex
(например, web/templates/<My-New-Page>/index.html.eex
).
Давайте сделаем это сейчас. Создайте web/templates/about/index.html.eex
и сделайте так, чтобы это выглядело так:
1
|
<div class=»jumbotron»> <h2>About my app</h2> </div>
|
Взгляды
В Фениксе, часть представления парадигмы проектирования MVC выполняет несколько важных заданий.
Для одного представления визуализируют шаблоны. Кроме того, они выступают в качестве уровня представления необработанных данных от контроллера, выступая в качестве посредника при подготовке их для использования в шаблоне.
Для примера возьмем общую гипотетическую структуру данных, которая представляет пользователя с полем first_name
полем last_name
. Теперь для шаблона мы хотим показать полное имя пользователя.
Для лучшего подхода мы напишем функцию для объединения first_name
и last_name
и предоставим нам помощника в представлении, чтобы написать чистый, краткий и легко читаемый код шаблона.
Для рендеринга любых шаблонов для нашего AboutController нам нужен AboutView
.
Примечание. Здесь важны имена — первая часть имен представления и контроллера должна совпадать.
Создайте web/views/about_view.ex
и сделайте так, чтобы это выглядело так:
1
2
3
|
defmodule HelloWorld.AboutView do
use HelloWorld.Web, :view
end
|
Маршрутизация
Чтобы увидеть новую страницу, вам нужно будет настроить маршрут и контроллер для вашего представления и шаблона.
Поскольку Phoenix работает над парадигмой MVC, нам нужно заполнить все части. Это не так много работы, хотя.
На простом английском языке: Маршруты отображают уникальные пары HTTP глагол / путь к парам контроллер / действие для дальнейшего выполнения.
Phoenix автоматически создает для нас файл роутера в новом приложении на web/router.ex
. Здесь мы будем работать для следующего раздела.
Маршрут по умолчанию «Добро пожаловать в Феникс!» Страница выглядит следующим образом.
get "/", PageController, :index
Это означает, что нужно перехватить все запросы, сделанные при посещении http: // localhost: 4000 / в браузере (который выдает HTTP- GET
) по пути приложения /
root, и отправить все эти запросы в функцию index
в модуле HelloPhoenix.PageController
определено в web/controllers/page_controller.ex
.
Страница, которую мы собираемся создать, просто скажет «О моем приложении», когда мы укажем нашему браузеру http: // localhost: 4000 / about . Вы можете добавить больше информации, чтобы соответствовать вашему приложению в шаблоне, так что просто впишите и напишите в своем HTML!
Новый маршрут
Для нашей страницы о нас нужно определить маршрут. Так что просто откройте web/router.ex
в текстовом редакторе. По умолчанию он будет содержать следующее; Для получения дополнительной информации о маршрутизации обратитесь к официальному руководству по маршрутизации .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
defmodule HelloPhoenix.Router do
use HelloPhoenix.Web, :router
pipeline :browser do
plug :accepts, [«html»]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, [«json»]
end
scope «/», HelloPhoenix do
pipe_through :browser # Use the default browser stack
get «/», PageController, :index
end
# Other scopes may use custom stacks.
# scope «/api», HelloPhoenix do
# pipe_through :api
# end
end
|
Для нашего раздела about, давайте добавим новый маршрут к маршрутизатору для запроса GET
в /about
. Он будет обработан HelloPhoenix.AboutController
, который мы HelloPhoenix.AboutController
в следующей части.
Для GET
to /about
добавьте эту строку в блок scope "/"
области действия router.ex
:
1
|
get «/about», AboutController, :index
|
Полный блок будет выглядеть так:
1
2
3
4
5
6
|
scope «/», HelloPhoenix do
pipe_through :browser # Use the default browser stack
get «/», PageController, :index
get «/about», AboutController, :index
end
|
Контроллер
Мы настроили маршрут, вид и шаблон. Итак, давайте теперь соберем все части вместе, чтобы мы могли просматривать их в браузере.
Контроллеры определяются как модули Elixir, а действия внутри контроллера являются функциями Elixir. Цель действий — собрать любые данные и выполнить любые задачи, необходимые для рендеринга.
Для маршрута /about
нам нужен модуль HelloWorld.AboutController
с действием index/2
.
Для этого нам нужно создать web/controllers/about_controller.ex
и поместить в него следующее:
1
2
3
4
5
6
7
|
defmodule HelloWorld.AboutController do
use HelloWorld.Web, :controller
def index(conn, _params) do
render conn, «index.html»
end
end
|
Для получения дополнительной информации о контроллерах см. Официальное руководство по контроллерам .
Структура контроллера
Все действия контроллера принимают два аргумента. Первым из них является conn
, структура, которая содержит загрузку данных о запросе.
Второе — это params
, которые являются параметрами запроса. Здесь мы не используем params
и избегаем предупреждений компилятора, добавляя ведущий _
.
Ядром этого действия является render conn, "index.html"
. Это говорит Фениксу найти шаблон index.html.eex
и отобразить его. Phoenix будет искать шаблон в каталоге, названном в честь нашего контроллера, поэтому web/templates/hello
.
Примечание. Использование атома в качестве имени шаблона также будет работать здесь: render conn, :index
, например, при использовании атома :index
. Но шаблон будет выбран на основе заголовков Accept, например, «index.html» или «index.json».
Тестирование нового маршрута
Посещение http: // localhost: 4000 / about URL теперь отобразит шаблон, контроллер, представление и маршрут, которые мы определили до сих пор!
действия
Итак, теперь мы создали страницу и немного настроили приложение. Но как мы на самом деле делаем что-то с пользовательским вводом? Действия.
Запросы для нашей страницы about будут обрабатываться HelloWorld.AboutController
с использованием действия show. Как мы уже определили контроллер на последних шагах, нам просто нужно добавить в код способ сохранения переменной, которая передается через URL-адрес, например: http: // localhost: 4000 / about / weather .
Теперь мы изменим код, чтобы сопоставить новый параметр запроса GET
URL через контроллер и, в конечном итоге, с шаблоном, используя сопоставление с образцом Elixir.
Добавьте следующее в модуль в web/controllers/about_controller.ex
:
1
2
3
|
def show(conn, %{«appName» => appName}) do
render conn, «show.html», appName: appName
end
|
Несколько интересных мест здесь:
- Мы сопоставляем шаблон с параметрами, передаваемыми в функцию show, так что переменная
appName
будет связана со значением из URL. - Для нашего примера URL ( http: // localhost: 4000 / about / weather ) переменная
appName
будет содержать значение weather. - В действии
show
также передается третий аргумент для функции рендеринга: пара ключ / значение, где atom:appName
является ключом, а переменнаяappName
передается в качестве значения.
Полный список web/controllers/about_controller.ex
так:
01
02
03
04
05
06
07
08
09
10
11
|
defmodule HelloWorld.AboutController do
use HelloWorld.Web, :controller
def index(conn, _params) do
render conn, «index.html»
end
def show(conn, %{«appName» => appName}) do
render conn, «show.html», appName: appName
end
end
|
Встраиваемый эликсир
Чтобы, наконец, сначала использовать переменную в нашем шаблоне, нам нужно создать файл для нашего действия show.
Создайте файл web/templates/about/show.html.eex
и добавьте следующее:
1
|
<div class=»jumbotron»> <h2>About <%= @appName %></h2>
|
Мы используем специальный синтаксис EEx <%= %>
для Embedded Elixir. Открывающий тег имеет знак =
, означающий, что код Elixir между ними будет выполнен, и в свою очередь вывод заменит тег.
Наша переменная для имени приложения отображается как @appName
. В этом случае это не атрибут модуля, но на самом деле это особый бит метапрограммированного синтаксиса, который Map.get(assigns, :appName)
. Результат намного приятнее для глаз и намного проще работать с шаблоном.
Определение маршрута
Например, чтобы мы могли видеть маршрут http: // localhost: 4000 / about / weather , нам нужно определить маршрут для связи с действием show
для только что определенного контроллера.
1
2
3
4
5
6
7
|
scope «/», HelloWorld do
pipe_through :browser # Use the default browser stack.
get «/», PageController, :index
get «/about», AboutController, :index
get «/about/:appName», AboutController, :show
end
|
Теперь наша работа завершена! Попробуйте это, посетив URL http: // localhost: 4000 / about / weather .
Вывод
Теперь у вас есть фундаментальные знания для создания приложения Phoenix, его графической настройки и создания маршрутов, действий, контроллеров и представлений для вашего приложения.
Мы затронули настройку функций Ecto для PostgreSQL, но для более подробного ознакомления с частью модели парадигмы MVC, пожалуйста, продолжите чтение в руководстве Ecto .
Что касается взаимодействия с пользователем и создания аутентификации, например, пожалуйста, продолжите свое обучение в руководстве по Plug на официальной документации Phoenix .