# Phoenix Fundamentals — Elixir & Phoenix

Source: https://www.geekswithgeeks.com/en/elixir-phoenix/p-phoenix

> Understand Phoenix's request pipeline: endpoint, router, plugs, controllers and components.

## A productive, fast web framework

**Phoenix** is Elixir's main web framework, known for high performance, real-time features and developer productivity. Create a project with `mix phx.new shop_web_app` (it generates Ecto, Tailwind and esbuild setup by default) and start it with `mix phx.server`. A request flows through the **endpoint** (the entry point, handling static files, parsing and sessions), then the **router**, which matches paths and pipes the request through **pipelines** of **plugs** (`:browser` for HTML with sessions and CSRF protection, `:api` for JSON), then to a **controller** action that returns a response. **Plug** is the core abstraction: a function or module that takes a `%Plug.Conn{}` and returns a modified conn, used for authentication, logging and headers. Since Phoenix 1.7, HTML is rendered with **HEEx** templates and **function components**, and routes are checked at compile time with **verified routes** using the `~p` sigil. **Contexts** are plain Elixir modules (such as `Shop.Catalog`) that hold the business logic, keeping controllers thin. Generators such as `mix phx.gen.html`, `mix phx.gen.json` and **`mix phx.gen.auth`** scaffold resources and authentication.

## Phoenix request flow

Endpoint, router pipeline, controller and context, then a rendered response.

![A left-to-right chain of boxes: a globe icon, a funnel of plugs, a router fork, a controller box calling a context box with a database cylinder, and a page icon at the end.](assets/figures/elixir-phoenix/section-6-map.svg) — Figure 6.1 — The Phoenix request pipeline.

## Router, pipeline, plug and controller

A JSON API scope with an authentication plug.

```elixir
# lib/shop_web/router.ex
defmodule ShopWeb.Router do
  use ShopWeb, :router

  pipeline :api do
    plug :accepts, ["json"]
    plug ShopWeb.Plugs.RequireApiKey
  end

  scope "/api", ShopWeb do
    pipe_through :api
    resources "/products", ProductController, only: [:index, :show]
  end
end

# lib/shop_web/plugs/require_api_key.ex
defmodule ShopWeb.Plugs.RequireApiKey do
  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    case get_req_header(conn, "x-api-key") do
      [key] when key != "" -> assign(conn, :api_key, key)
      _ -> conn |> send_resp(401, "missing API key") |> halt()
    end
  end
end

# lib/shop_web/controllers/product_controller.ex
defmodule ShopWeb.ProductController do
  use ShopWeb, :controller
  alias Shop.Catalog

  def index(conn, _params), do: json(conn, %{data: Catalog.list_products()})

  def show(conn, %{"id" => id}) do
    case Catalog.get_product(id) do
      nil -> conn |> put_status(:not_found) |> json(%{error: "not found"})
      product -> json(conn, %{data: product})
    end
  end
end
```

## Keep controllers thin

Controllers translate HTTP into calls to contexts and back. Business rules belong in contexts, so they can be reused from LiveViews, background jobs and tests without a web request.

**Quiz:** What is a plug in Phoenix?

- [ ] A database adapter
- [ ] A CSS framework
- [x] A function or module that receives a Plug.Conn and returns a (possibly modified) conn
- [ ] A type of process

*Answer:* A function or module that receives a Plug.Conn and returns a (possibly modified) conn. Plugs form the composable request pipeline.
