iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 7
1

接續昨天的進度,現在我們有一個乾淨的Phoenix專案
首先來新增一個靜態頁面

新增路由 (Router)

打開lib/hello_phoenix/web/router.ex
這個檔案是專案的路由
所謂的路由,就是決定網址如何對應到程式的對照表
通常是對照到控制器(controller)(在Django就是對照到View)

defmodule HelloWeb.Router do
  use HelloWeb, :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 "/", HelloWeb do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
  end

  # Other scopes may use custom stacks.
  # scope "/api", HelloWeb do
  #   pipe_through :api
  # end
end

如果你大致瀏覽一下,可能會注意到pipeline :browserpipeline :api
我個人認為這是相當好的發明
因為這邊算是新手指引,所以先不解釋太多
簡言之,就是讓透過瀏覽器與API兩種不同的進入專案模式可以做不同的處理
後面有機會再詳細說明。

我們讀到這一行get "/", PageController, :index
這就是我們看到的預設首頁的路由
我覺得能看到是蠻好的,有助於新手了解來龍去脈
像是Rails的預設首頁路由與內容都是藏在底層運作
也難怪很多人會說Rails充滿著黑魔法(不知道為什麼,但是會動)

要新增頁面,我們先建立一個路由
在首頁的路由下面新增這樣一行:get "/hello", HelloController, :index
如果你之前碰過任何一種現代網站框架,你大概就已經能理解這一行在講什麼:
GET方法訪問 http://localhost:4000/hello 的時候
對應到HelloControllerindex方法
也就是上面提到的網址與控制器的對應關係

順帶一提,透過在瀏覽器輸入網址的訪問,就是GET方法
如果要模擬POST或其他方法(通常是測試API時),可以透過一些工具

新增控制器 (Controller)

很遺憾的,當你新增完路由以後,controller不會自己產生
你可以透過指令或是手動新增檔案,這邊我們先手動新增
建立lib/hello_phoenix/web/controllers/hello_controller.ex
然後把下面內容複製貼上:

# hello_controller.ex
defmodule HelloWeb.HelloController do
  use HelloWeb, :controller

  def index(conn, _params) do
    render conn, "index.html"
  end
end

這邊稍微說明一下命名慣例
你可能會好奇為什麼在路由與程式內我們使用HelloController
但是檔案名稱卻是hello_controller
沒有為什麼,這就是慣例(XD)
首字大寫的組合叫做「駝峰式命名」(Upper Camel Case)
也可稱為「帕斯卡命名」(Pascal Case)
另外一種全小寫,用底線連結的我不知道怎麼稱呼(如果你知道請告訴我!)

如果你符合慣例,程式就會自動找到對應的檔案
這樣的慣例在Rails也相同
如果你硬要不符合慣例,也可以在後面指定路徑讓程式知道去哪裡找
但是建議千萬不要這麼做,只是增加維護的困擾

新增View

新增完controller後,我們接下來新增對應的view
請在 lib/hello_web/views/hello_view.ex這個位置
複製貼上下方的程式碼:

defmodule HelloWeb.HelloView do
  use HelloWeb, :view
end

新增 Template

最後在 lib/hello_phoenix/web/templates新增一個新的資料夾 hello
在裡面新增一個檔案 index.html.eex,複製貼上:

<div class="jumbotron">
  <h2>Hello World, from Phoenix!</h2>
</div>

然後在瀏覽器輸入 http://localhost:4000/hello
你就可以看到
new page

在Phoenix修改程式,是不需要重新啟動伺服器的
這一點相當方便

新增一個接收參數的頁面

現在我們新增另外一個頁面,可以從網址接收參數
首先打開路由,在剛剛的hello下新增一行:

scope "/", HelloWeb do
  pipe_through :browser # Use the default browser stack.

  get "/", PageController, :index
  get "/hello", HelloController, :index
  get "/hello/:messenger", HelloController, :show
end

接著到剛剛的hello_controller.ex新增show方法:

def show(conn, %{"messenger" => messenger}) do
  render conn, "show.html", messenger: messenger
end

最後一個動作,在剛剛的hello資料夾下新增一個show.html.eex

<div class="jumbotron">
  <h2>Hello World, from <%= @messenger %>!</h2>
</div>

好了!現在如果我們打開瀏覽器,輸入 http://localhost:4000/hello/bater
welcome bater

基本上在hello後面的參數不管接什麼名字,都會呈現在畫面上

現在回頭說明一下什麼是 *.html.eex
eex就是Elixir會事先編譯的文件,前面有html
代表是Elixir編譯過後會產生HTML
在這樣的文件內可使用Elixir語法,跟Ruby的erb一模一樣

  • <%= %> 這樣的開頭結尾之中的Elixir語法會執行,而且會輸出
  • <% %> 這樣也會執行,但是不會輸出

Router

剛剛新增了兩條新路由,你可能還沒有感覺
但之後如果每次有新的功能就要新增一次路由
感覺非常麻煩
所以Phoenix跟Rails一樣有resources 懶人工具
他會一次幫你產生八個常用到的路由
比如說:

resources "/users", UserController

他會自動產生下面的路由

user_path  GET     /users           HelloPhoenix.UserController :index
user_path  GET     /users/:id/edit  HelloPhoenix.UserController :edit
user_path  GET     /users/new       HelloPhoenix.UserController :new
user_path  GET     /users/:id       HelloPhoenix.UserController :show
user_path  POST    /users           HelloPhoenix.UserController :create
user_path  PATCH   /users/:id       HelloPhoenix.UserController :update
           PUT     /users/:id       HelloPhoenix.UserController :update
user_path  DELETE  /users/:id       HelloPhoenix.UserController :delete

順帶一提,如果你想查詢目前有什麼路由,指令是:

$ mix phoenix.routes

相當於Rails的

$ rake routes

恩,Rails還是比較簡短優雅呀!

當然,如果你用不到這麼多
與Rails相同,這邊也是支援onlyexcept
假如你輸入 resources "posts", PostController, only: [:index, :show]
那麼就只會產生:

post_path  GET     /posts HelloPhoenix.PostController :index
post_path  GET     /posts/:id HelloPhoenix.PostController :show

resources也支援套疊,後面scope與指定controller方法都與rails大同小異
實在沒有動力複製貼上
有興趣的朋友在需要用到時可以查詢用法
(看Rails的路由教學可能也有相同的效果XD)


上一篇
Phoenix起步走:環境安裝與建立專案
下一篇
Phoenix起步走:ORM與 Schema、Migrate
系列文
新時代的網頁框架比較-- 淺談Rails、Django、Phoenix、Laravel31

1 則留言

0
Bater
iT邦新手 5 級 ‧ 2018-01-03 15:12:25

全小寫用底線連接的命名方式稱為蛇型命名(snake_case)

我要留言

立即登入留言