Phoenix.Controller

Parsed documentation:
View on GitHub
Controllers are used to group common functionality in the same
(pluggable) module.

For example, the route:

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

will invoke the `show/2` action in the `MyAppWeb.UserController`:

    defmodule MyAppWeb.UserController do
      use MyAppWeb, :controller

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

An action is 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.

## Options

When used, the controller supports the following options:

  * `:namespace` - sets the namespace to properly inflect
    the layout view. By default it uses the base alias
    in your controller name

  * `:log` - the level to log. When false, disables controller
    logging

## Connection

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

Those functions are imported from two modules:

  * `Plug.Conn` - a collection of low-level functions to work with
    the connection

  * `Phoenix.Controller` - functions provided by Phoenix
    to support rendering, and other Phoenix specific behaviour

If you want to have functions that manipulate the connection
without fully implementing the controller, you can import both
modules directly instead of `use Phoenix.Controller`.

## Plug pipeline

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

    defmodule MyAppWeb.UserController do
      use MyAppWeb, :controller

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

      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(to: "/") |> halt()
        end
      end
    end

The `:authenticate` plug will be invoked before the action. If the
plug calls `Plug.Conn.halt/1` (which is by default imported into
controllers), it will halt the pipeline and won't invoke the action.

### Guards

`plug/2` in controllers supports guards, allowing a developer to configure
a plug to only run in some particular action:

    plug :authenticate, [usernames: ["jose", "eric", "sonny"]] when action in [:show, :edit]
    plug :authenticate, [usernames: ["admin"]] when not action in [:index]

The first plug will run only when action is show or edit. The second plug will
always run, except for the index action.

Those guards work like regular Elixir guards and the only variables accessible
in the guard are `conn`, the `action` as an atom and the `controller` as an
alias.

## Controllers are plugs

Like routers, controllers are plugs, but they are wired to dispatch
to a particular function which is called an action.

For example, the route:

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

will invoke `UserController` as a plug:

    UserController.call(conn, :show)

which will trigger the plug pipeline and which will eventually
invoke the inner action plug that dispatches to the `show/2`
function in the `UserController`.

As controllers are plugs, they implement both `init/1` and
`call/2`, and it also provides a function named `action/2`
which is responsible for dispatching the appropriate action
after the plug stack (and is also overridable).

### Overriding `action/2` for custom arguments

Phoenix injects an `action/2` plug in your controller which calls the
function matched from the router. By default, it passes the conn and params.
In some cases, overriding the `action/2` plug in your controller is a
useful way to inject arguments into your actions that you would otherwise
need to fetch of the connection repeatedly. For example, imagine if you
stored a `conn.assigns.current_user` in the connection and wanted quick
access to the user for every action in your controller:

    def action(conn, _) do
      args = [conn, conn.params, conn.assigns.current_user]
      apply(__MODULE__, action_name(conn), args)
    end

    def index(conn, _params, user) do
      videos = Repo.all(user_videos(user))
      # ...
    end

    def delete(conn, %{"id" => id}, user) do
      video = Repo.get!(user_videos(user), id)
      # ...
    end

## Rendering and layouts

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

It is also important not to confuse `Phoenix.Controller.render/3`
with `Phoenix.View.render/3`. The former expects
a connection and relies on content negotiation while the latter is
connection-agnostic and typically invoked from your views.
No suggestions.
Please help! Open an issue on GitHub if this assessment is incorrect.