Phoenix.Controller

Controllers are used to group common functionality in the same (pluggable) module.

For example, the route:

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

will invoke the show/2 action in the UserController:

defmodule UserController do
  use Phoenix.Controller

  plug :action

  def show(conn, %{"id" => id}) do
    user = Repo.get(User, id)
    render conn, "show.html", user: user
  end
end

An action is just a regular function that receives the connection and the request parameters as arguments. The connection is a Plug.Conn struct, as specified by the Plug library.

Connection

A controller by default provides many convenience functions for manipulating the connection, rendering templates, and more.

Those functions are imported from two modules:

Rendering and layouts

One of the main features provided by controllers is the ability to do content negotiation and render templates based on information sent by the client. Read render/3 to learn more.

It is also important to not confuse Phoenix.Controller.render/3 with Phoenix.View.render/3 in the long term. The former expects a connection and relies on content negotiation while the latter is connection-agnostic and typically invoked from your views.

Plug pipeline

As routers, controllers also have their own plug pipeline. However, different from routers, controllers have a single pipeline:

defmodule UserController do
  use Phoenix.Controller

  plug :authenticate, usernames: ["jose", "eric", "sonny"]
  plug :action

  def show(conn, params) do
    # authenticated users only
  end

  defp authenticate(conn, options) do
    if get_session(conn, :username) in options[:usernames] do
      conn
    else
      conn |> redirect(Router.root_path) |> halt
    end
  end
end

The :action plug must always be invoked and it represents the action to be dispatched to.

Check Phoenix.Controller.Pipeline for more information on plug/2 and how to customize the plug pipeline.

Source

Summary

accepts(conn, accepted)

Performs content negotiation based on the available formats

action_name(conn)

Returns the action name as an atom, raises if unavailable

clear_flash(conn)

Clears all flash messages

controller_module(conn)

Returns the controller module as an atom, raises if unavailable

delete_csrf_token()

Deletes any CSRF token set

endpoint_module(conn)

Returns the endpoint module as an atom, raises if unavailable

fetch_flash(conn, opts \\ [])

Fetches the flash storage

get_csrf_token()

Gets the CSRF token

get_flash(conn)

Returns a previously set flash message or nil

get_flash(conn, key)

Returns a message from flash by key

html(conn, data)

Sends html response

json(conn, data)

Sends JSON response

layout(conn)

Retrieves the current layout

layout_formats(conn)

Retrieves current layout formats

protect_from_forgery(conn, opts \\ [])

Enables CSRF protection

put_flash(conn, key, message)

Persists a value in flash

put_layout(conn, layout)

Stores the layout for rendering

put_layout_formats(conn, formats)

Sets which formats have a layout when rendering

put_new_layout(conn, layout)

Stores the layout for rendering if one was not stored yet

put_new_view(conn, module)

Stores the view for rendering if one was not stored yet

put_view(conn, module)

Stores the view for rendering

redirect(conn, opts)

Sends redirect response to the given url

render(conn, template_or_assigns \\ [])

Render the given template or the default template specified by the current action with the given assigns

render(conn, template, assigns)

Renders the given template and assigns based on the conn information

render(conn, view, template, assigns)
router_module(conn)

Returns the router module as an atom, raises if unavailable

scrub_params(conn, required_key)

Scrubs the parameters from the request

text(conn, data)

Sends text response

view_module(conn)

Retrieves the current view

Functions

accepts(conn, accepted)

Specs:

  • accepts(Plug.Conn.t, [binary]) :: Plug.Conn.t | no_return

Performs content negotiation based on the available formats.

It receives a connection, a list of formats that the server is capable of rendering and then proceeds to perform content negotiation based on the request information. If the client accepts any of the given formats, the request proceeds.

If the request contains a “format” parameter, it is considered to be the format desired by the client. If no “format” parameter is available, this function will parse the “accept” header and find a matching format accordingly.

It is important to notice that browsers have historically sent bad accept headers. For this reason, this function will default to “html” format whenever:

  • the accepted list of arguments contains the “html” format

  • the accept header specified more than one media type preceeded or followed by the wildcard media type “/

This function raises Phoenix.NotAcceptableError, which is rendered with status 406, whenever the server cannot serve a response in any of the formats expected by the client.

Examples

accepts/2 can be invoked as a function:

iex> accepts(conn, ["html", "json"])

or used as a plug:

plug :accepts, ["html", "json"]
plug :accepts, ~w(html json)
Source
action_name(conn)

Specs:

  • action_name(Plug.Conn.t) :: atom

Returns the action name as an atom, raises if unavailable.

Source
clear_flash(conn)

Clears all flash messages.

Source
controller_module(conn)

Specs:

  • controller_module(Plug.Conn.t) :: atom

Returns the controller module as an atom, raises if unavailable.

Source
delete_csrf_token()

Deletes any CSRF token set.

Source
endpoint_module(conn)

Specs:

  • endpoint_module(Plug.Conn.t) :: atom

Returns the endpoint module as an atom, raises if unavailable.

Source
fetch_flash(conn, opts \\ [])

Fetches the flash storage.

Source
get_csrf_token()

Gets the CSRF token.

Source
get_flash(conn)

Returns a previously set flash message or nil.

Examples

iex> conn = put_flash(conn, :notice, "Welcome Back!")
iex> get_flash(conn)
%{"notice" => "Welcome Back!"}
Source
get_flash(conn, key)

Returns a message from flash by key

Examples

iex> conn = put_flash(conn, :notice, "Welcome Back!")
iex> get_flash(conn, :notice)
"Welcome Back!"
Source
html(conn, data)

Specs:

  • html(Plug.Conn.t, iodata) :: Plug.Conn.t

Sends html response.

Examples

iex> html conn, "<html><head>..."
Source
json(conn, data)

Specs:

  • json(Plug.Conn.t, term) :: Plug.Conn.t

Sends JSON response.

It uses the configured :format_encoders under the :phoenix application for :json to pick up the encoder module.

Examples

iex> json conn, %{id: 123}
Source
layout(conn)

Specs:

  • layout(Plug.Conn.t) :: {atom, String.t} | false

Retrieves the current layout.

Source
layout_formats(conn)

Specs:

  • layout_formats(Plug.Conn.t) :: [String.t]

Retrieves current layout formats.

Source
protect_from_forgery(conn, opts \\ [])

Enables CSRF protection.

Currently used as a wrapper function for Plug.CSRFProtection and mainly serves as a function plug in YourApp.Router.

Check get_csrf_token/0 and delete_csrf_token/0 for retrieving and deleting CSRF tokens.

Source
put_flash(conn, key, message)

Persists a value in flash.

Returns the updated connection.

Examples

iex> conn = put_flash(conn, :notice, "Welcome Back!")
iex> get_flash(conn, :notice)
"Welcome Back!"
Source
put_layout(conn, layout)

Specs:

  • put_layout(Plug.Conn.t, {atom, binary} | binary | false) :: Plug.Conn.t

Stores the layout for rendering.

The layout must be a tuple, specifying the layout view and the layout name, or false. In case a previous layout is set, put_layout also accepts the layout name to be given as a string or as an atom. If a string, it must contain the format. Passing an atom means the layout format will be found at rendering time, similar to the template in render/3.

Examples

iex> layout(conn)
false

iex> conn = put_layout conn, {AppView, "application"}
iex> layout(conn)
{AppView, "application"}

iex> conn = put_layout conn, "print"
iex> layout(conn)
{AppView, "print"}

iex> conn = put_layout :print
iex> layout(conn)
{AppView, :print}

Raises Plug.Conn.AlreadySentError if the conn was already sent.

Source
put_layout_formats(conn, formats)

Specs:

  • put_layout_formats(Plug.Conn.t, [String.t]) :: Plug.Conn.t

Sets which formats have a layout when rendering.

Examples

iex> layout_formats conn
["html"]

iex> put_layout_formats conn, ["html", "mobile"]
iex> layout_formats conn
["html", "mobile"]

Raises Plug.Conn.AlreadySentError if the conn was already sent.

Source
put_new_layout(conn, layout)

Specs:

  • put_new_layout(Plug.Conn.t, {atom, binary} | false) :: Plug.Conn.t

Stores the layout for rendering if one was not stored yet.

Raises Plug.Conn.AlreadySentError if the conn was already sent.

Source
put_new_view(conn, module)

Specs:

  • put_new_view(Plug.Conn.t, atom) :: Plug.Conn.t

Stores the view for rendering if one was not stored yet.

Raises Plug.Conn.AlreadySentError if the conn was already sent.

Source
put_view(conn, module)

Specs:

  • put_view(Plug.Conn.t, atom) :: Plug.Conn.t

Stores the view for rendering.

Raises Plug.Conn.AlreadySentError if the conn was already sent.

Source
redirect(conn, opts)

Sends redirect response to the given url.

For security, :to only accepts paths. Use the :external option to redirect to any URL.

Examples

iex> redirect conn, to: "/login"

iex> redirect conn, external: "http://elixir-lang.org"
Source
render(conn, template_or_assigns \\ [])

Specs:

  • render(Plug.Conn.t, Dict.t | binary | atom) :: Plug.Conn.t

Render the given template or the default template specified by the current action with the given assigns.

See render/3 for more information.

Source
render(conn, template, assigns)

Specs:

  • render(Plug.Conn.t, module, binary | atom) :: Plug.Conn.t
  • render(Plug.Conn.t, binary | atom, Dict.t) :: Plug.Conn.t

Renders the given template and assigns based on the conn information.

Once the template is rendered, the template format is set as the response content type (for example, an HTML template will set “text/html” as response content type) and the data is sent to the client with default status of 200.

Arguments

  • conn - the Plug.Conn struct

  • template - which may be an atom or a string. If an atom, like :index, it will render a template with the same format as the one found in conn.params["format"]. For example, for an HTML request, it will render the “index.html” template. If the template is a string, it must contain the extension too, like “index.json”

  • assigns - a dictionary with the assigns to be used in the view. Those assigns are merged and have higher precedence than the connection assigns (conn.assigns)

Examples

defmodule MyApp.UserController do
  use Phoenix.Controller

  plug :action

  def show(conn, _params) do
    render conn, "show.html", message: "Hello"
  end
end

The example above renders a template “show.html” from the MyApp.UserView and sets the response content type to “text/html”.

In many cases, you may want the template format to be set dynamically based on the request. To do so, you can pass the template name as an atom (without the extension):

def show(conn, _params) do
  render conn, :show, message: "Hello"
end

In order for the example above to work, we need to do content negotiation with the accepts plug before rendering. You can do so by adding the following to your pipeline (in the router):

plug :accepts, ["html"]

Views

By default, Controllers render templates in a view with a similar name to the controller. For example, MyApp.UserController will render templates inside the MyApp.UserView. This information can be changed any time by using render/3, render/4 or the put_view/2 function:

def show(conn, _params) do
  render(conn, MyApp.SpecialView, :show, message: "Hello")
end

def show(conn, _params) do
  conn
  |> put_view(MyApp.SpecialView)
  |> render(:show, message: "Hello")
end

put_view/2 can also be used as a plug:

defmodule MyApp.UserController do
  use Phoenix.Controller

  plug :put_view, MyApp.SpecialView
  plug :action

  def show(conn, _params) do
    render conn, :show, message: "Hello"
  end
end

Layouts

Templates are often rendered inside layouts. By default, Phoenix will render layouts for html requests. For example:

defmodule MyApp.UserController do
  use Phoenix.Controller

  plug :action

  def show(conn, _params) do
    render conn, "show.html", message: "Hello"
  end
end

will render the “show.html” template inside an “application.html” template specified in MyApp.LayoutView. put_layout/2 can be used to change the layout, similar to how put_view/2 can be used to change the view.

layout_formats/2 and put_layout_formats/2 can be used to configure which formats support/require layout rendering (defaults to “html” only).

Source
render(conn, view, template, assigns)

Specs:

  • render(Plug.Conn.t, atom, atom | binary, Dict.t) :: Plug.Conn.t
Source
router_module(conn)

Specs:

  • router_module(Plug.Conn.t) :: atom

Returns the router module as an atom, raises if unavailable.

Source
scrub_params(conn, required_key)

Specs:

  • scrub_params(Plug.Conn.t, [String.t]) :: Plug.Conn.t

Scrubs the parameters from the request.

This process is two-fold:

  • Checks to see if the required_key is present
  • Changes empty parameters of required_key (recursively) to nils

This function is useful to remove empty strings sent via HTML forms. If you are providing an API, there is likely no need to invoke scrub_params/2.

If the required_key is not present, it will raise Phoenix.MissingParamError.

Examples

iex> scrub_params(conn, "user")
Source
text(conn, data)

Specs:

Sends text response.

Examples

iex> text conn, "hello"

iex> text conn, :implements_to_string
Source
view_module(conn)

Specs:

  • view_module(Plug.Conn.t) :: atom

Retrieves the current view.

Source