Controller

Phoenix adopt an architectural pattern similar to the MVC pattern.

In controller we need to find out:

  • How to access request data, like headers, body and query parameters.
  • How to invoke models.
  • How to render template.

Take a look at lib/app1_web/controllers/page_controller.ex:

defmodule App1Web.PageController do
  use App1Web, :controller

  def home(conn, _params) do
    render(conn, :home, layout: false)
  end
end

Take a look at lib/app1_web.ex:

  def controller do
    quote do
      use Phoenix.Controller,
        formats: [:html, :json],
        layouts: [html: App1Web.Layouts]

      use Gettext, backend: App1Web.Gettext

      import Plug.Conn

      unquote(verified_routes())
    end
  end

Accessing Request Data

_params is a map of query string and form inputs:

  def home(conn, _params) do
    render(conn, :home, layout: false)
  end

Try to add query string with curl:

curl 'localhost:4000?key=1&key=2'

It will be printed on the command line:

[debug] Processing with App1Web.PageController.home/2
  Parameters: %{"key" => 2}
  Pipelines: [:browser]

See if array works:

curl 'localhost:4000?key[]=1&key[]=2'
%{"key" => ["1", "2"]}

Add a routing rule for POST in router.ex:

post "/", PageController, :home
curl -d 'foo=bar' 'localhost:4000?key[]=1&key[]=2'
%{"foo" => "bar", "key" => ["1", "2"]}

JSON also works:

curl -d '{"ok":true}' -H 'content-type: application/json' \
  'localhost:4000?key[]=1&key[]=2'
%{"key" => ["1", "2"], "ok" => true}

Rendering Template

The controler simply called render, add passed :home.

In lib/app1_web/controllers/page_html.ex, it doesn't do much, just called embed_templates and passed the director path.

defmodule App1Web.PageHTML do
  use App1Web, :html

  embed_templates "page_html/*"
end

The embed_templates macro expands to following:

def home(assigns) do
  ~H"""
  <.flash_group flash={@flash} />
  ...
  """
end

And the home function will be called by render.